12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235 |
- /* GCSx
- ** WORLDEDIT.CPP
- **
- ** World storage
- ** EDITOR members
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- set<WorldEdit*>* WorldEdit::allWorlds = NULL;
- WorldEdit::WorldEdit() throw_File : World(), layersById(), spawnsById(), foldersById(), undo(this) { start_func
- headerModified = 1; // We have a title!
- contentModified = 1;
- browserNode = NULL;
- saveFile = NULL;
- file = saveFile = new WorldFile(); // Only exception point
-
- saveFile->newBlock(WorldFile::BLOCKTYPE_WORLDINFO, this);
- if (!allWorlds) allWorlds = new set<WorldEdit*>;
- allWorlds->insert(this);
- desktop->broadcastObjChange(OBJ_WORLD | OBJMOD_CREATE, this, 0, 0);
- }
- WorldEdit::WorldEdit(const char* wFilename) throw_File : World(), layersById(), spawnsById(), undo(this) { start_func
- headerModified = contentModified = 0;
- browserNode = NULL;
- saveFile = NULL;
- filename = NULL;
- TileSetEdit* tileset = NULL;
- SceneEdit* scene = NULL;
- AnimGroupEdit* animgroup = NULL;
- ScriptEdit* script = NULL;
- FolderEdit* folder = NULL;
- try {
- filename = new string(wFilename);
- file = saveFile = new WorldFile(filename); // One of many exception points (+claimBlocks)
- Uint32 type;
- Uint32 id;
- // Loop pass 1- World Info and TileSets
- saveFile->scanBlocks();
- while (saveFile->nextBlock(&type, &id)) {
- switch (type) {
- case WorldFileLoad::BLOCKTYPE_WORLDINFO:
- saveFile->claimBlock(id, this);
- break;
- case WorldFileLoad::BLOCKTYPE_TILESET:
- tileset = new TileSetEdit(this, 0);
- saveFile->claimBlock(id, tileset);
- indexTileSet(tileset);
- tileset = NULL;
- break;
- }
- }
- // Loop pass 2- Scenes and Animation Groups (need tilesets)
- saveFile->scanBlocks();
- while (saveFile->nextBlock(&type, &id)) {
- switch (type) {
- case WorldFileLoad::BLOCKTYPE_ANIMGROUP:
- animgroup = new AnimGroupEdit(this);
- saveFile->claimBlock(id, animgroup);
- indexAnimGroup(animgroup);
- animgroup = NULL;
- break;
- }
- }
-
- // Loop pass 3- Scripts (need tilesets/animgroups)
- saveFile->scanBlocks();
- while (saveFile->nextBlock(&type, &id)) {
- switch (type) {
- case WorldFileLoad::BLOCKTYPE_SCRIPT:
- script = new ScriptEdit(this);
- saveFile->claimBlock(id, script);
- indexScript(script);
- script = NULL;
- break;
- }
- }
- // Loop pass 4- Scenes (need tilesets/animgroups/scripts for spawns)
- saveFile->scanBlocks();
- while (saveFile->nextBlock(&type, &id)) {
- switch (type) {
- case WorldFileLoad::BLOCKTYPE_SCENE:
- scene = new SceneEdit(this);
- saveFile->claimBlock(id, scene);
- indexScene(scene);
- scene = NULL;
- break;
- }
- }
-
- // Loop pass 5- Folders (need all items that might go in a folder)
- saveFile->scanBlocks();
- while (saveFile->nextBlock(&type, &id)) {
- switch (type) {
- case WorldFileLoad::BLOCKTYPE_FOLDER:
- folder = new FolderEdit(this);
- saveFile->claimBlock(id, folder);
- indexFolder(folder);
- folder = NULL;
- break;
- }
- }
- if (!allWorlds) allWorlds = new set<WorldEdit*>;
- allWorlds->insert(this);
- }
- catch (...) {
- // Temporaries
- delete tileset;
- delete scene;
- delete animgroup;
- delete script;
- delete folder;
-
- // Collections
- deleteCollections();
-
- // File
- delete saveFile;
- delete filename;
- file = saveFile = NULL;
- filename = NULL;
- throw;
- }
- desktop->broadcastObjChange(OBJ_WORLD | OBJMOD_CREATE, this, 0, 0);
- }
- WorldEdit::~WorldEdit() { start_func
- // May not be needed, but a good safety
- desktop->broadcastObjChange(OBJ_WORLD | OBJMOD_DELETE, this, 0, 0);
- // Our node must be deleted outside this destructor
-
- if (allWorlds) {
- allWorlds->erase(this);
- if (allWorlds->empty()) {
- delete allWorlds;
- allWorlds = NULL;
- }
- }
- }
- void WorldEdit::addToBrowser(TreeView* worldBrowser) { start_func
- TreeView* myNode = new TreeView(title, this, TREEVIEW_WORLD, treeviewEventWrap);
- myNode->setIcon(3);
- TreeView* subNode = NULL;
- TreeView* subAddNode = NULL;
- TileSetIndex::iterator tilesetPos;
- TileSetIndex::iterator tilesetEnd = tilesetsById.end();
- SceneIndex::iterator scenePos;
- SceneIndex::iterator sceneEnd = scenesById.end();
- AnimGroupIndex::iterator animgroupPos;
- AnimGroupIndex::iterator animgroupEnd = animgroupsById.end();
- ScriptIndex::iterator scriptPos;
- ScriptIndex::iterator scriptEnd = scriptsById.end();
- FolderIndex::iterator folderPos;
- FolderIndex::iterator folderEnd = foldersById.end();
-
- myNode->expand(1);
-
- subNode = new TreeView("Images", this, TREEVIEW_TILESET, treeviewEventWrap);
- subNode->setIcon(1, 0);
- // Add existing libraries
- for (tilesetPos = tilesetsById.begin(); tilesetPos != tilesetEnd; ++tilesetPos) {
- if (!(*tilesetPos).second->getIsFont()) {
- dynamic_cast<TileSetEdit*>((*tilesetPos).second)->addToBrowser(subNode, 0);
- }
- }
- myNode->insert(subNode, 0);
-
- subNode = new TreeView("Fonts", this, TREEVIEW_FONT, treeviewEventWrap);
- subNode->setIcon(1, 0);
- // Add existing libraries
- for (tilesetPos = tilesetsById.begin(); tilesetPos != tilesetEnd; ++tilesetPos) {
- if ((*tilesetPos).second->getIsFont()) {
- dynamic_cast<TileSetEdit*>((*tilesetPos).second)->addToBrowser(subNode, 0);
- }
- }
- myNode->insert(subNode, 0);
-
- subNode = new TreeView("Scenes", this, TREEVIEW_SCENE, treeviewEventWrap);
- subNode->setIcon(1, 0);
- // Add existing scenes
- for (scenePos = scenesById.begin(); scenePos != sceneEnd; ++scenePos) {
- (dynamic_cast<SceneEdit*>((*scenePos).second))->addToBrowser(subNode, 0);
- }
- myNode->insert(subNode, 0);
-
- subNode = new TreeView("Scripts", this, TREEVIEW_SCRIPT, treeviewEventWrap);
- subNode->setIcon(1, 0);
- // Add existing scripts
- for (scriptPos = scriptsById.begin(); scriptPos != scriptEnd; ++scriptPos) {
- if ((*scriptPos).second->getType() != Script::SCRIPT_NOTE) {
- dynamic_cast<ScriptEdit*>((*scriptPos).second)->addToBrowser(subNode, 0);
- }
- }
- myNode->insert(subNode, 0);
-
- subNode = new TreeView("Animations", this, TREEVIEW_ANIMGROUP, treeviewEventWrap);
- subNode->setIcon(1, 0);
- // Add existing spite libraries
- for (animgroupPos = animgroupsById.begin(); animgroupPos != animgroupEnd; ++animgroupPos) {
- dynamic_cast<AnimGroupEdit*>((*animgroupPos).second)->addToBrowser(subNode, 0);
- }
- myNode->insert(subNode, 0);
- subNode = new TreeView("Notes", this, TREEVIEW_NOTES, treeviewEventWrap);
- subNode->setIcon(1, 0);
- // Add existing notes
- for (scriptPos = scriptsById.begin(); scriptPos != scriptEnd; ++scriptPos) {
- if ((*scriptPos).second->getType() == Script::SCRIPT_NOTE) {
- dynamic_cast<ScriptEdit*>((*scriptPos).second)->addToBrowser(subNode, 0);
- }
- }
- myNode->insert(subNode, 0);
-
- // @TODO: Clearly this block is a temporary setup
- subNode = new TreeView("Folders", this, TREEVIEW_FOLDER, treeviewEventWrap);
- subNode->setIcon(1, 0);
- // Add existing folders
- for (folderPos = foldersById.begin(); folderPos != folderEnd; ++folderPos) {
- dynamic_cast<FolderEdit*>((*folderPos).second)->addToBrowser(subNode, 0);
- }
- myNode->insert(subNode, 0);
-
- worldBrowser->insert(myNode);
- browserNode = myNode;
- }
- int WorldEdit::deleteTileset(TileSetEdit* toDelete, Window* srcWin) { start_func
- // Scan all scenes/layers, ensure tileset is not in use
- SceneIndex::iterator posS;
- SceneIndex::iterator endS = scenesById.end();
- for (posS = scenesById.begin(); posS != endS; ++posS) {
- for (int count = (*posS).second->getLayerCount() - 1; count >= 0; --count) {
- Layer* layer = (*posS).second->getLayer(count);
- if (layer->getTileSet() == toDelete) {
- guiErrorBox(formatString("Cannot delete %s- used by scene %s", toDelete->getName().c_str(), (*posS).second->getName().c_str()), errorTitleInUse);
- return 0;
- }
- }
- }
- // Scan all animation groups, ensure tileset is not in use
- AnimGroupIndex::iterator posL;
- AnimGroupIndex::iterator endL = animgroupsById.end();
- for (posL = animgroupsById.begin(); posL != endL; ++posL) {
- if ((*posL).second->usesTileSet(toDelete)) {
- guiErrorBox(formatString("Cannot delete %s- used by animation group %s", toDelete->getName().c_str(), (*posL).second->getName().c_str()), errorTitleInUse);
- return 0;
- }
- }
- // Verify tileset is in our list
- TileSet* verify = findTileSet(toDelete->getId());
- if (verify) {
- int noUndo = 0;
- // Remove browser node
- TreeView* node = browserNode->findRecursive(toDelete);
- if (node) node->findParent()->remove(node);
- // Disassociate, delete if fails
- try {
- toDelete->disassociate();
- }
- catch (FileException& e) {
- // File error, object must be deleted anyways, but can't be undone
- guiErrorBox(formatString("Deletion of object will not be undoable- %s", e.details), errorTitleFile);
- undo.clearUndo();
- noUndo = 1;
- }
-
- int noDelete = 0;
- if (!noUndo) {
- try {
- if (undo.storeUndoDelete(UndoBuffer::UNDO_TILEDELETE, toDelete->getId(), toDelete, srcWin))
- noDelete = 1;
- }
- catch (UndoException& e) {
- toDelete->reassociate(browserNode->find(toDelete->getIsFont() ? "Fonts" : "Images"));
- return 0;
- }
- }
- // Delete it from list, delete it from file
- deindexTileSet(toDelete);
- saveFile->discardBlock(toDelete);
- // Delete entire object if not claimed by undo
- if (!noDelete) delete toDelete;
- }
-
- return 1;
- }
- int WorldEdit::deleteScene(SceneEdit* toDelete, Window* srcWin) { start_func
- // Verify scene is in our list
- Scene* verify = findScene(toDelete->getId());
- if (verify) {
- int noUndo = 0;
- // Remove browser node
- TreeView* node = browserNode->findRecursive(toDelete);
- if (node) node->findParent()->remove(node);
- // Disassociate, delete if fails
- try {
- toDelete->disassociate();
- }
- catch (FileException& e) {
- // File error, object must be deleted anyways, but can't be undone
- guiErrorBox(formatString("Deletion of object will not be undoable- %s", e.details), errorTitleFile);
- undo.clearUndo();
- noUndo = 1;
- }
- int noDelete = 0;
- if (!noUndo) {
- try {
- if (undo.storeUndoDelete(UndoBuffer::UNDO_SCENEDELETE, toDelete->getId(), toDelete, srcWin))
- noDelete = 1;
- }
- catch (UndoException& e) {
- toDelete->reassociate(browserNode->find("Scenes"));
- return 0;
- }
- }
-
- // Delete it from list, delete it from file
- deindexScene(toDelete);
- saveFile->discardBlock(toDelete);
- // Delete entire object if not claimed by undo
- if (!noDelete) delete toDelete;
- }
-
- return 1;
- }
- int WorldEdit::deleteScript(ScriptEdit* toDelete, Window* srcWin) { start_func
- // Verify script is in our list
- Script* verify = findScript(toDelete->getId());
- if (verify) {
- int noUndo = 0;
- // Remove browser node
- TreeView* node = browserNode->findRecursive(toDelete);
- if (node) node->findParent()->remove(node);
- // Disassociate, delete if fails
- try {
- toDelete->disassociate();
- }
- catch (FileException& e) {
- // File error, object must be deleted anyways, but can't be undone
- guiErrorBox(formatString("Deletion of object will not be undoable- %s", e.details), errorTitleFile);
- undo.clearUndo();
- noUndo = 1;
- }
- int noDelete = 0;
- if (!noUndo) {
- try {
- if (undo.storeUndoDelete(UndoBuffer::UNDO_SCRIPTDELETE, toDelete->getId(), toDelete, srcWin))
- noDelete = 1;
- }
- catch (UndoException& e) {
- toDelete->reassociate(browserNode->find("Scripts"));
- return 0;
- }
- }
- // Delete it from list, delete it from file
- deindexScript(toDelete);
- saveFile->discardBlock(toDelete);
- // Delete entire object if not claimed by undo
- if (!noDelete) delete toDelete;
- }
-
- return 1;
- }
- int WorldEdit::deleteAnimGroup(AnimGroupEdit* toDelete, Window* srcWin) { start_func
- // Verify animation group is in our list
- AnimGroup* verify = findAnimGroup(toDelete->getId());
- if (verify) {
- int noUndo = 0;
- // Remove browser node
- TreeView* node = browserNode->findRecursive(toDelete);
- if (node) node->findParent()->remove(node);
- // Disassociate, delete if fails
- try {
- toDelete->disassociate();
- }
- catch (FileException& e) {
- // File error, object must be deleted anyways, but can't be undone
- guiErrorBox(formatString("Deletion of object will not be undoable- %s", e.details), errorTitleFile);
- undo.clearUndo();
- noUndo = 1;
- }
- int noDelete = 0;
- if (!noUndo) {
- try {
- if (undo.storeUndoDelete(UndoBuffer::UNDO_ANIMGROUPDELETE, toDelete->getId(), toDelete, srcWin))
- noDelete = 1;
- }
- catch (UndoException& e) {
- toDelete->reassociate(browserNode->find("Animations"));
- return 0;
- }
- }
- // Delete it from list, delete it from file
- deindexAnimGroup(toDelete);
- saveFile->discardBlock(toDelete);
- // Delete entire object if not claimed by undo
- if (!noDelete) delete toDelete;
- }
-
- return 1;
- }
- int WorldEdit::deleteFolder(FolderEdit* toDelete, Window* srcWin) { start_func
- // @TODO: Scan folder, ensure empty (if not, prompt user and move items elsewhere)
-
- // Verify folder is in our list
- FolderEdit* verify = findFolder(toDelete->getId());
- if (verify) {
- int noUndo = 0;
- // Remove browser node
- TreeView* node = browserNode->findRecursive(toDelete);
- if (node) node->findParent()->remove(node);
- // Disassociate, delete if fails
- try {
- toDelete->disassociate();
- }
- catch (FileException& e) {
- // File error, object must be deleted anyways, but can't be undone
- guiErrorBox(formatString("Deletion of object will not be undoable- %s", e.details), errorTitleFile);
- undo.clearUndo();
- noUndo = 1;
- }
- int noDelete = 0;
- if (!noUndo) {
- try {
- if (undo.storeUndoDelete(UndoBuffer::UNDO_FOLDERDELETE, toDelete->getId(), toDelete, srcWin))
- noDelete = 1;
- }
- catch (UndoException& e) {
- toDelete->reassociate(browserNode->find("Folders"));
- return 0;
- }
- }
- // Delete it from list, delete it from file
- deindexFolder(toDelete);
- saveFile->discardBlock(toDelete);
- // Delete entire object if not claimed by undo
- if (!noDelete) delete toDelete;
- }
-
- return 1;
- }
- void WorldEdit::importTileSet(TileSetEdit* toAdd, int openWindow, Window* srcWin) { start_func
- try {
- indexTileSet(toAdd);
- // (our only exception point)
- undo.storeUndoCreate(UndoBuffer::UNDO_TILECREATE, toAdd->getId(), srcWin);
- toAdd->addToBrowser(browserNode->find(toAdd->getIsFont() ? "Fonts" : "Images"));
- if (openWindow) toAdd->openBrowseWindow();
- saveFile->newBlock(WorldFile::BLOCKTYPE_TILESET, toAdd);
- }
- catch (UndoException& e) {
- delete toAdd;
- }
- }
- void WorldEdit::importScene(SceneEdit* toAdd, int openWindow, Window* srcWin) { start_func
- try {
- indexScene(toAdd);
- // (our only exception point)
- undo.storeUndoCreate(UndoBuffer::UNDO_SCENECREATE, toAdd->getId(), srcWin);
- toAdd->addToBrowser(browserNode->find("Scenes"));
- if (openWindow) toAdd->openEditWindow();
- saveFile->newBlock(WorldFile::BLOCKTYPE_SCENE, toAdd);
- }
- catch (UndoException& e) {
- delete toAdd;
- }
- }
- void WorldEdit::readdTileset(TileSetEdit* toAdd) { start_func
- indexTileSet(toAdd);
- saveFile->newBlock(WorldFile::BLOCKTYPE_TILESET, toAdd);
- toAdd->reassociate(browserNode->find(toAdd->getIsFont() ? "Fonts" : "Images"));
- }
- void WorldEdit::readdScene(SceneEdit* toAdd) { start_func
- indexScene(toAdd);
- saveFile->newBlock(WorldFile::BLOCKTYPE_SCENE, toAdd);
- toAdd->reassociate(browserNode->find("Scenes"));
- }
- void WorldEdit::readdScript(ScriptEdit* toAdd) { start_func
- indexScript(toAdd);
- saveFile->newBlock(WorldFile::BLOCKTYPE_SCRIPT, toAdd);
- toAdd->reassociate(browserNode->find("Scripts"));
- }
- void WorldEdit::readdAnimGroup(AnimGroupEdit* toAdd) { start_func
- indexAnimGroup(toAdd);
- saveFile->newBlock(WorldFile::BLOCKTYPE_ANIMGROUP, toAdd);
- toAdd->reassociate(browserNode->find("Animations"));
- }
- void WorldEdit::readdFolder(FolderEdit* toAdd) { start_func
- indexFolder(toAdd);
- saveFile->newBlock(WorldFile::BLOCKTYPE_FOLDER, toAdd);
- toAdd->reassociate(browserNode->find("Folders"));
- }
- int WorldEdit::commandEvent(int code) { start_func
- switch (code) {
- case FILE_SAVE:
- save();
- return 1;
-
- case FILE_SAVEAS:
- saveAs();
- return 1;
- case FILE_CLOSE:
- close();
- return 1;
- case EDIT_UNDO:
- undo.undoPerform();
- return 1;
-
- case EDIT_REDO:
- undo.redoPerform();
- return 1;
-
- case NEW_SCENE: {
- SceneEdit* myScene = new SceneEdit(this, unusedSceneId());
- SceneEdit* toDelete = myScene;
- indexScene(myScene);
- try {
- undo.preUndoBlock();
- if (undo.storeUndoCreate(UndoBuffer::UNDO_SCENECREATE, myScene->getId(), desktop->findPreviousFocusWindow())) toDelete = NULL;
- // If not OK, cancel creation of scene
- if (!myScene->propertiesDialog()) {
- // (this may delete and send msg)
- undo.cancelUndoBlock();
- // (if not, this does)
- if (toDelete) {
- undo.disableUndo();
- deleteScene(toDelete);
- undo.enableUndo();
- }
- return 1;
- }
-
- undo.postUndoBlock();
- myScene->addToBrowser(browserNode->find("Scenes"));
- myScene->openEditWindow();
-
- saveFile->newBlock(WorldFile::BLOCKTYPE_SCENE, myScene);
- }
- catch (UndoException& e) {
- delete toDelete;
- return 1;
- }
- return 1;
- }
- case NEW_ANIM: {
- AnimGroupEdit* myAnimGroup = new AnimGroupEdit(this, unusedAnimGroupId());
- AnimGroupEdit* toDelete = myAnimGroup;
- indexAnimGroup(myAnimGroup);
- try {
- undo.preUndoBlock();
- if (undo.storeUndoCreate(UndoBuffer::UNDO_ANIMGROUPCREATE, myAnimGroup->getId(), desktop->findPreviousFocusWindow())) toDelete = NULL;
- // If not OK, cancel creation of anim group
- if (!myAnimGroup->propertiesDialog()) {
- // (this may delete and send msg)
- undo.cancelUndoBlock();
- // (if not, this does)
- if (toDelete) {
- undo.disableUndo();
- deleteAnimGroup(toDelete);
- undo.enableUndo();
- }
- return 1;
- }
-
- undo.postUndoBlock();
- myAnimGroup->addToBrowser(browserNode->find("Animations"));
- myAnimGroup->openBrowseWindow();
-
- saveFile->newBlock(WorldFile::BLOCKTYPE_ANIMGROUP, myAnimGroup);
- }
- catch (UndoException& e) {
- delete toDelete;
- return 1;
- }
- return 1;
- }
- case NEW_FOLDER: {
- FolderEdit* myFolder = new FolderEdit(this, unusedFolderId());
- FolderEdit* toDelete = myFolder;
- indexFolder(myFolder);
- try {
- undo.preUndoBlock();
- if (undo.storeUndoCreate(UndoBuffer::UNDO_FOLDERCREATE, myFolder->getId(), desktop->findPreviousFocusWindow())) toDelete = NULL;
- // If not OK, cancel creation of folder
- if (!myFolder->propertiesDialog()) {
- // (this may delete and send msg)
- undo.cancelUndoBlock();
- // (if not, this does)
- if (toDelete) {
- undo.disableUndo();
- deleteFolder(toDelete);
- undo.enableUndo();
- }
- return 1;
- }
-
- undo.postUndoBlock();
- myFolder->addToBrowser(browserNode->find("Folders"));
-
- saveFile->newBlock(WorldFile::BLOCKTYPE_FOLDER, myFolder);
- }
- catch (UndoException& e) {
- delete toDelete;
- return 1;
- }
- return 1;
- }
- case NEW_NOTES:
- case NEW_SCRIPT:
- case NEW_LIBRARY: {
- Script::ScriptType type = code == NEW_NOTES ? Script::SCRIPT_NOTE : (code == NEW_SCRIPT ? Script::SCRIPT_CODE : Script::SCRIPT_LIBRARY);
- ScriptEdit* myScript = new ScriptEdit(this, type, unusedScriptId());
- ScriptEdit* toDelete = myScript;
- indexScript(myScript);
- try {
- undo.preUndoBlock();
- if (undo.storeUndoCreate(UndoBuffer::UNDO_SCRIPTCREATE, myScript->getId(), desktop->findPreviousFocusWindow())) toDelete = NULL;
- // If not OK, cancel creation of script
- if (!myScript->propertiesDialog()) {
- // (this may delete and send msg)
- undo.cancelUndoBlock();
- // (if not, this does)
- if (toDelete) {
- undo.disableUndo();
- deleteScript(toDelete);
- undo.enableUndo();
- }
- return 1;
- }
-
- undo.postUndoBlock();
- myScript->addToBrowser(browserNode->find(code == NEW_NOTES ? "Notes" : "Scripts"));
- myScript->openEditWindow();
-
- saveFile->newBlock(WorldFile::BLOCKTYPE_SCRIPT, myScript);
- }
- catch (UndoException& e) {
- delete toDelete;
- return 1;
- }
- return 1;
- }
-
- case NEW_IMPORT_IMAGE: {
- ImportImgDialog::createTileSet()->run(this, desktop->findPreviousFocusWindow());
- return 1;
- }
-
- case NEW_IMPORT_FONT: {
- ImportImgDialog::createFontSet()->run(this, desktop->findPreviousFocusWindow());
- return 1;
- }
-
- case NEW_IMAGE:
- case NEW_FONT: {
- TileSetEdit* myTileSet = new TileSetEdit(this, code == NEW_FONT ? 1 : 0, unusedTileSetId());
- TileSetEdit* toDelete = myTileSet;
- indexTileSet(myTileSet);
- try {
- undo.preUndoBlock();
- if (undo.storeUndoCreate(UndoBuffer::UNDO_TILECREATE, myTileSet->getId(), desktop->findPreviousFocusWindow())) toDelete = NULL;
- // If not OK, cancel creation of tile set
- if (!myTileSet->propertiesDialog(1)) {
- // (this may delete and send msg)
- undo.cancelUndoBlock();
- // (if not, this does)
- if (toDelete) {
- undo.disableUndo();
- deleteTileset(toDelete);
- undo.enableUndo();
- }
- return 1;
- }
- undo.postUndoBlock();
- myTileSet->addToBrowser(browserNode->find(code == NEW_FONT ? "Fonts" : "Images"));
- myTileSet->openBrowseWindow();
-
- saveFile->newBlock(WorldFile::BLOCKTYPE_TILESET, myTileSet);
- }
- catch (UndoException& e) {
- delete toDelete;
- return 1;
- }
- return 1;
- }
- }
-
- return 0;
- }
- Window::CommandSupport WorldEdit::supportsCommand(int code) const { start_func
- switch (code) {
- case FILE_SAVE:
- case FILE_SAVEAS:
- case FILE_CLOSE:
- return Window::COMMAND_ENABLE;
- case EDIT_UNDO:
- if (undo.undoAvailable()) return Window::COMMAND_ENABLE;
- return Window::COMMAND_DISABLE;
-
- case EDIT_REDO:
- if (undo.redoAvailable()) return Window::COMMAND_ENABLE;
- return Window::COMMAND_DISABLE;
- }
-
- return Window::COMMAND_HIDE;
- }
- int WorldEdit::treeviewEvent(int code, int command, int check) { start_func
- if (check) {
- return supportsCommand(command);
- }
- switch (code) {
- case TREEVIEW_WORLD:
- switch (command) {
- case LV_RCLICK:
- // @TODO: Should actually be a popup with this as an item
- propertiesDialog(desktop->findPreviousFocusWindow());
- return 1;
- case LV_DELETE:
- close();
- return 1;
- }
-
- return commandEvent(command);
- }
-
- return 0;
- }
- int WorldEdit::treeviewEventWrap(void* ptr, int code, int command, int check) { start_func
- return ((WorldEdit*)ptr)->treeviewEvent(code, command, check);
- }
- int WorldEdit::close(int justSave, int dontAsk) { start_func
- // Modified?
- if ((saveFile->isModified()) && (!dontAsk)) {
- int result = guiMessageBox(formatString("World '%s' has been modified- save?", title.c_str()), "World Modified", &messageBoxYes, &messageBoxNo, &messageBoxCancel);
- if ((result == 3) || (result == 0)) return 0;
- if (result == 1) {
- if (!save()) return 0;
- }
- }
-
- if (justSave) return 1;
-
- // Delete browser node from world browser
- // Also deletes, ex: tileset browser nodes
- if (browserNode) {
- browserNode->findParent()->remove(browserNode);
- }
-
- // Delete
- delete this;
- return 1;
- }
- int WorldEdit::modifiedAll() { start_func
- if (!allWorlds) return 1;
-
- set<WorldEdit*>::iterator pos;
- set<WorldEdit*>::iterator end = allWorlds->end();
- for (pos = allWorlds->begin(); pos != end; ++pos) {
- assert(*pos);
-
- // Close it; cancel rest of process anytime cancel is hit
- if (!(*pos)->close(1)) return 0;
- }
-
- return 1;
- }
- void WorldEdit::closeAll(int dontAsk) { start_func
- if (!allWorlds) return;
- if ((!dontAsk) && (!modifiedAll())) return;
- set<WorldEdit*>::iterator pos;
- set<WorldEdit*>::iterator next;
- set<WorldEdit*>::iterator end = allWorlds->end();
- for (pos = allWorlds->begin(); pos != end; pos = next) {
- assert(*pos);
-
- // Note the next element in sequence now, before we close it
- next = pos;
- ++next;
-
- // Close it; no questions asked
- (*pos)->close(0, 1);
- }
- }
- void WorldEdit::saveAll() { start_func
- if (!allWorlds) return;
-
- set<WorldEdit*>::iterator pos;
- set<WorldEdit*>::iterator end = allWorlds->end();
- for (pos = allWorlds->begin(); pos != end; ++pos) {
- assert(*pos);
-
- // Save it; cancel rest of process anytime cancel is hit
- if (!(*pos)->save()) return;
- }
- }
- void WorldEdit::setTitle(const string& newTitle, Window* srcWin, Window* exWin) throw_Undo { start_func
- if (title != newTitle) {
- setHeaderModified();
- undo.storeUndoName(UndoBuffer::UNDO_WORLDNAME, 0, title, newTitle, srcWin);
- title = newTitle;
- if (browserNode) browserNode->changeName(newTitle);
- desktop->broadcastObjChange(OBJ_WORLD | OBJMOD_NAME, this, 0, 0, exWin);
- }
- }
- void WorldEdit::setStartScene(int sId, Window* srcWin, Window* exWin) throw_Undo { start_func
- if (sId != startingScene) {
- setHeaderModified();
- undo.storeUndoWorldStart(startingScene, srcWin);
- startingScene = sId;
- desktop->broadcastObjChange(OBJ_WORLD | OBJMOD_START, this, 0, 0, exWin);
- }
- }
- int WorldEdit::propertiesDialog(Window* srcWin, Window* exWin) { start_func
- string newTitle = title;
- int newStart = startingScene;
- if (WorldPropertiesDialog::create()->run(&newTitle, &newStart, this)) {
- try {
- undo.preUndoBlock();
- setTitle(newTitle, srcWin, exWin);
- setStartScene(newStart, srcWin, exWin);
- undo.postUndoBlock();
- }
- catch (UndoException& e) {
- return 0;
- }
- return 1;
- }
- return 0;
- }
- void WorldEdit::setHeaderModified() { start_func
- if (!headerModified) headerModified = 1;
- }
- void WorldEdit::setGlobalLinksModified() { start_func
- // Called often, so we won't actually clear the global links here
- globalLinksDone = 0;
- setHeaderModified();
- }
- int WorldEdit::isHeaderModified() const { start_func
- return headerModified;
- }
- int WorldEdit::isContentModified() const { start_func
- return contentModified;
- }
- Uint32 WorldEdit::saveHeader(FileWrite* file) throw_File { start_func
- file->writeStr(title);
- file->writeInt(startingScene);
-
- if (globalLinksDone) {
- assert(globalLinksCount == globalLinks.size());
- file->writeInt(globalLinksCount);
- GlobalMap::iterator pos = globalLinks.begin();
- while (pos != globalLinks.end()) {
- file->writeStr((*pos).first);
- file->writeInt((*pos).second.first);
- file->writeStr((*pos).second.second);
- }
- }
- else {
- // -1 for 'global var list not present'
- file->writeInt((Uint32)-1);
- }
-
- return 1;
- }
- void WorldEdit::loadContent(FileRead* file) { start_func
- // (currently no content)
- delete file;
- }
- void WorldEdit::saveContent(FileWrite* file) { start_func
- // (currently no content)
- }
- void WorldEdit::saveSuccess() { start_func
- headerModified = contentModified = 0;
- }
- void WorldEdit::cachedContent(FileRead* file, int oldData) { start_func
- // (we don't cache)
- delete file;
- }
- int WorldEdit::save() { start_func
- if (saveFile->isNew()) {
- return saveAs();
- }
-
- try {
- // This will full save whenever appropriate
- saveFile->save();
- }
- catch (FileException& e) {
- guiErrorBox(e.details, errorTitleFile);
- }
-
- return 1;
- }
- int WorldEdit::saveAs() { start_func
- string* newFilename = NULL;
- if (filename) newFilename = new string(*filename);
- else newFilename = new string(blankString);
- if (fileSaveAs(FILETYPE_WORLD, *newFilename)) {
- try {
- saveFile->saveAs(newFilename);
- }
- catch (FileException& e) {
- guiErrorBox(e.details, errorTitleFile);
- }
- delete filename;
- filename = NULL;
- filename = newFilename;
- }
- else {
- delete newFilename;
- return 0;
- }
-
- return 1;
- }
- int WorldEdit::verifyWorld(WorldEdit* verify) { start_func
- if (!allWorlds) return 0;
- if (allWorlds->find(verify) != allWorlds->end()) return 1;
- return 0;
- }
- int WorldEdit::countWorlds() { start_func
- if (!allWorlds) return 0;
- return allWorlds->size();
- }
- WorldEdit* WorldEdit::listWorlds(int pos) { start_func
- if (!allWorlds) return NULL;
- if (pos < 0) return NULL;
- set<WorldEdit*>::iterator iter = allWorlds->begin();
- set<WorldEdit*>::iterator end = allWorlds->end();
-
- for (int numpos = 0; iter != end; ++iter, ++numpos) {
- assert(*iter);
-
- if (numpos == pos) return *iter;
- }
-
- return NULL;
- }
- // @TODO: start counting not at 1 but at last id assigned
- int WorldEdit::unusedSceneId() const { start_func
- int expectId = 1;
- SceneIndex::const_iterator end = scenesById.end();
- for (SceneIndex::const_iterator pos = scenesById.begin(); pos != end; ++pos) {
- if ((*pos).first > expectId) break;
- ++expectId;
- }
- return expectId;
- }
- int WorldEdit::unusedTileSetId() const { start_func
- int expectId = 1;
- TileSetIndex::const_iterator end = tilesetsById.end();
- for (TileSetIndex::const_iterator pos = tilesetsById.begin(); pos != end; ++pos) {
- if ((*pos).first > expectId) break;
- ++expectId;
- }
- return expectId;
- }
- int WorldEdit::unusedAnimGroupId() const { start_func
- int expectId = 1;
- AnimGroupIndex::const_iterator end = animgroupsById.end();
- for (AnimGroupIndex::const_iterator pos = animgroupsById.begin(); pos != end; ++pos) {
- if ((*pos).first > expectId) break;
- ++expectId;
- }
- return expectId;
- }
- int WorldEdit::unusedScriptId() const { start_func
- int expectId = SUB_ENTITY_FIRST;
- ScriptIndex::const_iterator end = scriptsById.end();
- for (ScriptIndex::const_iterator pos = scriptsById.begin(); pos != end; ++pos) {
- if ((*pos).first > expectId) break;
- ++expectId;
- }
- return expectId;
- }
- int WorldEdit::unusedLayerId() const { start_func
- int expectId = 1;
- LayerIndex::const_iterator end = layersById.end();
- for (LayerIndex::const_iterator pos = layersById.begin(); pos != end; ++pos) {
- if ((*pos).first > expectId) break;
- ++expectId;
- }
- return expectId;
- }
- int WorldEdit::unusedSpawnId() const { start_func
- int expectId = 1;
- SpawnIndex::const_iterator end = spawnsById.end();
- for (SpawnIndex::const_iterator pos = spawnsById.begin(); pos != end; ++pos) {
- if ((*pos).first > expectId) break;
- ++expectId;
- }
- return expectId;
- }
- int WorldEdit::unusedFolderId() const { start_func
- int expectId = 1;
- FolderIndex::const_iterator end = foldersById.end();
- for (FolderIndex::const_iterator pos = foldersById.begin(); pos != end; ++pos) {
- if ((*pos).first > expectId) break;
- ++expectId;
- }
- return expectId;
- }
- void WorldEdit::indexFolder(FolderEdit* addFolder) { start_func
- assert(foldersById.find(addFolder->getId()) == foldersById.end());
- foldersById.insert(pair<int, FolderEdit*>(addFolder->getId(), addFolder));
- }
- void WorldEdit::deindexFolder(FolderEdit* remFolder) { start_func
- foldersById.erase(remFolder->getId());
- }
- FolderEdit* WorldEdit::findFolder(int fId) const { start_func
- FolderIndex::const_iterator loc = foldersById.find(fId);
- if (loc == foldersById.end()) return NULL;
- return (*loc).second;
- }
- void WorldEdit::indexLayer(LayerEdit* addLayer) { start_func
- assert(layersById.find(addLayer->getId()) == layersById.end());
- layersById.insert(pair<int, LayerEdit*>(addLayer->getId(), addLayer));
- }
- void WorldEdit::deindexLayer(LayerEdit* remLayer) { start_func
- layersById.erase(remLayer->getId());
- }
- LayerEdit* WorldEdit::findLayer(int fId) const { start_func
- LayerIndex::const_iterator loc = layersById.find(fId);
- if (loc == layersById.end()) return NULL;
- return (*loc).second;
- }
- void WorldEdit::indexSpawn(SpawnEdit* addSpawn) { start_func
- assert(spawnsById.find(addSpawn->getId()) == spawnsById.end());
- spawnsById.insert(pair<int, SpawnEdit*>(addSpawn->getId(), addSpawn));
- }
- void WorldEdit::deindexSpawn(SpawnEdit* remSpawn) { start_func
- spawnsById.erase(remSpawn->getId());
- }
- SpawnEdit* WorldEdit::findSpawn(int fId) const { start_func
- SpawnIndex::const_iterator loc = spawnsById.find(fId);
- if (loc == spawnsById.end()) return NULL;
- return (*loc).second;
- }
- void WorldEdit::indexScene(Scene* addScene) { start_func
- World::indexScene(addScene);
-
- SceneEdit* addEdit = dynamic_cast<SceneEdit*>(addScene);
- int count = addEdit->getLayerCount();
- for (int pos = 0; pos < count; ++pos) {
- LayerEdit* layer = addEdit->getLayerEdit(pos);
- indexLayer(layer);
- int countS = layer->getSpawnCount();
- for (int posS = 0; posS < countS; ++posS) {
- assert(layer->getSpawn(posS));
- indexSpawn(layer->getSpawn(posS));
- }
- }
- }
- void WorldEdit::deindexScene(Scene* remScene) { start_func
- SceneEdit* remEdit = dynamic_cast<SceneEdit*>(remScene);
- int count = remEdit->getLayerCount();
- for (int pos = 0; pos < count; ++pos) {
- LayerEdit* layer = remEdit->getLayerEdit(pos);
- int countS = layer->getSpawnCount();
- for (int posS = 0; posS < countS; ++posS) {
- deindexSpawn(layer->getSpawn(posS));
- }
- deindexLayer(layer);
- }
-
- World::deindexScene(remScene);
- }
- SaveLoad* WorldEdit::findItem(int blockType, int id) { start_func
- switch (blockType) {
- case WorldFileLoad::BLOCKTYPE_TILESET:
- return dynamic_cast<TileSetEdit*>(findTileSet(id));
-
- case WorldFileLoad::BLOCKTYPE_SCENE:
- return dynamic_cast<SceneEdit*>(findScene(id));
-
- case WorldFileLoad::BLOCKTYPE_ANIMGROUP:
- return dynamic_cast<AnimGroupEdit*>(findAnimGroup(id));
-
- case WorldFileLoad::BLOCKTYPE_SCRIPT:
- return dynamic_cast<ScriptEdit*>(findScript(id));
-
- case WorldFileLoad::BLOCKTYPE_FOLDER:
- return findFolder(id);
-
- default:
- return NULL;
- }
- }
|