gcsx_spawnedit.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /* GCSx
  2. ** SPAWNEDIT.CPP
  3. **
  4. ** Spawn-point editor-only functionality
  5. */
  6. /*****************************************************************************
  7. ** Copyright (C) 2003-2006 Janson
  8. **
  9. ** This program is free software; you can redistribute it and/or modify
  10. ** it under the terms of the GNU General Public License as published by
  11. ** the Free Software Foundation; either version 2 of the License, or
  12. ** (at your option) any later version.
  13. **
  14. ** This program is distributed in the hope that it will be useful,
  15. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ** GNU General Public License for more details.
  18. **
  19. ** You should have received a copy of the GNU General Public License
  20. ** along with this program; if not, write to the Free Software
  21. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  22. *****************************************************************************/
  23. #include "all.h"
  24. SpawnEdit::SpawnEdit(WorldEdit* myWorld, LayerEdit* myLayer, int newId) : Spawn(newId) { start_func
  25. assert(myWorld);
  26. world = myWorld;
  27. layer = myLayer;
  28. lockCount = 0;
  29. undoReady = 0;
  30. }
  31. SpawnEdit::~SpawnEdit() { start_func
  32. if (lockCount) {
  33. if (animgroup) animgroup->markUnlock();
  34. if (tileset) tileset->markUnlock();
  35. }
  36. }
  37. SpawnEdit::SpawnEdit(const SpawnEdit* copy, LayerEdit* myLayer, int newId) : Spawn(newId) { start_func
  38. world = copy->world;
  39. layer = myLayer;
  40. lockCount = 0;
  41. undoReady = 0;
  42. name = copy->name;
  43. script = copy->script;
  44. animgroup = copy->animgroup;
  45. tileset = copy->tileset;
  46. subid = copy->subid;
  47. x = copy->x;
  48. y = copy->y;
  49. }
  50. void SpawnEdit::setLayer(LayerEdit* newLayer) { start_func
  51. layer = newLayer;
  52. }
  53. void SpawnEdit::setUndoReady() { start_func
  54. undoReady = 1;
  55. }
  56. void SpawnEdit::setModified() { start_func
  57. // @TODO: if no layer..?
  58. if (layer) layer->setContentModified();
  59. }
  60. void SpawnEdit::calculateDisplayCoords() { start_func
  61. displayX = x;
  62. displayY = y;
  63. if (tileset) {
  64. displayW = tileset->getWidth();
  65. displayH = tileset->getHeight();
  66. }
  67. else if ((animgroup) && (lockCount)) {
  68. // (if not locked, animgroup isn't locked and we can't get info)
  69. // @TODO: anim group sizing
  70. displayW = 40;
  71. displayH = 40;
  72. }
  73. else {
  74. displayW = 40;
  75. displayH = 40;
  76. }
  77. }
  78. void SpawnEdit::setName(const std::string& newName, Window* srcWin, Window* exWin) throw_Undo { start_func
  79. if (name != newName) {
  80. setModified();
  81. if ((world) && (undoReady)) world->undo.storeUndoName(UndoBuffer::UNDO_SPAWNNAME, id, name, newName, srcWin);
  82. name = newName;
  83. desktop->broadcastObjChange(OBJ_SPAWN | OBJMOD_NAME, this, 0, 0, exWin);
  84. }
  85. }
  86. void SpawnEdit::setPos(int nX, int nY, int skipUndo, Window* srcWin, Window* exWin) throw_Undo { start_func
  87. if ((x != nX) || (y != nY)) {
  88. setModified();
  89. if ((world) && (undoReady) && (!skipUndo)) world->undo.storeUndoSpawnMove(id, layer->getId(), x, y, srcWin);
  90. x = nX;
  91. y = nY;
  92. calculateDisplayCoords();
  93. desktop->broadcastObjChange(OBJ_SPAWN | OBJMOD_POS, this, 0, 0, exWin);
  94. }
  95. }
  96. void SpawnEdit::setSprite(AnimGroup* newAnimgroup, TileSet* newTileset, int newId, Window* srcWin, Window* exWin) throw_File throw_Undo { start_func
  97. if ((newAnimgroup != animgroup) || (newTileset != tileset) || (newId != subid)) {
  98. assert(newId >= 0);
  99. if ((newAnimgroup) || (newTileset)) {
  100. assert(newId);
  101. if (newAnimgroup) assert(!newTileset);
  102. else assert(!newAnimgroup);
  103. }
  104. else assert(!newId);
  105. // Lock first (file exception point)
  106. if (lockCount) {
  107. if (newAnimgroup) newAnimgroup->markLock();
  108. if (newTileset) {
  109. try {
  110. newTileset->markLock();
  111. }
  112. catch (...) {
  113. if (newAnimgroup) newAnimgroup->markUnlock();
  114. throw;
  115. }
  116. }
  117. }
  118. setModified();
  119. int aId = 0;
  120. int tId = 0;
  121. if (animgroup) aId = animgroup->getId();
  122. if (tileset) tId = tileset->getId();
  123. // Undo (if fail, undo locking from earlier)
  124. try {
  125. if ((world) && (undoReady)) world->undo.storeUndoSpawnSprite(id, layer->getId(), aId, tId, subid, srcWin);
  126. }
  127. catch (...) {
  128. if (lockCount) {
  129. if (newTileset) newTileset->markUnlock();
  130. if (newAnimgroup) newAnimgroup->markUnlock();
  131. }
  132. throw;
  133. }
  134. // Now that all exceptions are passed, unlock prior
  135. if (lockCount) {
  136. if (animgroup) animgroup->markUnlock();
  137. if (tileset) tileset->markUnlock();
  138. }
  139. animgroup = newAnimgroup;
  140. tileset = newTileset;
  141. subid = newId;
  142. calculateDisplayCoords();
  143. desktop->broadcastObjChange(OBJ_SPAWN | OBJMOD_IMAGE, this, 0, 0, exWin);
  144. }
  145. }
  146. void SpawnEdit::setScript(Script* newScript, Window* srcWin, Window* exWin) throw_Undo { start_func
  147. if (script != newScript) {
  148. setModified();
  149. int sId = 0;
  150. if (script) sId = script->getId();
  151. if ((world) && (undoReady)) world->undo.storeUndoSpawnScript(id, layer->getId(), sId, srcWin);
  152. script = newScript;
  153. desktop->broadcastObjChange(OBJ_SPAWN | OBJMOD_SCRIPT, this, 0, 0, exWin);
  154. }
  155. }
  156. int SpawnEdit::propertiesDialog(Window* srcWin, Window* exWin) { start_func
  157. string newName = name;
  158. AnimGroup* newAnimgroup = animgroup;
  159. TileSet* newTileset = tileset;
  160. Script* newScript = script;
  161. int newId = subid;
  162. int result;
  163. if (layer) {
  164. result = SpawnPropertiesDialog::createWithSprite()->run(&newName, &newScript, &newAnimgroup, &newTileset, &newId, world);
  165. }
  166. else {
  167. result = SpawnPropertiesDialog::createNoSprite()->run(&newName, &newScript, NULL, NULL, NULL, world);
  168. }
  169. if (result) {
  170. // (no locking of layer needed- if we're here, our owner is obviously in memory)
  171. try {
  172. if ((world) && (undoReady)) world->undo.preUndoBlock();
  173. setName(newName, srcWin, exWin);
  174. setScript(newScript, srcWin, exWin);
  175. if (layer) {
  176. // @TODO: throw_File
  177. setSprite(newAnimgroup, newTileset, newId, srcWin, exWin);
  178. }
  179. if ((world) && (undoReady)) world->undo.postUndoBlock();
  180. // (at least one of script or sprite must still be present now)
  181. assert((script) || (newTileset) || (newAnimgroup));
  182. }
  183. catch (UndoException& e) {
  184. return 0;
  185. }
  186. return 1;
  187. }
  188. return 0;
  189. }
  190. void SpawnEdit::save(class FileWrite* file) throw_File { start_func
  191. file->writeInt(id);
  192. file->writeStr(name);
  193. if (script) file->writeInt(script->getId());
  194. else file->writeInt(0);
  195. if (animgroup) file->writeInt(animgroup->getId());
  196. else file->writeInt(0);
  197. if (tileset) file->writeInt(tileset->getId());
  198. else file->writeInt(0);
  199. file->writeInt(subid);
  200. file->writeInt(x);
  201. file->writeInt(y);
  202. }
  203. void SpawnEdit::blit(int offsetX, int offsetY, SDL_Surface* dest, int clipX, int clipY, int clipW, int clipH, int dim, int selection) { start_func
  204. assert(lockCount);
  205. // Outside of range?
  206. if ((displayX >= clipX + clipW) ||
  207. (displayY >= clipY + clipH) ||
  208. (clipX >= displayX + displayW) ||
  209. (clipY >= displayY + displayH)) return;
  210. if (dim == 1) dim = 0x80;
  211. else if (dim) dim = 0xC0;
  212. else dim = 0xFF;
  213. // Display
  214. if (tileset) {
  215. dynamic_cast<TileSetEdit*>(tileset)->blitTileFx(subid, dest, offsetX + displayX,
  216. offsetY + displayY,
  217. dim * Image::ALPHA_DEFAULT / 0xFF,
  218. 0, 0, 0, Image::COLOR_DEFAULT);
  219. }
  220. //else if (animgroup) {
  221. // @TODO: animgroup display (base on x/y, as displayx/y would be offset already)
  222. //}
  223. else {
  224. SDL_Surface* src = getIconSurface();
  225. alphaBlitFx(60, 160, src, offsetX + displayX, offsetY + displayY, dest, displayW,
  226. displayH, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, dim, 0xFF);
  227. }
  228. if (selection) {
  229. drawSelectRect(offsetX + displayX, offsetY + displayY, displayW, displayH,
  230. guiPacked[COLOR_SELECTION1], dest);
  231. drawAntsBox(offsetX + displayX, offsetY + displayY, displayW, displayH,
  232. desktop->currentSelectionPhase(), dest);
  233. }
  234. }
  235. int SpawnEdit::markLock() throw_File { start_func
  236. if (animgroup) animgroup->markLock();
  237. if (tileset) {
  238. try {
  239. tileset->markLock();
  240. }
  241. catch (...) {
  242. animgroup->markUnlock();
  243. throw;
  244. }
  245. }
  246. // (animgroup might not have been locked before)
  247. calculateDisplayCoords();
  248. return ++lockCount;
  249. }
  250. int SpawnEdit::markUnlock() { start_func
  251. --lockCount;
  252. assert(lockCount >= 0);
  253. if (lockCount == 0) {
  254. if (animgroup) animgroup->markUnlock();
  255. if (tileset) tileset->markUnlock();
  256. }
  257. return lockCount;
  258. }
  259. int SpawnEdit::isLocked() const { start_func
  260. return lockCount;
  261. }
  262. void SpawnEdit::load(FileRead* file, const World* world) throw_File { start_func
  263. AnimGroup* prevA = NULL;
  264. TileSet* prevT = NULL;
  265. if (lockCount) {
  266. // Unlock later, after all exception points
  267. prevA = animgroup;
  268. prevT = tileset;
  269. animgroup = NULL;
  270. tileset = NULL;
  271. }
  272. Spawn::load(file, world);
  273. if (lockCount) {
  274. try {
  275. if (animgroup) animgroup->markLock();
  276. try {
  277. if (tileset) tileset->markLock();
  278. }
  279. catch (...) {
  280. tileset->markUnlock();
  281. throw;
  282. }
  283. }
  284. catch (...) {
  285. // Revert to previous, still-locked items
  286. animgroup = prevA;
  287. tileset = prevT;
  288. throw;
  289. }
  290. }
  291. if (prevA) prevA->markUnlock();
  292. if (prevT) prevT->markUnlock();
  293. calculateDisplayCoords();
  294. undoReady = 1;
  295. }