2 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "sprite/sprite_data.hpp"
22 #include "lisp/list_iterator.hpp"
23 #include "util/log.hpp"
24 #include "util/reader.hpp"
26 SpriteData::Action::Action() :
44 SpriteData::Action::~Action()
46 for(std::vector<Surface*>::iterator i = surfaces.begin();
47 i != surfaces.end(); ++i)
51 SpriteData::SpriteData(const Reader& lisp, const std::string& basedir) :
55 lisp::ListIterator iter(&lisp);
57 if(iter.item() == "name") {
58 iter.value()->get(name);
59 } else if(iter.item() == "action") {
60 parse_action(*iter.lisp(), basedir);
62 log_warning << "Unknown sprite field: " << iter.item() << std::endl;
66 throw std::runtime_error("Error: Sprite without actions.");
69 SpriteData::~SpriteData()
71 for(Actions::iterator i=actions.begin(); i != actions.end(); ++i)
76 SpriteData::parse_action(const Reader& lisp, const std::string& basedir)
78 Action* action = new Action;
80 if(!lisp.get("name", action->name)) {
82 throw std::runtime_error(
83 "If there are more than one action, they need names!");
85 std::vector<float> hitbox;
86 if (lisp.get("hitbox", hitbox)) {
87 switch(hitbox.size()) {
89 action->hitbox_h = hitbox[3];
90 action->hitbox_w = hitbox[2];
94 action->y_offset = hitbox[1];
95 action->x_offset = hitbox[0];
99 throw std::runtime_error("hitbox should specify 2/4 coordinates");
102 lisp.get("z-order", action->z_order);
103 lisp.get("fps", action->fps);
105 std::string mirror_action;
106 lisp.get("mirror-action", mirror_action);
107 if(!mirror_action.empty()) {
108 Action* act_tmp = get_action(mirror_action);
109 if(act_tmp == NULL) {
110 throw std::runtime_error("Could not mirror action. Action not found.\n"
111 "Mirror actions must be defined after the real one!");
115 for(int i = 0; static_cast<unsigned int>(i) < act_tmp->surfaces.size(); i++) {
116 Surface* surface = new Surface(*(act_tmp->surfaces[i]));
118 max_w = std::max(max_w, (float) surface->get_width());
119 max_h = std::max(max_h, (float) surface->get_height());
120 action->surfaces.push_back(surface);
122 if (action->hitbox_w < 1) action->hitbox_w = max_w - action->x_offset;
123 if (action->hitbox_h < 1) action->hitbox_h = max_h - action->y_offset;
125 } else { // Load images
126 std::vector<std::string> images;
127 if(!lisp.get("images", images)) {
128 std::stringstream msg;
129 msg << "Sprite '" << name << "' contains no images in action '"
130 << action->name << "'.";
131 throw std::runtime_error(msg.str());
136 for(std::vector<std::string>::size_type i = 0; i < images.size(); i++) {
137 Surface* surface = new Surface(basedir + images[i]);
138 max_w = std::max(max_w, (float) surface->get_width());
139 max_h = std::max(max_h, (float) surface->get_height());
140 action->surfaces.push_back(surface);
142 if (action->hitbox_w < 1) action->hitbox_w = max_w - action->x_offset;
143 if (action->hitbox_h < 1) action->hitbox_h = max_h - action->y_offset;
145 actions[action->name] = action;
149 SpriteData::get_action(std::string act)
151 Actions::iterator i = actions.find(act);
152 if(i == actions.end()) {