gcsx_tilesetbrowse.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /* GCSx
  2. ** TILESETBROWSE.CPP
  3. **
  4. ** Tileset browsing
  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. // Tool panel- Mode
  25. int TileSetBrowseToolsMode::event(int hasFocus, const SDL_Event* event) { start_func
  26. if (event->type == SDL_COMMAND) {
  27. // Choose mode
  28. if (((event->user.code == MODE_EDITTILES) ||
  29. (event->user.code == MODE_EDITCOLLISION) ||
  30. (event->user.code == MODE_EDITASSIGN)) && (!font)) {
  31. *modePtr = event->user.code;
  32. updateTools();
  33. // Change mode (*mode aleady updated)
  34. myBrowse->reloadTileStats();
  35. return 1;
  36. }
  37. }
  38. return Dialog::event(hasFocus, event);
  39. }
  40. void TileSetBrowseToolsMode::updateTools() { start_func
  41. if (!font) {
  42. for (int pos = 0; pos <= 2; ++pos) {
  43. WRadioButton* w = dynamic_cast<WRadioButton*>(findWidget(ID_MODE, pos));
  44. w->load();
  45. if (w->getValue() != MODE_EDITTILES) {
  46. if (*hasMapsPtr) {
  47. w->enable();
  48. }
  49. else {
  50. w->disable();
  51. }
  52. }
  53. }
  54. }
  55. }
  56. void TileSetBrowseToolsMode::childModified(Window* modified) { start_func
  57. Dialog::childModified(modified);
  58. // Change mode (*mode aleady updated)
  59. myBrowse->reloadTileStats();
  60. }
  61. int TileSetBrowseToolsMode::wantsToBeDeleted() const { start_func
  62. return 1;
  63. }
  64. FrameWindow* TileSetBrowseToolsMode::createWindowed() { start_func
  65. // Prevent duplication
  66. if (myFrame) {
  67. return myFrame;
  68. }
  69. // We remember the frame pointer even though it'll delete itself
  70. myFrame = new FrameWindow("Modes", FrameWindow::RESIZING_SNAP, FrameWindow::FRAMETYPE_DIALOG, this, FrameWindow::TITLEBAR_TOOL, 0);
  71. return myFrame;
  72. }
  73. Window::WindowSort TileSetBrowseToolsMode::windowSort() const { start_func
  74. return WINDOWSORT_ONTOP;
  75. }
  76. TileSetBrowseToolsMode::TileSetBrowseToolsMode(TileSetBrowse* tBrowseArea, int isFont, int* mode, const int* hasMaps) : Dialog(blankString, 1, 0, 1) { start_func
  77. myFrame = NULL;
  78. modePtr = mode;
  79. myBrowse = tBrowseArea;
  80. font = isFont;
  81. hasMapsPtr = hasMaps;
  82. Widget* w = NULL;
  83. if (!isFont) {
  84. w = new WRadioButton(ID_MODE, getIconSurface(), 0, 160, 20, 20, mode, MODE_EDITTILES);
  85. w->setToolTip("Edit images");
  86. w->addTo(this);
  87. w = new WRadioButton(ID_MODE, getIconSurface(), 20, 160, 20, 20, mode, MODE_EDITCOLLISION);
  88. w->setToolTip("Edit collision maps");
  89. if (!*hasMaps) w->disable();
  90. w->addTo(this);
  91. w = new WRadioButton(ID_MODE, getIconSurface(), 40, 160, 20, 20, mode, MODE_EDITASSIGN);
  92. w->setToolTip("Assign collision maps to images");
  93. if (!*hasMaps) w->disable();
  94. w->addTo(this);
  95. }
  96. arrangeRow();
  97. runAsPanel();
  98. }
  99. TileSetBrowseToolsMode::~TileSetBrowseToolsMode() { start_func
  100. }
  101. // Browse window- Main
  102. TileSetBrowse::TileSetBrowse(TileSetEdit* myTileset) throw_File : Window() { start_func
  103. assert(myTileset);
  104. cursor = selectFirst = selectLast = selectBegin = selectEnd = 0;
  105. haveFocus = partialFocus = 0;
  106. dirtyRange.w = 0;
  107. toolsMode = NULL;
  108. tileset = myTileset;
  109. hasMaps = tileset->getCollisionCount() ? 1 : 0;
  110. // @TODO: These need to be selectable
  111. zoomRatio = 100;
  112. gridSize = 1;
  113. // (this setting is purposely not remembered)
  114. mode = MODE_EDITTILES;
  115. reloadTileStats();
  116. // @TODO: This needs to be selectable
  117. showLetters = isFont;
  118. FrameWindow* myFrame = NULL;
  119. FrameWindow* toolsModeFrame = NULL;
  120. tileset->markLock(); // exception point
  121. toolsMode = new TileSetBrowseToolsMode(this, isFont, &mode, &hasMaps);
  122. toolsModeFrame = toolsMode->createWindowed();
  123. myFrame = new FrameWindow(formatString("%s : %s", tileset->getWorld()->getTitle().c_str(), tileset->getName().c_str()), FrameWindow::RESIZING_NORMAL, FrameWindow::FRAMETYPE_BEVEL_BK, this);
  124. myFrame->addToolPanel(toolsModeFrame, FrameWindow::CLIENT_RIGHT);
  125. myFrame->show(FrameWindow::SHOW_CASCADE, FrameWindow::SHOW_CASCADE, FrameWindow::SHOW_CURRENT, FrameWindow::SHOW_CURRENT);
  126. }
  127. TileSetBrowse::~TileSetBrowse() { start_func
  128. if (tileset) tileset->markUnlock();
  129. }
  130. void TileSetBrowse::setDirtyRange(int first, int last) { start_func
  131. if (!numTiles) {
  132. setDirty(1);
  133. return;
  134. }
  135. assert(first >= 0);
  136. assert(first < numTiles);
  137. assert(last >= 0);
  138. assert(last < numTiles);
  139. if (first > last) swap(first, last);
  140. // On the same line?
  141. if (first / tilesPerLine == last / tilesPerLine) {
  142. setDirtyBox(first, last);
  143. }
  144. else {
  145. // Have to cover entire lines
  146. setDirtyBox(first - first % tilesPerLine, last - last % tilesPerLine + tilesPerLine - 1);
  147. }
  148. }
  149. void TileSetBrowse::setDirtyBox(int begin, int end) { start_func
  150. if (!numTiles) {
  151. setDirty(1);
  152. return;
  153. }
  154. assert(begin >= 0);
  155. assert(begin < numTiles);
  156. assert(end >= 0);
  157. // ('end' can be greater than number of tiles to complete a box pattern)
  158. assert(begin <= end);
  159. assert((begin % tilesPerLine) <= (end % tilesPerLine));
  160. // Create a rectangle, include outermost gridlines
  161. Rect range;
  162. range.x = (begin % tilesPerLine) * (zoomWidth + gridSize);
  163. range.y = (begin / tilesPerLine) * (zoomHeight + gridSize);
  164. range.w = (end % tilesPerLine - begin % tilesPerLine + 1) * (zoomWidth + gridSize) + gridSize;
  165. range.h = (end / tilesPerLine - begin / tilesPerLine + 1) * (zoomHeight + gridSize) + gridSize;
  166. // Add rectangle into dirty range
  167. boundRects(dirtyRange, range);
  168. setDirty();
  169. }
  170. void TileSetBrowse::reloadTileStats() { start_func
  171. numTiles = (mode == MODE_EDITCOLLISION) ? tileset->getCollisionCount() : tileset->getCount();
  172. tileWidth = tileset->getWidth();
  173. tileHeight = tileset->getHeight();
  174. isFont = tileset->getIsFont();
  175. zoomWidth = tileWidth * zoomRatio / 100;
  176. zoomHeight = tileHeight * zoomRatio / 100;
  177. tilesPerLine = tileset->getTilesPerLine();
  178. fixedTilesPerLine = tilesPerLine ? 1 : 0;
  179. resize(width, height);
  180. // (never put cursor below 0)
  181. if (numTiles) {
  182. if (cursor >= numTiles) cursor = numTiles - 1;
  183. if (selectFirst >= numTiles) selectFirst = numTiles - 1;
  184. if (selectLast >= numTiles) selectLast = numTiles - 1;
  185. // This must occur after resize() which sets tilesperline for us if needed
  186. realignSelection();
  187. }
  188. setDirty(1);
  189. }
  190. void TileSetBrowse::resize(int newWidth, int newHeight, int newViewWidth, int newViewHeight, int fromParent) { start_func
  191. if (newViewWidth == -1) newViewWidth = viewWidth;
  192. // Calculate tiles per line, if not fixed
  193. if (!fixedTilesPerLine) {
  194. // For non fixed tiles, default width is 3/4ths desktop
  195. if (newViewWidth <= 0) newViewWidth = desktop->desktopWidth() * 3 / 4;
  196. tilesPerLine = (newViewWidth - gridSize) / (zoomWidth + gridSize);
  197. if (tilesPerLine < 1) tilesPerLine = 1;
  198. }
  199. // Size to match
  200. int myWidth = tilesPerLine * (zoomWidth + gridSize) + gridSize;
  201. int myHeight = numTiles / tilesPerLine;
  202. if (numTiles % tilesPerLine) ++myHeight;
  203. myHeight = myHeight * (zoomHeight + gridSize) + gridSize;
  204. // Recurse back to parent until we get a match
  205. if ((myWidth != width) || (myHeight != height)) fromParent = 0;
  206. Window::resize(myWidth, myHeight, newViewWidth, newViewHeight, fromParent);
  207. if (parent) dynamic_cast<FrameWindow*>(parent)->setScroll(zoomWidth + gridSize, zoomHeight + gridSize);
  208. }
  209. int TileSetBrowse::event(int hasFocus, const SDL_Event* event) { start_func
  210. int drag = 0;
  211. int key;
  212. int target;
  213. int changed = 0;
  214. ObjChange* obj;
  215. switch (event->type) {
  216. case SDL_OBJECTCHANGE:
  217. obj = (ObjChange*)event->user.data1;
  218. if ((event->user.code & OBJ_TILESET) && (obj->obj == tileset)) {
  219. if (event->user.code & OBJMOD_DELETE) {
  220. tileset = NULL;
  221. closeWindow();
  222. }
  223. if (event->user.code & OBJMOD_NAME) {
  224. if (parent) dynamic_cast<FrameWindow*>(parent)->setTitle(formatString("%s : %s", tileset->getWorld()->getTitle().c_str(), tileset->getName().c_str()));
  225. }
  226. if (event->user.code & OBJMOD_COUNTCOLL) {
  227. hasMaps = tileset->getCollisionCount() ? 1 : 0;
  228. if (!hasMaps) mode = MODE_EDITTILES;
  229. toolsMode->updateTools();
  230. reloadTileStats();
  231. }
  232. if (event->user.code & (OBJMOD_WIDTH | OBJMOD_HEIGHT | OBJMOD_COUNT | OBJMOD_PERLINE)) {
  233. reloadTileStats();
  234. }
  235. if (event->user.code & OBJMOD_GLYPHW) {
  236. setDirtyRange(obj->info1 - 1, obj->info1 - 1);
  237. }
  238. if ((event->user.code & OBJMOD_TILE) && (mode != MODE_EDITCOLLISION)) {
  239. setDirtyRange(obj->info1 - 1, obj->info2 - 1);
  240. }
  241. if (event->user.code & OBJMOD_COLL) {
  242. if (mode == MODE_EDITCOLLISION) {
  243. setDirtyRange(obj->info1 - 1, obj->info2 - 1);
  244. }
  245. else if (mode == MODE_EDITASSIGN) {
  246. setDirty(1);
  247. }
  248. }
  249. }
  250. if ((event->user.code & OBJ_WORLD) && (obj->obj == tileset->getWorld())) {
  251. if (event->user.code & OBJMOD_DELETE) {
  252. tileset = NULL;
  253. closeWindow();
  254. }
  255. if (event->user.code & OBJMOD_NAME) {
  256. if (parent) dynamic_cast<FrameWindow*>(parent)->setTitle(formatString("%s : %s", tileset->getWorld()->getTitle().c_str(), tileset->getName().c_str()));
  257. }
  258. }
  259. return 1;
  260. case SDL_COMMAND:
  261. if (tileset->getWorldEdit()->commandEvent(event->user.code)) return 1;
  262. break;
  263. case SDL_MOUSEBUTTONDOWN:
  264. case SDL_MOUSEBUTTONDBL:
  265. if (event->button.button == SDL_BUTTON_LEFT) {
  266. int mX = event->button.x / (zoomWidth + gridSize);
  267. int mY = event->button.y / (zoomHeight + gridSize);
  268. // (clip to edge, in cse off of it)
  269. if (mX >= tilesPerLine) mX = tilesPerLine - 1;
  270. if (mY >= (numTiles + tilesPerLine - 1) / tilesPerLine) mY = (numTiles + tilesPerLine - 1) / tilesPerLine - 1;
  271. cursorState(mX + mY * tilesPerLine, SDL_GetModState() & KMOD_SHIFT);
  272. if (event->type == SDL_MOUSEBUTTONDBL) {
  273. if (mode == MODE_EDITCOLLISION) {
  274. tileset->openCollPaintWindow(cursor + 1);
  275. }
  276. else {
  277. tileset->openTilePaintWindow(cursor + 1);
  278. }
  279. }
  280. return 1;
  281. }
  282. break;
  283. case SDL_MOUSEMOTION:
  284. if (event->motion.state & SDL_BUTTON_LMASK) {
  285. int mX = ((Sint16)event->motion.x) / (zoomWidth + gridSize);
  286. int mY = ((Sint16)event->motion.y) / (zoomHeight + gridSize);
  287. // (clip to edge, in case off of it)
  288. if (mX >= tilesPerLine) mX = tilesPerLine - 1;
  289. if (mY >= (numTiles + tilesPerLine - 1) / tilesPerLine) mY = (numTiles + tilesPerLine - 1) / tilesPerLine - 1;
  290. cursorState(mX + mY * tilesPerLine, 1);
  291. }
  292. return 1;
  293. case SDL_SPECIAL:
  294. // Refresh selection rectangle or cursor color?
  295. if ((event->user.code == SDL_IDLEPHASE) && (partialFocus)) {
  296. if (fixedTilesPerLine) setDirtyBox(selectBegin, selectEnd);
  297. else setDirtyRange(selectFirst, selectLast);
  298. }
  299. else if ((event->user.code == SDL_IDLECURSOR) && (haveFocus)) {
  300. setDirtyRange(cursor, cursor);
  301. }
  302. return 1;
  303. case SDL_INPUTFOCUS:
  304. if (event->user.code & 1) {
  305. if (!haveFocus) {
  306. haveFocus = partialFocus = 1;
  307. changed = 1;
  308. }
  309. }
  310. else if (event->user.code & 2) {
  311. if (!partialFocus) {
  312. partialFocus = 1;
  313. changed = 1;
  314. }
  315. }
  316. else {
  317. if (partialFocus) {
  318. partialFocus = 0;
  319. changed = 1;
  320. }
  321. }
  322. if (!(event->user.code & 1)) {
  323. if (haveFocus) {
  324. haveFocus = 0;
  325. changed = 1;
  326. }
  327. }
  328. if (changed) {
  329. if (fixedTilesPerLine) setDirtyBox(selectBegin, selectEnd);
  330. else setDirtyRange(selectFirst, selectLast);
  331. }
  332. return 1;
  333. case SDL_KEYDOWN:
  334. if (event->key.keysym.mod & KMOD_SHIFT) {
  335. drag = 1; // We'll check this if we care about SHIFT
  336. key = combineKey(event->key.keysym.sym, event->key.keysym.mod & ~KMOD_SHIFT);
  337. }
  338. else {
  339. key = combineKey(event->key.keysym.sym, event->key.keysym.mod);
  340. }
  341. switch (key) {
  342. case SDLK_KP_ENTER:
  343. case SDLK_RETURN:
  344. case SDLK_SPACE:
  345. tileset->openTilePaintWindow(cursor + 1);
  346. return 1;
  347. case SDLK_RIGHT:
  348. cursorState(cursor + 1, drag);
  349. return 1;
  350. case combineKey(SDLK_RIGHT, KMOD_CTRL):
  351. case SDLK_END:
  352. cursorState(cursor + tilesPerLine - (cursor % tilesPerLine) - 1, drag);
  353. return 1;
  354. case SDLK_LEFT:
  355. if (cursor > 0) cursorState(cursor - 1, drag);
  356. return 1;
  357. case combineKey(SDLK_LEFT, KMOD_CTRL):
  358. case SDLK_HOME:
  359. cursorState(cursor - (cursor % tilesPerLine), drag);
  360. return 1;
  361. case SDLK_DOWN:
  362. cursorState(cursor + tilesPerLine, drag);
  363. return 1;
  364. case SDLK_PAGEDOWN:
  365. cursorState(cursor + (viewHeight / (zoomHeight + gridSize) - 1) * tilesPerLine, drag);
  366. return 1;
  367. case SDLK_PAGEUP:
  368. target = cursor - (viewHeight / (zoomHeight + gridSize) - 1) * tilesPerLine;
  369. if (target > 0) cursorState(target, drag);
  370. else cursorState(0, drag);
  371. return 1;
  372. case SDLK_UP:
  373. if (cursor - tilesPerLine > 0) cursorState(cursor - tilesPerLine, drag);
  374. else cursorState(0, drag);
  375. return 1;
  376. case combineKey(SDLK_HOME, KMOD_CTRL):
  377. cursorState(0, drag);
  378. return 1;
  379. case combineKey(SDLK_END, KMOD_CTRL):
  380. cursorState(numTiles - 1, drag);
  381. return 1;
  382. }
  383. break;
  384. }
  385. return 0;
  386. }
  387. void TileSetBrowse::realignSelection() { start_func
  388. if (selectFirst % tilesPerLine <= selectLast % tilesPerLine) {
  389. selectBegin = selectFirst;
  390. selectEnd = selectLast;
  391. }
  392. else {
  393. selectBegin = selectFirst - selectFirst % tilesPerLine + selectLast % tilesPerLine;
  394. selectEnd = selectLast - selectLast % tilesPerLine + selectFirst % tilesPerLine;
  395. }
  396. }
  397. int TileSetBrowse::cursorState(int newPos, int drag) { start_func
  398. if (newPos >= 0) {
  399. // Clip on right
  400. if (newPos >= numTiles) newPos = numTiles - 1;
  401. // Dirty previous selection
  402. if (fixedTilesPerLine) setDirtyBox(selectBegin, selectEnd);
  403. else setDirtyRange(selectFirst, selectLast);
  404. // Drag?
  405. if (drag) {
  406. // If selection beginning matches cursor
  407. if (selectFirst == cursor) {
  408. // Drag beginning point
  409. selectFirst = cursor = newPos;
  410. }
  411. else {
  412. // Drag end point
  413. selectLast = cursor = newPos;
  414. }
  415. // Ensure in proper order
  416. if (selectLast < selectFirst) {
  417. swap(selectFirst, selectLast);
  418. }
  419. }
  420. else {
  421. // Reset selection and set cursor
  422. selectFirst = selectLast = cursor = newPos;
  423. }
  424. // Scroll?
  425. int newY = cursor / tilesPerLine * (zoomHeight + gridSize);
  426. int newX = (cursor % tilesPerLine) * (zoomWidth + gridSize);
  427. if (parent) dynamic_cast<FrameWindow*>(parent)->scrollToView(newX, newY, zoomWidth + gridSize * 2, zoomHeight + gridSize * 2);
  428. realignSelection();
  429. // Dirty
  430. if (fixedTilesPerLine) setDirtyBox(selectBegin, selectEnd);
  431. else setDirtyRange(selectFirst, selectLast);
  432. }
  433. return cursor;
  434. }
  435. void TileSetBrowse::display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset) { start_func
  436. assert(destSurface);
  437. if (visible) {
  438. // If dirty, redraw range or all
  439. if (dirty) {
  440. if (totalDirty) {
  441. getRect(toDisplay);
  442. toDisplay.x += xOffset;
  443. toDisplay.y += yOffset;
  444. }
  445. else {
  446. dirtyRange.x += x + xOffset;
  447. dirtyRange.y += y + yOffset;
  448. // Range must include requested update area as well
  449. boundRects(toDisplay, dirtyRange);
  450. }
  451. dirty = totalDirty = 0;
  452. dirtyRange.w = 0;
  453. intersectRects(toDisplay, clipArea);
  454. }
  455. xOffset += x;
  456. yOffset += y;
  457. // Anything to draw?
  458. if (toDisplay.w) {
  459. SDL_SetClipRect(destSurface, &toDisplay);
  460. SDL_FillRect(destSurface, &toDisplay, guiPacked[COLOR_BKFILL]);
  461. int dX = xOffset + gridSize;
  462. int lastX = xOffset + width;
  463. // Draw starting at the first line of the displayed area;
  464. int skip = (toDisplay.y - yOffset) / (zoomHeight + gridSize);
  465. // Make sure this includes the tile above a gridline
  466. // if that gridline is the very top pixel being shown
  467. if (((toDisplay.y - yOffset) % (zoomHeight + gridSize) == 0) && (skip > 0)) --skip;
  468. int dY = yOffset + skip * (zoomHeight + gridSize) + gridSize;
  469. int lastY = toDisplay.y + toDisplay.h;
  470. int pos = tilesPerLine * skip;
  471. // Determine first/last tiles of each row we need to show
  472. // These numbers would be, for example, 0 for first tile, 1 for second,
  473. // up to tilesPerLine - 1
  474. int leftmost = (toDisplay.x - xOffset) / (zoomWidth + gridSize);
  475. int rightmost = (toDisplay.x + toDisplay.w - xOffset - 1) / (zoomWidth + gridSize);
  476. // Make sure this includes the tile to the left of a gridline
  477. // if that gridline is the very left pixel being shown
  478. if (((toDisplay.x - xOffset) % (zoomWidth + gridSize) == 0) && (leftmost > 0)) --leftmost;
  479. pos += leftmost;
  480. dX += (zoomWidth + gridSize) * leftmost;
  481. int selectBeginMod = selectBegin % tilesPerLine;
  482. int selectEndMod = selectEnd % tilesPerLine;
  483. for (; (pos < numTiles) && (dY < lastY); ++pos) {
  484. int posMod = pos % tilesPerLine;
  485. // We use modulo to determine if this tile needs displaying
  486. if ((posMod >= leftmost) && (posMod <= rightmost)) {
  487. // Draw tile @TODO: doesn't zoom
  488. if (mode == MODE_EDITCOLLISION) {
  489. tileset->blitCollFx(pos + 1, destSurface, dX, dY, 0, 0, 0, 0, 0xffffffff);
  490. }
  491. else {
  492. tileset->blitTile(pos + 1, destSurface, dX, dY);
  493. }
  494. // Glyph width
  495. if (isFont) {
  496. int glyphWidth = tileset->getGlyphWidth(pos + 1);
  497. glyphWidth = glyphWidth * zoomRatio / 100;
  498. drawVLine(dY, dY + zoomHeight, glyphWidth + dX, guiPacked[COLOR_GLYPHWIDTH], destSurface);
  499. if (showLetters) {
  500. string glyph(1, pos + 32);
  501. drawText(glyph, guiRGB[COLOR_TOOLTIP], dX + zoomWidth - fontWidth(glyph), dY + zoomHeight - fontHeight(), destSurface);
  502. }
  503. }
  504. // Overlay collision data in assign mode @TODO
  505. if (partialFocus) {
  506. // Selected or cursor- if fixed width, within begin/end
  507. // If not, within first/last
  508. if (((fixedTilesPerLine) &&
  509. (pos >= selectBegin) && (pos <= selectEnd) &&
  510. (posMod >= selectBeginMod) &&
  511. (posMod <= selectEndMod))
  512. ||
  513. ((!fixedTilesPerLine) &&
  514. (pos >= selectFirst) && (pos <= selectLast))
  515. ) {
  516. drawSelectRect(dX, dY, zoomWidth, zoomHeight,
  517. guiPacked[(pos == cursor) && (haveFocus) ? COLOR_TILECURSOR : COLOR_TILESELECTION], destSurface,
  518. (pos == cursor) && (haveFocus) ? desktop->currentCursorAlpha() : 128);
  519. if (pos == cursor) {
  520. drawBox(dX - gridSize, dY - gridSize, zoomWidth + gridSize * 2, zoomHeight + gridSize * 2, guiPacked[COLOR_TILECURSORBORDER1], destSurface);
  521. drawBox(dX - gridSize + 1, dY - gridSize + 1, zoomWidth + gridSize * 2 - 2, zoomHeight + gridSize * 2 - 2, guiPacked[COLOR_TILECURSORBORDER2], destSurface);
  522. }
  523. // Draw ants borders
  524. if (selectFirst != selectLast) {
  525. int drawT = 1;
  526. int drawB = 1;
  527. int drawL = 1;
  528. int drawR = 1;
  529. if (fixedTilesPerLine) {
  530. if (posMod > selectBeginMod) drawL = 0;
  531. if (posMod < selectEndMod) drawR = 0;
  532. if (pos - selectBegin >= tilesPerLine) drawT = 0;
  533. if (selectEnd - pos >= tilesPerLine) drawB = 0;
  534. }
  535. else {
  536. if (pos > selectFirst) drawL = 0;
  537. if (pos < selectLast) drawR = 0;
  538. if (pos - selectFirst >= tilesPerLine) drawT = 0;
  539. if (selectLast - pos >= tilesPerLine) drawB = 0;
  540. }
  541. if (drawT) drawAntsHLine(dX - gridSize, dX + zoomWidth - 1 + gridSize, dY - gridSize, desktop->currentSelectionPhase(), destSurface);
  542. if (drawB) drawAntsHLine(dX - gridSize, dX + zoomWidth - 1 + gridSize, dY + zoomHeight - 1 + gridSize, desktop->currentSelectionPhase(), destSurface);
  543. if (drawL) drawAntsVLine(dY - gridSize, dY + zoomHeight - 1 + gridSize, dX - gridSize, desktop->currentSelectionPhase(), destSurface);
  544. if (drawR) drawAntsVLine(dY - gridSize, dY + zoomHeight - 1 + gridSize, dX + zoomWidth - 1 + gridSize, desktop->currentSelectionPhase(), destSurface);
  545. }
  546. }
  547. }
  548. }
  549. dX += zoomWidth + gridSize;
  550. if (dX + zoomWidth > lastX) {
  551. dX = xOffset + gridSize;
  552. dY += zoomHeight + gridSize;
  553. }
  554. }
  555. }
  556. }
  557. }
  558. // @TODO: select all/deselct/cutcopypaste/zoom/grid
  559. Window::CommandSupport TileSetBrowse::supportsCommand(int code) const { start_func
  560. switch (code) {
  561. // @TODO: these 3 should be radios
  562. case MODE_EDITTILES:
  563. return isFont ? Window::COMMAND_HIDE : Window::COMMAND_ENABLE;
  564. case MODE_EDITCOLLISION:
  565. case MODE_EDITASSIGN:
  566. return isFont ? Window::COMMAND_HIDE : (hasMaps ? Window::COMMAND_ENABLE : Window::COMMAND_DISABLE);
  567. }
  568. return tileset->getWorldEdit()->supportsCommand(code);
  569. }
  570. Window::WindowType TileSetBrowse::windowType() const { start_func
  571. return WINDOW_CLIENT;
  572. }