diff --git a/Aquaria/SceneEditor.cpp b/Aquaria/SceneEditor.cpp index 0b69282..4e5a465 100644 --- a/Aquaria/SceneEditor.cpp +++ b/Aquaria/SceneEditor.cpp @@ -774,14 +774,18 @@ void SceneEditor::init() placer = new Quad; game->addRenderObject(placer, LR_HUD); placer->alpha = 0; - curElement = 0; + curElementId = 0; selectedEntity.clear(); nextElement(); + const ElementTemplate *et = dsq->tilemgr.tileset.getIfExists(0); + if(!et) + dsq->tilemgr.tileset.getAdjacent(0, 1, false, 1024); - if (curElement < dsq->tilemgr.tileset.elementTemplates.size()) + + if (et) { - placer->setTexture(dsq->tilemgr.tileset.elementTemplates[curElement]->gfx); + placer->setTexture(et->gfx); placer->scale = Vector(1,1); } else @@ -962,11 +966,11 @@ void SceneEditor::clearSelection() void SceneEditor::editModeElements() { - clearSelection(); + setActiveLayer(bgLayer, editType != ET_ELEMENTS); editType = ET_ELEMENTS; - if (curElement < dsq->tilemgr.tileset.elementTemplates.size()) + if (const ElementTemplate *et = dsq->tilemgr.tileset.getIfExists(curElementId)) { - placer->setTexture(dsq->tilemgr.tileset.elementTemplates[curElement]->gfx); + placer->setTexture(et->gfx); placer->scale = Vector(1,1); } placer->alpha = 0.5; @@ -977,6 +981,7 @@ void SceneEditor::editModeElements() void SceneEditor::editModeEntities() { + unselectTileLayer(); clearSelection(); editType = ET_ENTITIES; placer->setTexture(selectedEntity.prevGfx); @@ -986,6 +991,7 @@ void SceneEditor::editModeEntities() void SceneEditor::editModePaths() { + unselectTileLayer(); clearSelection(); editType = ET_PATHS; placer->alpha = 0; @@ -1731,14 +1737,18 @@ void SceneEditor::updateMultiSelect() } } -void SceneEditor::setActiveLayer(unsigned bglayer) +void SceneEditor::unselectTileLayer() { - if(this->bgLayer == bglayer) - return; - for(size_t i = 0; i < MAX_TILE_LAYERS; ++i) dsq->tileRenders[i]->renderBorders = false; +} + +void SceneEditor::setActiveLayer(unsigned bglayer, bool force) +{ + if(this->bgLayer == bglayer && !force) + return; + unselectTileLayer(); dsq->tileRenders[bglayer]->renderBorders = true; destroyMultiTileHelper(); @@ -2078,7 +2088,7 @@ void SceneEditor::cycleSelectedTiles(int direction) for(size_t i = 0; i < n; ++i) { TileData& t = ts.tiles[selectedTiles[i]]; - const ElementTemplate *adj = dsq->tilemgr.tileset.getAdjacent(t.et->idx, direction, true); + const ElementTemplate *adj = dsq->tilemgr.tileset.getAdjacent(t.et->idx, direction, true, 1024); if(adj) t.et = adj; } @@ -2158,17 +2168,12 @@ void SceneEditor::prevElement() void SceneEditor::cyclePlacer(int direction) { - const int maxn = (int)dsq->tilemgr.tileset.elementTemplates.size(); - int nextidx = (int)curElement + direction; - if(nextidx < 0) - nextidx += maxn; - if(nextidx >= maxn) - nextidx -= maxn; + const ElementTemplate *next = dsq->tilemgr.tileset.getAdjacent(curElementId, direction, true, 1024); - if (maxn && dsq->tilemgr.tileset.elementTemplates[curElement]->idx < 1024) + if (next) { - placer->setTexture(dsq->tilemgr.tileset.elementTemplates[curElement]->gfx); - curElement = nextidx; + placer->setTexture(next->gfx); + curElementId = next->idx; } } @@ -2178,9 +2183,9 @@ void SceneEditor::selectZero() if (editType == ET_ELEMENTS) { - if (dsq->tilemgr.tileset.elementTemplates.empty()) return; - curElement = 0; - placer->setTexture(dsq->tilemgr.tileset.elementTemplates[curElement]->gfx); + curElementId = 0; + const ElementTemplate *et = dsq->tilemgr.tileset.getIfExists(0); + placer->setTexture(et ? et->gfx : "missingimage"); } } @@ -2189,19 +2194,12 @@ void SceneEditor::selectEnd() if (state != ES_SELECTING) return; if (editType == ET_ELEMENTS) { - if (dsq->tilemgr.tileset.elementTemplates.empty()) return; - - size_t largest = 0; - for (size_t i = 0; i < dsq->tilemgr.tileset.elementTemplates.size(); i++) + const ElementTemplate *next = dsq->tilemgr.tileset.getAdjacent(0, -1, true, 1024); + if(next) { - ElementTemplate *et = dsq->tilemgr.tileset.elementTemplates[i]; - if (et->idx < 1024 && i > largest) - { - largest = i; - } + curElementId = next->idx; + placer->setTexture(next->gfx); } - curElement = largest; - placer->setTexture(dsq->tilemgr.tileset.elementTemplates[curElement]->gfx); } } @@ -2211,8 +2209,7 @@ void SceneEditor::placeElement() { if (!core->getShiftState() && !core->getKeyState(KEY_LALT)) { - unsigned tilesetID = dsq->tilemgr.tileset.elementTemplates[curElement]->idx; - dsq->tilemgr.createOneTile(tilesetID, bgLayer, placer->position.x, placer->position.y); + dsq->tilemgr.createOneTile(curElementId, bgLayer, placer->position.x, placer->position.y); // FIXME: need to update grid or no? updateText(); } @@ -2414,6 +2411,13 @@ void SceneEditor::updateText() os << " gfx: " << t.et->gfx; os << " F:" << ((t.flags & TILEFLAG_FH) ? "H" : "") << ((t.flags & TILEFLAG_FV) ? "V" : ""); } + else + { + os << " // id: " << curElementId; + const ElementTemplate *et = dsq->tilemgr.tileset.getIfExists(curElementId); + if(et) + os << " gfx: " << et->gfx; + } break; case ET_ENTITIES: os << "entities (" << dsq->entities.size() << ")"; diff --git a/Aquaria/SceneEditor.h b/Aquaria/SceneEditor.h index 56c5a17..7ce24bf 100644 --- a/Aquaria/SceneEditor.h +++ b/Aquaria/SceneEditor.h @@ -223,13 +223,14 @@ protected: void mouseButtonLeft(); void mouseButtonRight(); - void setActiveLayer(unsigned bglayer); + void setActiveLayer(unsigned bglayer, bool force = false); TileStorage& getCurrentLayerTiles(); void clearSelection(); + void unselectTileLayer(); MultiTileHelper *createMultiTileHelperFromSelection(); void destroyMultiTileHelper(); - size_t curElement; + size_t curElementId; Quad *placer; MultiTileHelper *multi; diff --git a/BBGE/Tileset.cpp b/BBGE/Tileset.cpp index d7351af..ee9fd9d 100644 --- a/BBGE/Tileset.cpp +++ b/BBGE/Tileset.cpp @@ -14,6 +14,11 @@ Tileset::~Tileset() clear(); } +static bool _etsort(const ElementTemplate *a, const ElementTemplate *b) +{ + return a->idx < b->idx; +} + bool Tileset::loadFile(const char *fn, const unsigned char *usedIdx, size_t usedIdxLen) { clear(); @@ -50,7 +55,7 @@ bool Tileset::loadFile(const char *fn, const unsigned char *usedIdx, size_t used if(warn) errorLog("Tileset indices of 1024 and above are reserved; ignored during load"); - std::sort(elementTemplates.begin(), elementTemplates.end()); + std::sort(elementTemplates.begin(), elementTemplates.end(), _etsort); // begin preloading textures @@ -126,7 +131,7 @@ void Tileset::clear() elementTemplates.clear(); } -const ElementTemplate *Tileset::getByIdx(size_t idx) +const ElementTemplate * Tileset::getIfExists(size_t idx) { for (size_t i = 0; i < elementTemplates.size(); i++) { @@ -137,6 +142,13 @@ const ElementTemplate *Tileset::getByIdx(size_t idx) return et; } } + return NULL; +} + +const ElementTemplate *Tileset::getByIdx(size_t idx) +{ + if(const ElementTemplate *existing = getIfExists(idx)) + return existing; // a tile that gets an ET attached must remember its tileset id even if the entry is not present // in the tileset. since the tile does not store the idx as an integer, we need to return a dummy element. @@ -161,9 +173,9 @@ const ElementTemplate *Tileset::getByIdx(size_t idx) return dummy; } -const ElementTemplate* Tileset::getAdjacent(size_t idx, int direction, bool wraparound) +const ElementTemplate* Tileset::getAdjacent(size_t idx, int direction, bool wraparound, size_t maxidx) { - ElementTemplate *et = _getAdjacent(idx, direction, wraparound); + ElementTemplate *et = _getAdjacent(idx, direction, wraparound, maxidx); if(et) et->finalize(); // load just in case return et; @@ -207,10 +219,17 @@ void ElementTemplate::finalize() } } -ElementTemplate * Tileset::_getAdjacent(size_t idx, int direction, bool wraparound) +ElementTemplate * Tileset::_getAdjacent(size_t idx, int direction, bool wraparound, size_t maxidx) { assert(direction == 1 || direction == -1); + const size_t maxn = elementTemplates.size(); + if(!maxn) + return NULL; + + if(idx >= maxidx) + return NULL; + size_t closest = 0; int mindiff = 0; for (size_t i = 0; i < maxn; i++) @@ -220,14 +239,16 @@ ElementTemplate * Tileset::_getAdjacent(size_t idx, int direction, bool wraparou if(wraparound) { if(!i && direction < 0) - return elementTemplates.back(); - if(i + direction >= maxn) + for(size_t k = maxn; k --> 0; ) + if(elementTemplates[k]->idx < maxidx) + return elementTemplates[k]; + if(i + direction >= maxn || elementTemplates[i+direction]->idx >= maxidx) return elementTemplates[0]; } - else + i += direction; // may underflow - return i < maxn ? elementTemplates[i] : NULL; + return i < maxn && elementTemplates[i]->idx < maxidx ? elementTemplates[i] : NULL; } int diff = labs((int)elementTemplates[i]->idx - (int)idx); if(diff < mindiff || !mindiff) @@ -247,11 +268,13 @@ ElementTemplate * Tileset::_getAdjacent(size_t idx, int direction, bool wraparou else if(wraparound) { if(!closest && direction < 0) - return elementTemplates.back(); - if(closest + direction >= maxn) + for(size_t k = maxn; k --> 0; ) + if(elementTemplates[k]->idx < maxidx) + return elementTemplates[k]; + if(closest + direction >= maxn || elementTemplates[closest+direction]->idx >= maxidx) return elementTemplates[0]; } size_t i = closest + direction; - return i < maxn ? elementTemplates[i] : NULL; + return i < maxn && elementTemplates[i]->idx < maxidx ? elementTemplates[i] : NULL; } diff --git a/BBGE/Tileset.h b/BBGE/Tileset.h index 994dc83..536ad88 100644 --- a/BBGE/Tileset.h +++ b/BBGE/Tileset.h @@ -13,7 +13,6 @@ class ElementTemplate public: ElementTemplate() { w=0; h=0; idx=-1; tc.setStandard(); grid = NULL; } ~ElementTemplate(); - inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; } void finalize(); // call after settings params @@ -46,14 +45,16 @@ public: // return valid ET if found, or creates a dummy if not. never returns NULL. const ElementTemplate *getByIdx(size_t idx); + const ElementTemplate *getIfExists(size_t idx); + // search for non-dummy ET in a given direction. used to cycle through ETs. // never returns dummy ET. May return NULL. - const ElementTemplate *getAdjacent(size_t idx, int direction, bool wraparound); + const ElementTemplate *getAdjacent(size_t idx, int direction, bool wraparound, size_t maxidx); std::vector elementTemplates; private: - ElementTemplate *_getAdjacent(size_t idx, int direction, bool wraparound); + ElementTemplate *_getAdjacent(size_t idx, int direction, bool wraparound, size_t maxidx); std::vector dummies; };