diff options
Diffstat (limited to 'tools/mapedit/src/object.cpp')
| -rw-r--r-- | tools/mapedit/src/object.cpp | 304 |
1 files changed, 254 insertions, 50 deletions
| diff --git a/tools/mapedit/src/object.cpp b/tools/mapedit/src/object.cpp index a783691..8ed29af 100644 --- a/tools/mapedit/src/object.cpp +++ b/tools/mapedit/src/object.cpp | |||
| @@ -2,29 +2,130 @@ | |||
| 2 | #include <dirent.h> | 2 | #include <dirent.h> |
| 3 | #include <libxml/parser.h> | 3 | #include <libxml/parser.h> |
| 4 | #include <memory> | 4 | #include <memory> |
| 5 | #include "world.h" | ||
| 5 | 6 | ||
| 6 | static std::map<std::string, std::shared_ptr<MapObject>> allObjects; | 7 | static std::map<std::string, MapObject> allObjects; |
| 7 | static bool objsInit = false; | 8 | static bool objsInit = false; |
| 8 | 9 | ||
| 9 | const std::map<std::string, std::shared_ptr<MapObject>> MapObject::getAllObjects() | 10 | const std::map<std::string, MapObject>& MapObject::getAllObjects() |
| 10 | { | 11 | { |
| 11 | if (!objsInit) | 12 | if (!objsInit) |
| 12 | { | 13 | { |
| 13 | DIR* dir = opendir("entities/"); | 14 | try |
| 14 | if (dir != NULL) | ||
| 15 | { | 15 | { |
| 16 | struct dirent* ent; | 16 | xmlDocPtr doc = xmlParseFile("res/entities.xml"); |
| 17 | while ((ent = readdir(dir)) != NULL) | 17 | if (doc == nullptr) |
| 18 | { | 18 | { |
| 19 | std::string path = ent->d_name; | 19 | throw MapObjectLoadException("can't open file"); |
| 20 | if ((path.length() >= 4) && (path.substr(path.length() - 4, 4) == ".xml")) | 20 | } |
| 21 | |||
| 22 | xmlNodePtr top = xmlDocGetRootElement(doc); | ||
| 23 | if (top == nullptr) | ||
| 24 | { | ||
| 25 | throw MapObjectLoadException("missing root element"); | ||
| 26 | } | ||
| 27 | |||
| 28 | if (xmlStrcmp(top->name, (const xmlChar*) "entities")) | ||
| 29 | { | ||
| 30 | throw MapObjectLoadException("root element is not entities"); | ||
| 31 | } | ||
| 32 | |||
| 33 | for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) | ||
| 34 | { | ||
| 35 | if (!xmlStrcmp(node->name, (const xmlChar*) "entity")) | ||
| 21 | { | 36 | { |
| 22 | std::string name = path.substr(0, path.length() - 4); | 37 | xmlChar* idKey = xmlGetProp(node, (xmlChar*) "id"); |
| 23 | auto obj = std::make_shared<MapObject>(name.c_str()); | 38 | if (idKey == 0) throw MapObjectLoadException("entity missing id"); |
| 24 | 39 | std::string theID = (char*) idKey; | |
| 25 | allObjects[name] = obj; | 40 | xmlFree(idKey); |
| 41 | |||
| 42 | allObjects.emplace(theID, theID); | ||
| 43 | MapObject& mapObject = allObjects.at(theID); | ||
| 44 | |||
| 45 | xmlChar* nameKey = xmlGetProp(node, (xmlChar*) "name"); | ||
| 46 | if (nameKey == 0) throw MapObjectLoadException("entity missing name"); | ||
| 47 | mapObject.name = (char*) nameKey; | ||
| 48 | xmlFree(nameKey); | ||
| 49 | |||
| 50 | xmlChar* spriteKey = xmlGetProp(node, (xmlChar*) "sprite"); | ||
| 51 | if (spriteKey == 0) throw MapObjectLoadException("entity missing sprite"); | ||
| 52 | mapObject.sprite = wxImage((char*) spriteKey); | ||
| 53 | xmlFree(spriteKey); | ||
| 54 | |||
| 55 | xmlChar* widthKey = xmlGetProp(node, (xmlChar*) "width"); | ||
| 56 | if (widthKey == 0) throw MapObjectLoadException("entity missing width"); | ||
| 57 | mapObject.width = atoi((char*) widthKey); | ||
| 58 | xmlFree(widthKey); | ||
| 59 | |||
| 60 | xmlChar* heightKey = xmlGetProp(node, (xmlChar*) "height"); | ||
| 61 | if (heightKey == 0) throw MapObjectLoadException("entity missing height"); | ||
| 62 | mapObject.height = atoi((char*) heightKey); | ||
| 63 | xmlFree(heightKey); | ||
| 64 | |||
| 65 | for (xmlNodePtr entityNode = node->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next) | ||
| 66 | { | ||
| 67 | if (!xmlStrcmp(entityNode->name, (const xmlChar*) "input")) | ||
| 68 | { | ||
| 69 | xmlChar* key = xmlGetProp(entityNode, (xmlChar*) "id"); | ||
| 70 | if (key == 0) throw MapObjectLoadException("input missing id"); | ||
| 71 | std::string inputID = (char*) key; | ||
| 72 | xmlFree(key); | ||
| 73 | |||
| 74 | Input& input = mapObject.inputs[inputID]; | ||
| 75 | |||
| 76 | key = xmlGetProp(entityNode, (xmlChar*) "name"); | ||
| 77 | if (key == 0) throw MapObjectLoadException("input missing name"); | ||
| 78 | input.name = (char*) key; | ||
| 79 | xmlFree(key); | ||
| 80 | |||
| 81 | key = xmlGetProp(entityNode, (xmlChar*) "type"); | ||
| 82 | if (key == 0) throw MapObjectLoadException("input missing type"); | ||
| 83 | std::string inputType = (char*) key; | ||
| 84 | xmlFree(key); | ||
| 85 | |||
| 86 | if (inputType == "choice") | ||
| 87 | { | ||
| 88 | input.type = Input::Type::Choice; | ||
| 89 | |||
| 90 | for (xmlNodePtr choiceNode = entityNode->xmlChildrenNode; choiceNode != NULL; choiceNode = choiceNode->next) | ||
| 91 | { | ||
| 92 | if (!xmlStrcmp(choiceNode->name, (xmlChar*) "value")) | ||
| 93 | { | ||
| 94 | key = xmlGetProp(choiceNode, (xmlChar*) "id"); | ||
| 95 | if (key == 0) throw MapObjectLoadException("input value missing id"); | ||
| 96 | int valueId = atoi((char*) key); | ||
| 97 | xmlFree(key); | ||
| 98 | |||
| 99 | key = xmlNodeGetContent(choiceNode); | ||
| 100 | if (key == 0) throw MapObjectLoadException("input value missing content"); | ||
| 101 | std::string choiceText = (char*) key; | ||
| 102 | xmlFree(key); | ||
| 103 | |||
| 104 | input.choices[valueId] = choiceText; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | } else if (inputType == "slider") | ||
| 108 | { | ||
| 109 | input.type = Input::Type::Slider; | ||
| 110 | |||
| 111 | key = xmlGetProp(entityNode, (xmlChar*) "minvalue"); | ||
| 112 | if (key == 0) throw MapObjectLoadException("integer input missing minvalue"); | ||
| 113 | input.minvalue = atoi((char*) key); | ||
| 114 | xmlFree(key); | ||
| 115 | |||
| 116 | key = xmlGetProp(entityNode, (xmlChar*) "maxvalue"); | ||
| 117 | if (key == 0) throw MapObjectLoadException("integer input missing maxvalue"); | ||
| 118 | input.maxvalue = atoi((char*) key); | ||
| 119 | xmlFree(key); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 26 | } | 123 | } |
| 27 | } | 124 | } |
| 125 | } catch (std::exception& ex) | ||
| 126 | { | ||
| 127 | wxMessageBox(ex.what(), "Error loading objects", wxOK | wxCENTRE | wxICON_ERROR); | ||
| 128 | exit(3); | ||
| 28 | } | 129 | } |
| 29 | 130 | ||
| 30 | objsInit = true; | 131 | objsInit = true; |
| @@ -33,67 +134,170 @@ const std::map<std::string, std::shared_ptr<MapObject>> MapObject::getAllObjects | |||
| 33 | return allObjects; | 134 | return allObjects; |
| 34 | } | 135 | } |
| 35 | 136 | ||
| 36 | MapObject::MapObject(const char* filename) | 137 | MapObject::MapObject(std::string id) : id(id) |
| 37 | { | 138 | { |
| 38 | type = filename; | ||
| 39 | 139 | ||
| 40 | xmlDocPtr doc = xmlParseFile(("entities/" + std::string(filename) + ".xml").c_str()); | 140 | } |
| 41 | if (doc == nullptr) throw MapObjectLoadException(filename); | ||
| 42 | 141 | ||
| 43 | xmlNodePtr top = xmlDocGetRootElement(doc); | 142 | std::string MapObject::getID() const |
| 44 | if (top == nullptr) throw MapObjectLoadException(filename); | 143 | { |
| 144 | return id; | ||
| 145 | } | ||
| 45 | 146 | ||
| 46 | if (xmlStrcmp(top->name, (const xmlChar*) "entity-def")) | 147 | std::string MapObject::getName() const |
| 47 | { | 148 | { |
| 48 | throw MapObjectLoadException(filename); | 149 | return name; |
| 49 | } | 150 | } |
| 151 | |||
| 152 | wxBitmap MapObject::getSprite() const | ||
| 153 | { | ||
| 154 | return sprite; | ||
| 155 | } | ||
| 156 | |||
| 157 | int MapObject::getWidth() const | ||
| 158 | { | ||
| 159 | return width; | ||
| 160 | } | ||
| 161 | |||
| 162 | int MapObject::getHeight() const | ||
| 163 | { | ||
| 164 | return height; | ||
| 165 | } | ||
| 166 | |||
| 167 | const std::map<std::string, MapObject::Input>& MapObject::getInputs() const | ||
| 168 | { | ||
| 169 | return inputs; | ||
| 170 | } | ||
| 171 | |||
| 172 | const MapObject::Input& MapObject::getInput(std::string id) const | ||
| 173 | { | ||
| 174 | return inputs.at(id); | ||
| 175 | } | ||
| 176 | |||
| 177 | bool MapObject::operator==(const MapObject& other) const | ||
| 178 | { | ||
| 179 | return id == other.id; | ||
| 180 | } | ||
| 181 | |||
| 182 | bool MapObject::operator!=(const MapObject& other) const | ||
| 183 | { | ||
| 184 | return id != other.id; | ||
| 185 | } | ||
| 186 | |||
| 187 | MapObjectEntry::MapObjectEntry(const MapObject& object, int posx, int posy) : object(object) | ||
| 188 | { | ||
| 189 | position = std::make_pair(posx, posy); | ||
| 190 | } | ||
| 191 | |||
| 192 | const MapObject& MapObjectEntry::getObject() const | ||
| 193 | { | ||
| 194 | return object; | ||
| 195 | } | ||
| 196 | |||
| 197 | std::pair<int, int> MapObjectEntry::getPosition() const | ||
| 198 | { | ||
| 199 | return position; | ||
| 200 | } | ||
| 201 | |||
| 202 | MapObjectEntry::Item& MapObjectEntry::getItem(std::string str) | ||
| 203 | { | ||
| 204 | return items[str]; | ||
| 205 | } | ||
| 206 | |||
| 207 | const std::map<std::string, MapObjectEntry::Item>& MapObjectEntry::getItems() const | ||
| 208 | { | ||
| 209 | return items; | ||
| 210 | } | ||
| 211 | |||
| 212 | void MapObjectEntry::addItem(std::string id, Item& item) | ||
| 213 | { | ||
| 214 | items[id] = item; | ||
| 215 | } | ||
| 216 | |||
| 217 | void MapObjectEntry::setPosition(int x, int y) | ||
| 218 | { | ||
| 219 | position = std::make_pair(x, y); | ||
| 220 | } | ||
| 221 | |||
| 222 | bool MapObjectEntry::operator==(const MapObjectEntry& other) const | ||
| 223 | { | ||
| 224 | return (object == other.object) && (position == other.position); | ||
| 225 | } | ||
| 226 | |||
| 227 | bool MapObjectEntry::operator!=(const MapObjectEntry& other) const | ||
| 228 | { | ||
| 229 | return (object != other.object) && (position != other.position); | ||
| 230 | } | ||
| 231 | |||
| 232 | VariableChoiceValidator::VariableChoiceValidator(World& world, MapObjectEntry::Item& item) : world(world), item(item) | ||
| 233 | { | ||
| 234 | |||
| 235 | } | ||
| 50 | 236 | ||
| 51 | for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) | 237 | wxObject* VariableChoiceValidator::Clone() const |
| 238 | { | ||
| 239 | return new VariableChoiceValidator(world, item); | ||
| 240 | } | ||
| 241 | |||
| 242 | bool VariableChoiceValidator::TransferFromWindow() | ||
| 243 | { | ||
| 244 | wxChoice* choice = (wxChoice*) GetWindow(); | ||
| 245 | int sel = choice->GetSelection(); | ||
| 246 | int val = (intptr_t) choice->GetClientData(sel); | ||
| 247 | item.intvalue = val; | ||
| 248 | world.setDirty(true); | ||
| 249 | |||
| 250 | return true; | ||
| 251 | } | ||
| 252 | |||
| 253 | bool VariableChoiceValidator::TransferToWindow() | ||
| 254 | { | ||
| 255 | wxChoice* choice = (wxChoice*) GetWindow(); | ||
| 256 | for (size_t i=0; i<choice->GetCount(); i++) | ||
| 52 | { | 257 | { |
| 53 | if (!xmlStrcmp(node->name, (const xmlChar*) "sprite")) | 258 | if ((intptr_t) choice->GetClientData(i) == item.intvalue) |
| 54 | { | ||
| 55 | xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); | ||
| 56 | std::string spriteFile = (char*) key; | ||
| 57 | xmlFree(key); | ||
| 58 | |||
| 59 | sprite = wxImage(spriteFile); | ||
| 60 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "action")) | ||
| 61 | { | 259 | { |
| 62 | xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); | 260 | choice->SetSelection(i); |
| 63 | action = (char*) key; | 261 | return true; |
| 64 | xmlFree(key); | ||
| 65 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "size")) | ||
| 66 | { | ||
| 67 | xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); | ||
| 68 | sscanf((char*) key, "%d,%d", &width, &height); | ||
| 69 | xmlFree(key); | ||
| 70 | } | 262 | } |
| 71 | } | 263 | } |
| 264 | |||
| 265 | return false; | ||
| 266 | } | ||
| 72 | 267 | ||
| 73 | xmlFreeDoc(doc); | 268 | bool VariableChoiceValidator::Validate(wxWindow*) |
| 269 | { | ||
| 270 | return true; | ||
| 74 | } | 271 | } |
| 75 | 272 | ||
| 76 | wxBitmap MapObject::getSprite() const | 273 | SliderItemValidator::SliderItemValidator(World& world, MapObjectEntry::Item& item) : world(world), item(item) |
| 77 | { | 274 | { |
| 78 | return sprite; | 275 | |
| 79 | } | 276 | } |
| 80 | 277 | ||
| 81 | std::string MapObject::getAction() const | 278 | wxObject* SliderItemValidator::Clone() const |
| 82 | { | 279 | { |
| 83 | return action; | 280 | return new SliderItemValidator(world, item); |
| 84 | } | 281 | } |
| 85 | 282 | ||
| 86 | int MapObject::getWidth() const | 283 | bool SliderItemValidator::TransferFromWindow() |
| 87 | { | 284 | { |
| 88 | return width; | 285 | wxSlider* slider = (wxSlider*) GetWindow(); |
| 286 | item.intvalue = slider->GetValue(); | ||
| 287 | world.setDirty(true); | ||
| 288 | |||
| 289 | return true; | ||
| 89 | } | 290 | } |
| 90 | 291 | ||
| 91 | int MapObject::getHeight() const | 292 | bool SliderItemValidator::TransferToWindow() |
| 92 | { | 293 | { |
| 93 | return height; | 294 | wxSlider* slider = (wxSlider*) GetWindow(); |
| 295 | slider->SetValue(item.intvalue); | ||
| 296 | |||
| 297 | return true; | ||
| 94 | } | 298 | } |
| 95 | 299 | ||
| 96 | std::string MapObject::getType() const | 300 | bool SliderItemValidator::Validate(wxWindow*) |
| 97 | { | 301 | { |
| 98 | return type; | 302 | return true; |
| 99 | } | 303 | } |
