From 7c98cba1f5821df24cdc4052a25b2c52b75f3650 Mon Sep 17 00:00:00 2001 From: dnk-88 Date: Tue, 28 Jun 2011 02:55:38 +0300 Subject: [PATCH] Changed: #1301 Binding 2d renderer to NELLIGO. --HG-- branch : gsoc2011-worldeditorqt --- .../plugins/landscape_editor/builder_zone.cpp | 256 +- .../plugins/landscape_editor/builder_zone.h | 77 +- .../landscape_editor/builder_zone_region.cpp | 2084 +++++++++++++++++ .../landscape_editor/builder_zone_region.h | 134 +- .../landscape_editor/landscape_actions.cpp | 103 +- .../landscape_editor/landscape_actions.h | 56 +- .../landscape_editor_window.cpp | 22 +- .../landscape_editor_window.h | 3 - .../landscape_editor/landscape_scene.cpp | 213 +- .../landscape_editor/landscape_scene.h | 45 +- .../landscape_editor/list_zones_widget.cpp | 32 +- .../landscape_editor/list_zones_widget.h | 9 +- .../landscape_editor/zone_region_editor.cpp | 66 + .../landscape_editor/zone_region_editor.h | 36 + 14 files changed, 2904 insertions(+), 232 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp index 288a4b1be..8271fe37c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp @@ -17,6 +17,8 @@ // Project includes #include "builder_zone.h" +#include "list_zones_widget.h" +#include "landscape_actions.h" // NeL includes #include @@ -29,9 +31,9 @@ namespace LandscapeEditor { -const int PixmapScale = 256; PixmapDatabase::PixmapDatabase() + : m_textureSize(256) { } @@ -66,15 +68,21 @@ bool PixmapDatabase::loadPixmaps(const QString &zonePath, NLLIGO::CZoneBank &zon // Generate filled pixmap } // All pixmaps must be have same size - if (pixmap->width() != sizeX * PixmapScale) + if (pixmap->width() != sizeX * m_textureSize) { - QPixmap *scaledPixmap = new QPixmap(pixmap->scaled(sizeX * PixmapScale, sizeY * PixmapScale)); + QPixmap *scaledPixmap = new QPixmap(pixmap->scaled(sizeX * m_textureSize, sizeY * m_textureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); delete pixmap; m_pixmapMap.insert(zonePixmapName, scaledPixmap); } else m_pixmapMap.insert(zonePixmapName, pixmap); } + + QPixmap *pixmap = new QPixmap(zonePath + "_UNUSED_.png"); + QPixmap *scaledPixmap = new QPixmap(pixmap->scaled(m_textureSize, m_textureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + delete pixmap; + m_pixmapMap.insert(QString(STRING_UNUSED), scaledPixmap); + delete progressDialog; return true; } @@ -105,8 +113,17 @@ QPixmap *PixmapDatabase::pixmap(const QString &zoneName) const return result; } -ZoneBuilder::ZoneBuilder() - : m_pixmapDatabase(0) +int PixmapDatabase::textureSize() const +{ + return m_textureSize; +} + +ZoneBuilder::ZoneBuilder(ListZonesWidget *listZonesWidget, LandscapeScene *landscapeScene, QUndoStack *undoStack) + : m_currentZoneRegion(-1), + m_pixmapDatabase(0), + m_listZonesWidget(listZonesWidget), + m_landscapeScene(landscapeScene), + m_undoStack(undoStack) { m_pixmapDatabase = new PixmapDatabase(); m_lastPathName = ""; @@ -144,10 +161,131 @@ bool ZoneBuilder::init(const QString &pathName, bool makeAZone) } } if ((makeAZone) && (bRet)) - newZone(); + createZoneRegion(); return bRet; } +void ZoneBuilder::actionLigoTile(const LigoData &data, const ZonePosition &zonePos) +{ + nlinfo(QString("%1 %2 %3 (%4 %5)").arg(data.zoneName.c_str()).arg(zonePos.x).arg(zonePos.y).arg(data.posX).arg(data.posY).toStdString().c_str()); + m_undoStack->push(new LigoTileCommand(data, zonePos, this, m_landscapeScene)); +} + +void ZoneBuilder::actionLigoMove(uint index, sint32 deltaX, sint32 deltaY) +{ + nlinfo("ligoMove"); + //m_undoStack->push(new LigoMoveCommand(index, deltaX, deltaY, this)); +} + +void ZoneBuilder::actionLigoResize(uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) +{ + nlinfo(QString("minX=%1 maxX=%2 minY=%3 maxY=%4").arg(newMinX).arg(newMaxX).arg(newMinY).arg(newMaxY).toStdString().c_str()); + m_undoStack->push(new LigoResizeCommand(index, newMinX, newMaxX, newMinY, newMaxY, this)); +} + +void ZoneBuilder::addZone(sint32 posX, sint32 posY) +{ + if (m_builderZoneRegions.empty()) + return; + + std::string zoneName = m_listZonesWidget->currentZoneName().toStdString(); + if (zoneName.empty()) + return; + + std::string error; + BuilderZoneRegion *builderZoneRegion = m_builderZoneRegions.at(m_currentZoneRegion); + builderZoneRegion->init(this, error); + + uint8 rot = uint8(m_listZonesWidget->currentRot()); + uint8 flip = uint8(m_listZonesWidget->currentFlip()); + + NLLIGO::CZoneBankElement *zoneBankElement = getZoneBank().getElementByZoneName(zoneName); + + m_undoStack->beginMacro(QString("Add zone %1,%2").arg(posX).arg(posY)); + if (m_listZonesWidget->isForce()) + { + builderZoneRegion->addForce(posX, posY, rot, flip, zoneBankElement); + } + else + { + if (m_listZonesWidget->isNotPropogate()) + builderZoneRegion->addNotPropagate(posX, posY, rot, flip, zoneBankElement); + else + builderZoneRegion->add(posX, posY, rot, flip, zoneBankElement); + } + m_undoStack->endMacro(); +} + +void ZoneBuilder::addTransition(const sint32 posX, const sint32 posY) +{ +} + +void ZoneBuilder::delZone(const sint32 posX, const sint32 posY) +{ + if (m_builderZoneRegions.empty()) + return; + + m_undoStack->beginMacro(QString("Del zone %1,%2").arg(posX).arg(posY)); + BuilderZoneRegion *builderZoneRegion = m_builderZoneRegions.at(m_currentZoneRegion); + std::string error; + builderZoneRegion->init(this, error); + builderZoneRegion->del(posX, posY); + m_undoStack->endMacro(); +} + +int ZoneBuilder::createZoneRegion() +{ + ZoneRegionEditor *newZoneRegion = new ZoneRegionEditor(); + m_zoneRegions.push_back(newZoneRegion); + if (m_currentZoneRegion == -1) + m_currentZoneRegion = m_zoneRegions.indexOf(newZoneRegion); + + newZone(); + return m_zoneRegions.indexOf(newZoneRegion); +} + +void ZoneBuilder::deleteZoneRegion(int id) +{ + if ((0 <= id) && (id < m_zoneRegions.size())) + delete m_zoneRegions.takeAt(id); +} + +void ZoneBuilder::setCurrentZoneRegion(int id) +{ + if ((0 <= id) && (id < m_zoneRegions.size())) + m_currentZoneRegion = id; +} + +int ZoneBuilder::currentIdZoneRegion() const +{ + return m_currentZoneRegion; +} + +ZoneRegionEditor *ZoneBuilder::currentZoneRegion() const +{ + return m_zoneRegions.at(m_currentZoneRegion); +} + +int ZoneBuilder::countZoneRegion() const +{ + return m_zoneRegions.size(); +} + +ZoneRegionEditor *ZoneBuilder::zoneRegion(int id) const +{ + return m_zoneRegions.at(id); +} + +void ZoneBuilder::ligoData(LigoData &data, const ZonePosition &zonePos) +{ + m_zoneRegions.at(zonePos.region)->ligoData(data, zonePos.x, zonePos.y); +} + +void ZoneBuilder::setLigoData(LigoData &data, const ZonePosition &zonePos) +{ + m_zoneRegions.at(zonePos.region)->setLigoData(data, zonePos.x, zonePos.y); +} + bool ZoneBuilder::initZoneBank (const QString &pathName) { QDir *dir = new QDir(pathName); @@ -178,8 +316,112 @@ QString ZoneBuilder::dataPath() const return m_lastPathName; } -void ZoneBuilder::newZone (bool bDisplay) +void ZoneBuilder::newZone() { + BuilderZoneRegion *builderZoneRegion = new BuilderZoneRegion(m_builderZoneRegions.size()); + m_builderZoneRegions.push_back(builderZoneRegion); + + // Select starting point for the moment 0,0 + sint32 x = 0, y = 0; + + // If there are some zone already present increase x until free + for (int i = 0; i < m_zoneRegions.size(); ++i) + { + const NLLIGO::CZoneRegion &zoneRegion = m_zoneRegions.at(i)->zoneRegion(); + const std::string &zoneName = zoneRegion.getName (x, y); + if ((zoneName != STRING_OUT_OF_BOUND) && (zoneName != STRING_UNUSED)) + { + ++x; + i = -1; + } + } + calcMask(); +} + +bool ZoneBuilder::getZoneMask(sint32 x, sint32 y) +{ + if ((x < m_minX) || (x > m_maxX) || + (y < m_minY) || (y > m_maxY)) + { + return true; + } + else + { + return m_zoneMask[(x - m_minX) + (y - m_minY) * (1 + m_maxX - m_minX)]; + } +} + +void ZoneBuilder::calcMask() +{ + sint32 i; + sint32 x, y; + + m_minY = m_minX = 1000000; + m_maxY = m_maxX = -1000000; + + if (m_builderZoneRegions.size() == 0) + return; + + for (i = 0; i < (sint32)m_builderZoneRegions.size(); ++i) + { + const NLLIGO::CZoneRegion ®ion = zoneRegion(i)->zoneRegion(); + + if (m_minX > region.getMinX()) + m_minX = region.getMinX(); + if (m_minY > region.getMinY()) + m_minY = region.getMinY(); + if (m_maxX < region.getMaxX()) + m_maxX = region.getMaxX(); + if (m_maxY < region.getMaxY()) + m_maxY = region.getMaxY(); + } + + m_zoneMask.resize ((1 + m_maxX - m_minX) * (1 + m_maxY - m_minY)); + sint32 stride = (1 + m_maxX - m_minX); + for (y = m_minY; y <= m_maxY; ++y) + for (x = m_minX; x <= m_maxX; ++x) + { + m_zoneMask[x - m_minX + (y - m_minY) * stride] = true; + + for (i = 0; i < (sint32)m_builderZoneRegions.size(); ++i) + if (i != m_currentZoneRegion) + { + const NLLIGO::CZoneRegion ®ion = zoneRegion(i)->zoneRegion(); + + const std::string &rSZone = region.getName (x, y); + if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) + { + m_zoneMask[x - m_minX + (y - m_minY) * stride] = false; + } + } + } +} + +bool ZoneBuilder::getZoneAmongRegions (ZonePosition &zonePos, BuilderZoneRegion *builderZoneRegionFrom, sint32 x, sint32 y) +{ + Q_FOREACH(ZoneRegionEditor *zoneRegion, m_zoneRegions) + { + const NLLIGO::CZoneRegion ®ion = zoneRegion->zoneRegion(); + if ((x < region.getMinX()) || (x > region.getMaxX()) || + (y < region.getMinY()) || (y > region.getMaxY())) + continue; + if (region.getName(x, y) != STRING_UNUSED) + { + int index = m_zoneRegions.indexOf(zoneRegion); + builderZoneRegionFrom = m_builderZoneRegions.at(index); + zonePos = ZonePosition(x, y, index); + return true; + } + } + + // The zone is not present in other region so it is an empty or oob zone of the current region + const NLLIGO::CZoneRegion ®ion = zoneRegion(builderZoneRegionFrom->getRegionId())->zoneRegion(); + if ((x < region.getMinX()) || (x > region.getMaxX()) || + (y < region.getMinY()) || (y > region.getMaxY())) + return false; // Out Of Bound + + zonePos = ZonePosition(x, y, builderZoneRegionFrom->getRegionId()); + return true; } } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h index f43bb7d7e..54cdb3b73 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h @@ -19,9 +19,12 @@ #define BUILDER_ZONE_H // Project includes +#include "builder_zone_region.h" +#include "zone_region_editor.h" // NeL includes #include +#include // STL includes #include @@ -30,11 +33,38 @@ // Qt includes #include #include +#include #include #include +#include namespace LandscapeEditor { +class ListZonesWidget; +class LandscapeScene; + +// Data +struct ZonePosition +{ + // Absolute position + sint32 x; + sint32 y; + int region; + + ZonePosition() + { + x = 0xffffffff; + y = 0xffffffff; + region = -1; + } + + ZonePosition(const sint32 posX, const sint32 posY, const int id) + { + x = posX; + y = posY; + region = id; + } +}; /** @class PixmapDatabase @@ -59,8 +89,12 @@ public: /// Get original pixmap /// @return QPixmap* if the image is in the database ; otherwise returns 0. QPixmap *pixmap(const QString &zoneName) const; + + int textureSize() const; + private: + int m_textureSize; QMap m_pixmapMap; }; @@ -74,13 +108,37 @@ PixmapDatabase contains the graphics for the zones class ZoneBuilder { public: - ZoneBuilder(); + ZoneBuilder(ListZonesWidget *listZonesWidget, LandscapeScene *landscapeScene, QUndoStack *undoStack); ~ZoneBuilder(); - // Init zoneBank and init zone pixmap database + /// Init zoneBank and init zone pixmap database bool init(const QString &pathName, bool bMakeAZone); - void newZone(bool bDisplay=true); + void calcMask(); + void newZone(); + bool getZoneMask (sint32 x, sint32 y); + bool getZoneAmongRegions(ZonePosition &zonePos, BuilderZoneRegion *builderZoneRegionFrom, sint32 x, sint32 y); + + // Ligo Actions + void actionLigoTile(const LigoData &data, const ZonePosition &zonePos); + void actionLigoMove(uint index, sint32 deltaX, sint32 deltaY); + void actionLigoResize(uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); + + // Zone Bricks + void addZone(sint32 posX, sint32 posY); + void addTransition(const sint32 posX, const sint32 posY); + void delZone(const sint32 posX, const sint32 posY); + + // Zone Region + int createZoneRegion(); + void deleteZoneRegion(int id); + void setCurrentZoneRegion(int id); + int currentIdZoneRegion() const; + ZoneRegionEditor *currentZoneRegion() const; + int countZoneRegion() const; + ZoneRegionEditor *zoneRegion(int id) const; + void ligoData(LigoData &data, const ZonePosition &zonePos); + void setLigoData(LigoData &data, const ZonePosition &zonePos); // Accessors NLLIGO::CZoneBank &getZoneBank() @@ -94,15 +152,24 @@ public: private: - // Scan ./zoneligos dir and add all *.ligozone files to zoneBank + /// Scan ./zoneligos dir and add all *.ligozone files to zoneBank bool initZoneBank (const QString &path); sint32 m_minX, m_maxX, m_minY, m_maxY; + std::vector m_zoneMask; + QString m_lastPathName; + QList m_zoneRegions; + int m_currentZoneRegion; + + std::vector m_builderZoneRegions; + PixmapDatabase *m_pixmapDatabase; NLLIGO::CZoneBank m_zoneBank; - std::vector m_currentSelection; + ListZonesWidget *m_listZonesWidget; + LandscapeScene *m_landscapeScene; + QUndoStack *m_undoStack; }; } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp index 4dbd3e9e1..2a4fc204a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp @@ -17,6 +17,8 @@ // Project includes #include "builder_zone_region.h" +#include "builder_zone.h" +#include "zone_region_editor.h" // NeL includes #include @@ -25,4 +27,2086 @@ namespace LandscapeEditor { + +BuilderZoneRegion::BuilderZoneRegion(uint regionId) + : m_regionId(regionId), + m_zoneBuilder(0), + m_firstInit(false) +{ +} + +bool BuilderZoneRegion::init(ZoneBuilder *zoneBuilder, std::string &error) +{ + if (m_firstInit) + return true; + + m_zoneBuilder = zoneBuilder; + + uint32 j, k; + SMatNode mn; + std::vector AllValues; + + // Build the material tree + m_zoneBuilder->getZoneBank().getCategoryValues("material", AllValues); + for (uint32 i = 0; i < AllValues.size(); ++i) + { + mn.Name = AllValues[i]; + m_matTree.push_back(mn); + } + + // Link between materials + AllValues.clear (); + m_zoneBuilder->getZoneBank().getCategoryValues("transname", AllValues); + for (uint32 i = 0; i < AllValues.size(); ++i) + { + // Get the 2 materials linked together + std::string matAstr, matBstr; + for (j = 0; j < AllValues[i].size(); ++j) + { + if (AllValues[i][j] == '-') + break; + else + matAstr += AllValues[i][j]; + } + ++j; + for (; j < AllValues[i].size(); ++j) + matBstr += AllValues[i][j]; + + // Find matA + for (j = 0; j < m_matTree.size(); ++j) + if (m_matTree[j].Name == matAstr) + break; + + if (j < m_matTree.size()) + { + // Find matB + for (k = 0; k < m_matTree.size(); ++k) + if (m_matTree[k].Name == matBstr) + break; + + if (k < m_matTree.size()) + { + // Add a ref to matB in node matA + m_matTree[j].Arcs.push_back(k); + + // Add a ref to matA in node matB + m_matTree[k].Arcs.push_back(j); + } + } + } + + m_firstInit = true; + return true; +} + +class ToUpdate +{ + struct SElement + { + sint32 x, y; + + // Material put into the cell to update + std::string matPut; + + BuilderZoneRegion *builderZoneRegion; + }; + + std::vector m_elements; + +public: + + void add(BuilderZoneRegion *builderZoneRegion, sint32 x, sint32 y, const std::string &matName) + { + bool bFound = false; + for (uint32 m = 0; m < m_elements.size(); ++m) + if ((m_elements[m].x == x) && (m_elements[m].y == y)) + { + bFound = true; + break; + } + if (!bFound) + { + SElement newElement; + newElement.x = x; + newElement.y = y; + newElement.matPut = matName; + newElement.builderZoneRegion = builderZoneRegion; + m_elements.push_back (newElement); + } + } + + void del(sint32 x, sint32 y) + { + bool bFound = false; + uint32 m; + for (m = 0; m < m_elements.size(); ++m) + if ((m_elements[m].x == x) && (m_elements[m].y == y)) + { + bFound = true; + break; + } + if (bFound) + { + for (; m < m_elements.size() - 1; ++m) + m_elements[m] = m_elements[m + 1]; + m_elements.resize (m_elements.size() - 1); + } + } + + uint32 size() + { + return m_elements.size(); + } + + sint32 getX(uint32 m) + { + return m_elements[m].x; + } + + sint32 getY(uint32 m) + { + return m_elements[m].y; + } + + BuilderZoneRegion* getBuilderZoneRegion(uint32 m) + { + return m_elements[m].builderZoneRegion; + } + + const std::string& getMat (uint32 m) + { + return m_elements[m].matPut; + } +}; + +void BuilderZoneRegion::add(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 i, j; + NLLIGO::SPiece sMask, sPosX, sPosY; + ToUpdate tUpdate; // Transition to update + + if (!m_zoneBuilder->getZoneMask (x,y)) + return; + + if (zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, rot, flip, zoneBankElement); + return; + } + + // Create the mask in the good rotation and flip + sMask.Tab.resize(sizeX * sizeY); + sPosX.Tab.resize(sizeX * sizeY); + sPosY.Tab.resize(sizeX * sizeY); + + for(j = 0; j < sizeY; ++j) + for(i = 0; i < sizeX; ++i) + { + sPosX.Tab[i + j * sizeX] = (uint8)i; + sPosY.Tab[i + j * sizeX] = (uint8)j; + sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip(rot, flip); + sPosX.rotFlip(rot, flip); + sPosY.rotFlip(rot, flip); + + // Test if the pieces can be put (due to mask) + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + if (m_zoneBuilder->getZoneMask(x + i, y + j) == false) + return; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + del(x + i, y + j, true, &tUpdate); + } + + // Delete all around all material that are not from the same as us + const std::string &curMat = zoneBankElement->getCategory ("material"); + + if (curMat != STRING_NO_CAT_TYPE) + { + // This element is a valid material + // Place the piece + const std::string &eltName = zoneBankElement->getName (); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + set(x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], eltName); + setRot(x + i, y + j, rot); + setFlip(x + i, y + j, flip); + } + + // Put all transitions between different materials + putTransitions (x, y, sMask, curMat, &tUpdate); + + // Place the piece + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + set(x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], eltName); + setRot(x + i, y + j, rot); + setFlip(x + i, y + j, flip); + } + } +} + +void BuilderZoneRegion::invertCutEdge(sint32 x, sint32 y, uint8 cePos) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || + (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) + return; + + NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName(x, y)); + if (zoneBankElement == NULL) + return; + if (zoneBankElement->getCategory("transname") == STRING_NO_CAT_TYPE) + return; + + + ZonePosition zonePos(x, y, m_regionId); + LigoData dataZone; + + m_zoneBuilder->ligoData(dataZone, zonePos); + if (dataZone.sharingCutEdges[cePos] != 3 - dataZone.sharingCutEdges[cePos]) + { + dataZone.sharingCutEdges[cePos] = 3 - dataZone.sharingCutEdges[cePos]; + + m_zoneBuilder->actionLigoTile(dataZone, zonePos); + } + updateTrans(x, y); + + // If the transition number is not the same propagate the change + // Propagate where the edge is cut (1/3 or 2/3) and update the transition + if (cePos == 2) + if (dataZone.sharingMatNames[0] != dataZone.sharingMatNames[2]) + { + if (x > zoneRegion.getMinX ()) + { + // [x-1][y].right = [x][y].left + // _Zones[(x-1-zoneRegion->getMinX ())+(y-zoneRegion->getMinY ())*stride].SharingCutEdges[3] = dataZonePos.SharingCutEdges[2]; + ZonePosition zonePosTemp(x - 1, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[3] != dataZone.sharingCutEdges[2]) + { + dataZoneTemp.sharingCutEdges[3] = dataZone.sharingCutEdges[2]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x - 1, y); + } + if (cePos == 3) + if (dataZone.sharingMatNames[1] != dataZone.sharingMatNames[3]) + { + if (x < zoneRegion.getMaxX ()) + { + // [x+1][y].left = [x][y].right + ZonePosition zonePosTemp(x + 1, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[2] != dataZone.sharingCutEdges[3]) + { + dataZoneTemp.sharingCutEdges[2] = dataZone.sharingCutEdges[3]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x + 1, y); + } + if (cePos == 1) + if (dataZone.sharingMatNames[0] != dataZone.sharingMatNames[1]) + { + if (y > zoneRegion.getMinY ()) + { + // [x][y-1].up = [x][y].down + ZonePosition zonePosTemp(x, y - 1, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[0] != dataZone.sharingCutEdges[1]) + { + dataZoneTemp.sharingCutEdges[0] = dataZone.sharingCutEdges[1]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x, y-1); + } + if (cePos == 0) + if (dataZone.sharingMatNames[2] != dataZone.sharingMatNames[3]) + { + if (y < zoneRegion.getMaxY ()) + { + // [x][y+1].down = [x][y].up + ZonePosition zonePosTemp(x, y + 1, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[1] != dataZone.sharingCutEdges[0]) + { + dataZoneTemp.sharingCutEdges[1] = dataZone.sharingCutEdges[0]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x, y + 1); + } +} + +void BuilderZoneRegion::cycleTransition(sint32 x, sint32 y) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || + (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) + return; + + NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName (zoneRegion.getName (x, y)); + if (zoneBankElement == NULL) + return; + if (zoneBankElement->getCategory("transname") == STRING_NO_CAT_TYPE) + return; + + // \todo trap -> choose the good transition in function of the transition under the current location + // Choose the next possible transition if not the same as the first one + // Choose among all transition of the same number + + updateTrans (x, y); +} + +bool BuilderZoneRegion::addNotPropagate (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 i, j; + NLLIGO::SPiece sMask, sPosX, sPosY; + ToUpdate tUpdate; // Transition to update + + if (!m_zoneBuilder->getZoneMask (x, y)) + return false; + + if (zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, rot, flip, zoneBankElement); + return true; + } + + // Create the mask in the good rotation and flip + sMask.Tab.resize (sizeX * sizeY); + sPosX.Tab.resize (sizeX * sizeY); + sPosY.Tab.resize (sizeX * sizeY); + + for (j = 0; j < sizeY; ++j) + for (i = 0; i < sizeX; ++i) + { + sPosX.Tab[i + j * sizeX] = (uint8)i; + sPosY.Tab[i + j * sizeX] = (uint8)j; + sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip (rot, flip); + sPosX.rotFlip (rot, flip); + sPosY.rotFlip (rot, flip); + + // Test if the pieces can be put (due to mask) + sint32 stride = (1 + zoneRegion.getMaxX () - zoneRegion.getMinX ()); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (m_zoneBuilder->getZoneMask(x + i, y + j) == false) + return false; + if (((x + i) < zoneRegion.getMinX ()) || ((x + i) > zoneRegion.getMaxX ()) || + ((y + j) < zoneRegion.getMinY ()) || ((y + j) > zoneRegion.getMaxY ())) + return false; + NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x + i, y + j)); + if (zoneBankElementUnder == NULL) + return false; + if (zoneBankElementUnder->getCategory("material") != zoneBankElement->getCategory("material")) + return false; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + del(x + i, y + j, true, &tUpdate); + } + + const std::string &curMat = zoneBankElement->getCategory ("material"); + + if (curMat != STRING_NO_CAT_TYPE) + { + // This element is a valid material + // Place the piece + const std::string &EltName = zoneBankElement->getName (); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + set (x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], EltName); + setRot (x + i, y + j, rot); + setFlip (x + i, y + j, flip); + } + } + + return true; +} + +void BuilderZoneRegion::addForce (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 i, j; + NLLIGO::SPiece sMask, sPosX, sPosY; + ToUpdate tUpdate; // Transition to update + + if (!m_zoneBuilder->getZoneMask (x, y)) + return; + + /* + if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, nRot, nFlip, pElt); + return; + }*/ + + // Create the mask in the good rotation and flip + sMask.Tab.resize (sizeX * sizeY); + sPosX.Tab.resize (sizeX * sizeY); + sPosY.Tab.resize (sizeX * sizeY); + + for (j = 0; j < sizeY; ++j) + for (i = 0; i < sizeX; ++i) + { + sPosX.Tab[i + j * sizeX] = (uint8)i; + sPosY.Tab[i + j * sizeX] = (uint8)j; + sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip (rot, flip); + sPosX.rotFlip (rot, flip); + sPosY.rotFlip (rot, flip); + + // Test if the pieces can be put (due to mask) + // All space under the mask must be empty + sint32 stride = (1 + zoneRegion.getMaxX () - zoneRegion.getMinX ()); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (m_zoneBuilder->getZoneMask(x+i, y+j) == false) + return; + if (((x+i) < zoneRegion.getMinX ()) || ((x+i) > zoneRegion.getMaxX ()) || + ((y+j) < zoneRegion.getMinY ()) || ((y+j) > zoneRegion.getMaxY ())) + return; + NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x + i, y + i)); + if (zoneBankElementUnder != NULL) + return; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + del(x+i, y+j, true, &tUpdate); + } + + const std::string &curMat = zoneBankElement->getCategory ("material"); + const bool transition = zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE; + + if (curMat != STRING_NO_CAT_TYPE || transition) + { + // This element is a valid material + // Place the piece + const std::string &eltName = zoneBankElement->getName(); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + set(x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], eltName, transition); + setRot(x + i, y + j, rot); + setFlip(x + i, y + j, flip); + } + } +} + +uint8 TransToEdge[72][4] = +{ + { 0, 0, 1, 1 }, // TransNum = 0, Flip = 0, Rot = 0 + { 2, 2, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 1 + { 0, 0, 2, 2 }, // TransNum = 0, Flip = 0, Rot = 2 + { 1, 1, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 3 + { 0, 0, 1, 1 }, // TransNum = 0, Flip = 1, Rot = 0 + { 2, 2, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 1 + { 0, 0, 2, 2 }, // TransNum = 0, Flip = 1, Rot = 2 + { 1, 1, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 3 + + { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 0 + { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 1 + { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 2 + { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 3 + { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 0 + { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 1 + { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 2 + { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 3 + + { 0, 0, 2, 2 }, // TransNum = 2, Flip = 0, Rot = 0 + { 1, 1, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 1 + { 0, 0, 1, 1 }, // TransNum = 2, Flip = 0, Rot = 2 + { 2, 2, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 3 + { 0, 0, 2, 2 }, // TransNum = 2, Flip = 1, Rot = 0 + { 1, 1, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 1 + { 0, 0, 1, 1 }, // TransNum = 2, Flip = 1, Rot = 2 + { 2, 2, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 3 + + { 0, 1, 1, 0 }, // TransNum = 3, Flip = 0, Rot = 0 + { 0, 2, 0, 1 }, // TransNum = 3, Flip = 0, Rot = 1 + { 2, 0, 0, 2 }, // TransNum = 3, Flip = 0, Rot = 2 + { 1, 0, 2, 0 }, // TransNum = 3, Flip = 0, Rot = 3 + { 0, 2, 0, 1 }, // TransNum = 3, Flip = 1, Rot = 0 + { 2, 0, 0, 2 }, // TransNum = 3, Flip = 1, Rot = 1 + { 1, 0, 2, 0 }, // TransNum = 3, Flip = 1, Rot = 2 + { 0, 1, 1, 0 }, // TransNum = 3, Flip = 1, Rot = 3 + + { 0, 2, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 0 + { 0, 2, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 1 + { 1, 0, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 2 + { 1, 0, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 3 + { 0, 1, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 0 + { 2, 0, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 1 + { 2, 0, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 2 + { 0, 1, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 3 + + { 0, 2, 2, 0 }, // TransNum = 5, Flip = 0, Rot = 0 + { 0, 1, 0, 2 }, // TransNum = 5, Flip = 0, Rot = 1 + { 1, 0, 0, 1 }, // TransNum = 5, Flip = 0, Rot = 2 + { 2, 0, 1, 0 }, // TransNum = 5, Flip = 0, Rot = 3 + { 0, 1, 0, 2 }, // TransNum = 5, Flip = 1, Rot = 0 + { 1, 0, 0, 1 }, // TransNum = 5, Flip = 1, Rot = 1 + { 2, 0, 1, 0 }, // TransNum = 5, Flip = 1, Rot = 2 + { 0, 2, 2, 0 }, // TransNum = 5, Flip = 1, Rot = 3 + + { 0, 1, 1, 0 }, // TransNum = 6, Flip = 0, Rot = 0 + { 0, 2, 0, 1 }, // TransNum = 6, Flip = 0, Rot = 1 + { 2, 0, 0, 2 }, // TransNum = 6, Flip = 0, Rot = 2 + { 1, 0, 2, 0 }, // TransNum = 6, Flip = 0, Rot = 3 + { 0, 2, 0, 1 }, // TransNum = 6, Flip = 1, Rot = 0 + { 2, 0, 0, 2 }, // TransNum = 6, Flip = 1, Rot = 1 + { 1, 0, 2, 0 }, // TransNum = 6, Flip = 1, Rot = 2 + { 0, 1, 1, 0 }, // TransNum = 6, Flip = 1, Rot = 3 + + { 0, 2, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 0 + { 0, 2, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 1 + { 1, 0, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 2 + { 1, 0, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 3 + { 0, 1, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 0 + { 2, 0, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 1 + { 2, 0, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 2 + { 0, 1, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 3 + + { 0, 2, 2, 0 }, // TransNum = 8, Flip = 0, Rot = 0 + { 0, 1, 0, 2 }, // TransNum = 8, Flip = 0, Rot = 1 + { 1, 0, 0, 1 }, // TransNum = 8, Flip = 0, Rot = 2 + { 2, 0, 1, 0 }, // TransNum = 8, Flip = 0, Rot = 3 + { 0, 1, 0, 2 }, // TransNum = 8, Flip = 1, Rot = 0 + { 1, 0, 0, 1 }, // TransNum = 8, Flip = 1, Rot = 1 + { 2, 0, 1, 0 }, // TransNum = 8, Flip = 1, Rot = 2 + { 0, 2, 2, 0 }, // TransNum = 8, Flip = 1, Rot = 3 +}; + +void BuilderZoneRegion::addTransition (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + uint32 i; + // Check that we write in an already defined place + if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || + (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) + return; + + // Check size + if ((zoneBankElement->getSizeX() != 1) || (zoneBankElement->getSizeY() != 1)) + return; + + // Check that an element already exist at position we want put the transition + NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName(x, y)); + if (zoneBankElementUnder == NULL) + return; + + // And check that this element is also a transition and the same transition + if (zoneBankElementUnder->getCategory ("transname") == STRING_NO_CAT_TYPE) + return; + if (zoneBankElementUnder->getCategory ("transname") != zoneBankElement->getCategory("transname")) + return; + + std::string underType = zoneBankElementUnder->getCategory("transtype"); + std::string overType = zoneBankElement->getCategory("transtype"); + std::string underNum = zoneBankElementUnder->getCategory("transnum"); + std::string overNum = zoneBankElement ->getCategory("transnum"); + + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + LigoData dataZoneOriginal = dataZoneTemp; + + bool bMustPropagate = false; + // Same type of transition ? + if (zoneBankElementUnder->getCategory("transtype") != zoneBankElement->getCategory("transtype")) + { + // No so random the cutEdges + for (i = 0; i < 4; ++i) + { + uint8 nCut = (uint8)(1.0f + NLMISC::frand(2.0f)); + NLMISC::clamp(nCut, (uint8)1, (uint8)2); + + dataZoneTemp.sharingCutEdges[i] = nCut; + } + zoneBankElement = NULL; + bMustPropagate = true; + } + else + { + // Put exactly the transition as given + sint32 transnum = atoi(zoneBankElement->getCategory("transnum").c_str()); + sint32 flip = zoneRegion.getFlip(x, y); + sint32 rot = zoneRegion.getRot(x, y); + sint32 pos1 = -1, pos2 = -1; + + for (i = 0; i < 4; ++i) + { + if ((TransToEdge[transnum * 8 + flip * 4 + rot][i] != 0) && + (TransToEdge[transnum * 8 + flip * 4 + rot][i] != dataZoneTemp.sharingCutEdges[i])) + bMustPropagate = true; + + dataZoneTemp.sharingCutEdges[i] = TransToEdge[transnum * 8 + flip * 4 + rot][i]; + + if ((pos1 != -1) && (dataZoneTemp.sharingCutEdges[i] != 0)) + pos2 = i; + if ((pos1 == -1) && (dataZoneTemp.sharingCutEdges[i] != 0)) + pos1 = i; + } + // Exchange cutedges != 0 one time /2 to permit all positions + if ((transnum == 1) || (transnum == 4) || (transnum == 7)) + if (zoneBankElement->getName() == zoneBankElementUnder->getName()) + { + bMustPropagate = true; + + dataZoneTemp.sharingCutEdges[pos1] = 3 - dataZoneTemp.sharingCutEdges[pos1]; + dataZoneTemp.sharingCutEdges[pos2] = 3 - dataZoneTemp.sharingCutEdges[pos2]; + } + } + if (dataZoneTemp != dataZoneOriginal) + { + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + updateTrans (x, y, zoneBankElement); + + // If the transition number is not the same propagate the change + if (bMustPropagate) + { + // Propagate where the edge is cut (1/3 or 2/3) and update the transition + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[2]) + { + if (x > zoneRegion.getMinX ()) + { + // [x-1][y].right = [x][y].left + // _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; + ZonePosition zonePosTemp2(x - 1, y, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[3] != dataZoneTemp.sharingCutEdges[2]) + { + dataZoneTemp2.sharingCutEdges[3] = dataZoneTemp.sharingCutEdges[2]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x - 1, y); + } + if (dataZoneTemp.sharingMatNames[1] != dataZoneTemp.sharingMatNames[3]) + { + if (x < zoneRegion.getMaxX ()) + { + // [x+1][y].left = [x][y].right + //_Zones[(x+1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; + ZonePosition zonePosTemp2(x + 1, y, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[2] != dataZoneTemp.sharingCutEdges[3]) + { + dataZoneTemp2.sharingCutEdges[2] = dataZoneTemp.sharingCutEdges[3]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x + 1, y); + } + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1]) + { + if (y > zoneRegion.getMinY ()) + { + // [x][y-1].up = [x][y].down + //_Zones[(x-pBZR->getMinX ())+(y-1-pBZR->getMinY ())*stride].SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; + ZonePosition zonePosTemp2(x, y - 1, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[0] != dataZoneTemp.sharingCutEdges[1]) + { + dataZoneTemp2.sharingCutEdges[0] = dataZoneTemp.sharingCutEdges[1]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x, y - 1); + } + if (dataZoneTemp.sharingMatNames[2] != dataZoneTemp.sharingMatNames[3]) + { + if (y < zoneRegion.getMaxY ()) + { + // [x][y+1].down = [x][y].up + //_Zones[(x-pBZR->getMinX ())+(y+1-pBZR->getMinY ())*stride].SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; + ZonePosition zonePosTemp2(x, y + 1, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[1] != dataZoneTemp.sharingCutEdges[0]) + { + dataZoneTemp2.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x, y + 1); + } + } +} + +void BuilderZoneRegion::addToUpdateAndCreate(BuilderZoneRegion* builderZoneRegion, sint32 sharePos, sint32 x, sint32 y, const std::string &newMat, void *pInt1, void *pInt2) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + ToUpdate *ptCreate = reinterpret_cast(pInt1); + ToUpdate *ptUpdate = reinterpret_cast(pInt2); + sint32 stride = (1 + zoneRegion.getMaxX() - zoneRegion.getMinX()); + + ZonePosition zonePos; + if (m_zoneBuilder->getZoneAmongRegions(zonePos, builderZoneRegion, x, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePos); + if (data.sharingMatNames[sharePos] != newMat) + { + data.sharingMatNames[sharePos] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePos); + } + builderZoneRegion->del(x, y, true, ptUpdate); + ptCreate->add(builderZoneRegion, x, y, newMat); + } +} + +void BuilderZoneRegion::putTransitions (sint32 inX, sint32 inY, const NLLIGO::SPiece &mask, const std::string &matName, + void *pInternal) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + ToUpdate tCreate; // Transition to create + ToUpdate *ptUpdate = reinterpret_cast(pInternal); // Transition to update + + sint32 i, j, k, l, m; + sint32 x = inX, y = inY; + for (j = 0; j < mask.h; ++j) + for (i = 0; i < mask.w; ++i) + if (mask.Tab[i + j * mask.w]) + { + for (k = -1; k <= 1; ++k) + for (l = -1; l <= 1; ++l) + { + BuilderZoneRegion *builderZoneRegion2 = this; + ZonePosition zonePos; + if (m_zoneBuilder->getZoneAmongRegions(zonePos, builderZoneRegion2, inX + i + l, inY + j + k)) + tCreate.add(builderZoneRegion2, inX + i + l, inY + j + k, matName); + } + } + + // Check coherency of the transition to update + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + BuilderZoneRegion *builderZoneRegion2 = tCreate.getBuilderZoneRegion(m); + x = tCreate.getX(m); + y = tCreate.getY(m); + std::string putMat = tCreate.getMat(m); + + //if ((x < pBZR->getMinX ())||(x > pBZR->getMaxX ())||(y < pBZR->getMinY ())||(y > pBZR->getMaxY ())) + // continue; + + ZonePosition zoneTemp(x, y, builderZoneRegion2->getRegionId()); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + + if (!((dataZoneTemp.sharingMatNames[0] == dataZoneTemp.sharingMatNames[1])&& + (dataZoneTemp.sharingMatNames[1] == dataZoneTemp.sharingMatNames[2])&& + (dataZoneTemp.sharingMatNames[2] == dataZoneTemp.sharingMatNames[3]))) + builderZoneRegion2->del(x, y, true, ptUpdate); + + // Check to see material can be posed + uint corner; + for (corner = 0; corner < 4; corner++) + { + std::string newMat = getNextMatInTree (putMat, dataZoneTemp.sharingMatNames[corner]); + + // Can't be posed ? + if (newMat == STRING_UNUSED) + break; + } + if ( (corner < 4) && (m != 0) ) + { + // The material can't be paused + dataZoneTemp.sharingMatNames[0] = STRING_UNUSED; + dataZoneTemp.sharingMatNames[1] = STRING_UNUSED; + dataZoneTemp.sharingMatNames[2] = STRING_UNUSED; + dataZoneTemp.sharingMatNames[3] = STRING_UNUSED; + + // Don't propagate any more + } + else + { + // Expand material for the 1st quarter + std::string newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[0]); + if (newMat != dataZoneTemp.sharingMatNames[0]) + { + // Update the quarter + if (dataZoneTemp.sharingMatNames[0] != newMat) + { + dataZoneTemp.sharingMatNames[0] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 1, x - 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 3, x - 1, y - 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 2, x, y - 1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 2nd quarter + newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[1]); + if (newMat != dataZoneTemp.sharingMatNames[1]) + { + // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.sharingMatNames[1] != newMat) + { + dataZoneTemp.sharingMatNames[1] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 0, x + 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 2, x + 1, y - 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 3, x, y - 1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 3rd quarter + newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[2]); + if (newMat != dataZoneTemp.sharingMatNames[2]) + { + // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.sharingMatNames[2] != newMat) + { + dataZoneTemp.sharingMatNames[2] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 3, x - 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 1, x - 1, y + 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 0, x, y + 1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 4th quarter + newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[3]); + if (newMat != dataZoneTemp.sharingMatNames[3]) + { + // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.sharingMatNames[3] != newMat) + { + dataZoneTemp.sharingMatNames[3] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 2, x + 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 0, x + 1, y + 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 1, x, y + 1, newMat, &tCreate, ptUpdate); + } + } + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + // Delete transitions that are inside the mask + for (j = 0; j < mask.h; ++j) + for (i = 0; i < mask.w; ++i) + if (mask.Tab[i + j * mask.w]) + { + tCreate.del(inX + i, inY + j); + } + + // For all transition to update choose the cut edge + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->zoneRegion(); + x = tCreate.getX(m); + y = tCreate.getY(m); + + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + continue; + + ZonePosition zoneTemp(x, y, tCreate.getBuilderZoneRegion(m)->getRegionId()); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + LigoData dataZoneTempOriginal = dataZoneTemp; + + for (i = 0; i < 4; ++i) + { + uint8 nCut = (uint8)(1.0f + NLMISC::frand(2.0f)); + NLMISC::clamp(nCut, (uint8)1, (uint8)2); + dataZoneTemp.sharingCutEdges[i] = nCut; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + + // Propagate + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[2]) + { + // [x-1][y].right = [x][y].left + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion3, x - 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[3] != dataZoneTemp.sharingCutEdges[2]) + { + data.sharingCutEdges[3] = dataZoneTemp.sharingCutEdges[2]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add(builderZoneRegion3, x - 1, y, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[2] != 0) + { + dataZoneTemp.sharingCutEdges[2] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1]) + { + // [x][y-1].up = [x][y].down + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions (zonePosU, builderZoneRegion3, x, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[0] != dataZoneTemp.sharingCutEdges[1]) + { + data.sharingCutEdges[0] = dataZoneTemp.sharingCutEdges[1]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add (builderZoneRegion3, x, y - 1, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[1] != 0) + { + dataZoneTemp.sharingCutEdges[1] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + + if (dataZoneTemp.sharingMatNames[3] != dataZoneTemp.sharingMatNames[1]) + { + // [x+1][y].left = [x][y].right + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion3, x + 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[2] != dataZoneTemp.sharingCutEdges[3]) + { + data.sharingCutEdges[2] = dataZoneTemp.sharingCutEdges[3]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add(builderZoneRegion3, x + 1, y, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[3] != 0) + { + dataZoneTemp.sharingCutEdges[3] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + + if (dataZoneTemp.sharingMatNames[2] != dataZoneTemp.sharingMatNames[3]) + { + // [x][y+1].down = [x][y].up + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions (zonePosU, builderZoneRegion3, x, y+1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]) + { + data.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add (builderZoneRegion3, x, y + 1, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[0] = 0) + { + dataZoneTemp.sharingCutEdges[0] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + } + + // Delete in tUpdate each element in common with tCreate + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + x = tCreate.getX(m); + y = tCreate.getY(m); + ptUpdate->del (x,y); + } + + // Finally update all transition + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->zoneRegion(); + x = tCreate.getX(m); + y = tCreate.getY(m); + + if ((x >= zoneRegion2.getMinX()) && (x <= zoneRegion2.getMaxX()) && + (y >= zoneRegion2.getMinY()) && (y <= zoneRegion2.getMaxY())) + tCreate.getBuilderZoneRegion(m)->updateTrans(x, y); + } + for (m = 0; m < (sint32)ptUpdate->size(); ++m) + { + const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->zoneRegion(); + x = ptUpdate->getX(m); + y = ptUpdate->getY(m); + if ((x >= zoneRegion2.getMinX()) && (x <= zoneRegion2.getMaxX()) && + (y >= zoneRegion2.getMinY()) && (y <= zoneRegion2.getMaxY())) + tCreate.getBuilderZoneRegion(m)->updateTrans(x, y); + } + + // Cross material + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->zoneRegion(); + x = tCreate.getX(m); + y = tCreate.getY(m); + + + ZonePosition zoneTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + + std::set matNameSet; + for (i = 0; i < 4; ++i) + matNameSet.insert(dataZoneTemp.sharingMatNames[i]); + + if (((dataZoneTemp.sharingMatNames[0] == dataZoneTemp.sharingMatNames[3]) && + (dataZoneTemp.sharingMatNames[1] == dataZoneTemp.sharingMatNames[2]) && + (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1])) + || (matNameSet.size()>2)) + { + NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); + zoneBank.resetSelection(); + zoneBank.addOrSwitch("material", tCreate.getMat(m)); + zoneBank.addAndSwitch("size", "1x1"); + std::vector vElts; + zoneBank.getSelection(vElts); + if (vElts.size() == 0) + return; + sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); + NLMISC::clamp(nRan, (sint32)0, (sint32)(vElts.size() - 1)); + NLLIGO::CZoneBankElement *zoneBankElement = vElts[nRan]; + nRan = (uint32)(NLMISC::frand (1.0) * 4); + NLMISC::clamp(nRan, (sint32)0, (sint32)3); + uint8 rot = (uint8)nRan; + nRan = (uint32)(NLMISC::frand (1.0) * 2); + NLMISC::clamp (nRan, (sint32)0, (sint32)1); + uint8 flip = (uint8)nRan; + + tCreate.getBuilderZoneRegion(m)->add(x, y, rot, flip, zoneBankElement); + } + } +} + +struct STrans +{ + uint8 Num; + uint8 Rot; + uint8 Flip; +}; + +STrans TranConvTable[128] = +{ + { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 1 UNUSED + + { 6,0,0 }, // Quart = 1, CutEdge = 0, Np = 0 + { 6,3,1 }, // Quart = 1, CutEdge = 0, Np = 1 + { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 0 + { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 1 + { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 0 + { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 1 + { 8,0,0 }, // Quart = 1, CutEdge = 3, Np = 0 + { 8,3,1 }, // Quart = 1, CutEdge = 3, Np = 1 + + { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 0 + { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 1 + { 6,0,1 }, // Quart = 2, CutEdge = 1, Np = 0 + { 6,1,0 }, // Quart = 2, CutEdge = 1, Np = 1 + { 8,1,0 }, // Quart = 2, CutEdge = 2, Np = 0 + { 8,0,1 }, // Quart = 2, CutEdge = 2, Np = 1 + { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 0 + { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 3, CutEdge = 0, Np = 0 + { 0,0,1 }, // Quart = 3, CutEdge = 0, Np = 1 + { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 0 + { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 1 + { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 0 + { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 1 + { 2,0,0 }, // Quart = 3, CutEdge = 3, Np = 0 + { 2,0,1 }, // Quart = 3, CutEdge = 3, Np = 1 + + { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 0 + { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 1 + { 8,3,0 }, // Quart = 4, CutEdge = 1, Np = 0 + { 8,2,1 }, // Quart = 4, CutEdge = 1, Np = 1 + { 6,3,0 }, // Quart = 4, CutEdge = 2, Np = 0 + { 6,2,1 }, // Quart = 4, CutEdge = 2, Np = 1 + { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 0 + { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 1 + + { 0,3,0 }, // Quart = 5, CutEdge = 0, Np = 0 + { 0,3,1 }, // Quart = 5, CutEdge = 0, Np = 1 + { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 0 + { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 1 + { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 0 + { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 1 + { 2,3,0 }, // Quart = 5, CutEdge = 3, Np = 0 + { 2,3,1 }, // Quart = 5, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 1 UNUSED + + { 5,2,0 }, // Quart = 7, CutEdge = 0, Np = 0 + { 5,1,1 }, // Quart = 7, CutEdge = 0, Np = 1 + { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 0 + { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 1 + { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 0 + { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 1 + { 3,2,0 }, // Quart = 7, CutEdge = 3, Np = 0 + { 3,1,1 }, // Quart = 7, CutEdge = 3, Np = 1 + + { 8,2,0 }, // Quart = 8, CutEdge = 0, Np = 0 + { 8,1,1 }, // Quart = 8, CutEdge = 0, Np = 1 + { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 0 + { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 1 + { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 0 + { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 1 + { 6,2,0 }, // Quart = 8, CutEdge = 3, Np = 0 + { 6,1,1 }, // Quart = 8, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 1 UNUSED + + { 2,1,0 }, // Quart = 10, CutEdge = 0, Np = 0 + { 2,1,1 }, // Quart = 10, CutEdge = 0, Np = 1 + { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 0 + { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 1 + { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 0 + { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 1 + { 0,1,0 }, // Quart = 10, CutEdge = 3, Np = 0 + { 0,1,1 }, // Quart = 10, CutEdge = 3, Np = 1 + + { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 0 + { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 1 + { 5,3,0 }, // Quart = 11, CutEdge = 1, Np = 0 + { 5,2,1 }, // Quart = 11, CutEdge = 1, Np = 1 + { 3,3,0 }, // Quart = 11, CutEdge = 2, Np = 0 + { 3,2,1 }, // Quart = 11, CutEdge = 2, Np = 1 + { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 0 + { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 1 + + { 2,2,0 }, // Quart = 12, CutEdge = 0, Np = 0 + { 2,2,1 }, // Quart = 12, CutEdge = 0, Np = 1 + { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 0 + { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 1 + { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 0 + { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 1 + { 0,2,0 }, // Quart = 12, CutEdge = 3, Np = 0 + { 0,2,1 }, // Quart = 12, CutEdge = 3, Np = 1 + + { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 0 + { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 1 + { 3,1,0 }, // Quart = 13, CutEdge = 1, Np = 0 + { 3,0,1 }, // Quart = 13, CutEdge = 1, Np = 1 + { 5,1,0 }, // Quart = 13, CutEdge = 2, Np = 0 + { 5,0,1 }, // Quart = 13, CutEdge = 2, Np = 1 + { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 0 + { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 1 + + { 3,0,0 }, // Quart = 14, CutEdge = 0, Np = 0 + { 3,3,1 }, // Quart = 14, CutEdge = 0, Np = 1 + { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 0 + { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 1 + { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 0 + { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 1 + { 5,0,0 }, // Quart = 14, CutEdge = 3, Np = 0 + { 5,3,1 }, // Quart = 14, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 } // Quart = 15, CutEdge = 3, Np = 1 UNUSED +}; + +void BuilderZoneRegion::updateTrans (sint32 x, sint32 y, NLLIGO::CZoneBankElement *zoneBankElement) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + return; + + //if (!_Builder->getZoneMask(x,y)) + // return; + + // Interpret the transition info + x -= zoneRegion.getMinX (); + y -= zoneRegion.getMinY (); + sint32 m; + + // Calculate the number of material around with transition info + std::set matNameSet; + + ZonePosition zonePosTemp(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + LigoData dataZoneTempOriginal = dataZoneTemp; + + for (m = 0; m < 4; ++m) + matNameSet.insert(dataZoneTemp.sharingMatNames[m]); + + if (matNameSet.size() == 1) + { + if (dataZoneTemp.sharingMatNames[0] == STRING_UNUSED) + { + del(x + zoneRegion.getMinX (), y + zoneRegion.getMinY ()); + // set (x+pBZR->getMinX (), y+pBZR->getMinY (), 0, 0, STRING_UNUSED, false); + return; + } + else + { + NLLIGO::CZoneBankElement *zoneBankElement2 = m_zoneBuilder->getZoneBank().getElementByZoneName(dataZoneTemp.zoneName); + if ((zoneBankElement != NULL) && (zoneBankElement2->getCategory("material") == dataZoneTemp.sharingMatNames[0])) + return; + + NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); + zoneBank.resetSelection (); + zoneBank.addOrSwitch ("material", dataZoneTemp.sharingMatNames[0]); + zoneBank.addAndSwitch ("size", "1x1"); + std::vector vElts; + zoneBank.getSelection (vElts); + if (vElts.size() == 0) + return; + sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); + NLMISC::clamp (nRan, (sint32)0, (sint32)(vElts.size()-1)); + zoneBankElement = vElts[nRan]; + nRan = (uint32)(NLMISC::frand(1.0) * 4); + NLMISC::clamp (nRan, (sint32)0, (sint32)3); + uint8 rot = (uint8)nRan; + nRan = (uint32)(NLMISC::frand(1.0) * 2); + NLMISC::clamp (nRan, (sint32)0, (sint32)1); + uint8 flip = (uint8)nRan; + + set(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), 0, 0, zoneBankElement->getName(), false); + setRot(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), rot); + setFlip(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), flip); + return; + } + } + + // No 2 materials so the transition system dont work + if (matNameSet.size() != 2) + return; + + std::set::iterator it = matNameSet.begin(); + std::string matA = *it; + ++it; + std::string matB = *it; + + NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); + zoneBank.resetSelection (); + zoneBank.addOrSwitch("transname", matA + "-" + matB); + std::vector selection; + zoneBank.getSelection(selection); + if (selection.size() == 0) + { + std::string matTmp = matA; + matA = matB; + matB = matTmp; + zoneBank.resetSelection (); + zoneBank.addOrSwitch ("transname", matA + "-" + matB); + zoneBank.getSelection (selection); + } + + if (selection.size() == 0) + return; + + // Convert the sharingCutEdges and SharingNames to the num and type of transition + uint8 nQuart = 0; // 0-MatA 1-MatB + for (m = 0; m < 4; ++m) + if (dataZoneTemp.sharingMatNames[m] == matB) + nQuart |= (1 << m); + + if ((nQuart == 0) || (nQuart == 6) || + (nQuart == 9) || (nQuart == 15)) + return; // No transition for those types + + uint8 nCutEdge = 0; + uint8 nPosCorner = 0; + + // If up edge is cut write the cut position in nCutEdge bitfield (1->0, 2->1) + if ((nQuart == 4) || (nQuart == 5) || + (nQuart == 7) || (nQuart == 8) || + (nQuart == 10) || (nQuart == 11)) + { + if (dataZoneTemp.sharingCutEdges[0] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[0] = 0; + } + + // Same for down edge + if ((nQuart == 1) || (nQuart == 2) || + (nQuart == 5) || (nQuart == 10) || + (nQuart == 13) || (nQuart == 14)) + { + if (dataZoneTemp.sharingCutEdges[1] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[1] = 0; + } + + // Same for left edge + if ((nQuart == 1) || (nQuart == 3) || + (nQuart == 4) ||(nQuart == 11) || + (nQuart == 12) || (nQuart == 14)) + { + if (dataZoneTemp.sharingCutEdges[2] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[2] = 0; + } + + // Same for right edge + if ((nQuart == 2) || (nQuart == 3) || + (nQuart == 7) || (nQuart == 8) || + (nQuart == 12) || (nQuart == 13)) + { + if (dataZoneTemp.sharingCutEdges[3] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[3] = 0; + } + + nlassert (nPosCorner == 2); // If not this means that more than 2 edges are cut which is not possible + + STrans Trans, TransTmp1, TransTmp2; + + TransTmp1 = TranConvTable[nQuart * 8 + 2 * nCutEdge + 0]; + TransTmp2 = TranConvTable[nQuart * 8 + 2 * nCutEdge + 1]; + + // Choose one or the two + sint32 nTrans = (sint32)(NLMISC::frand(2.0f)); + NLMISC::clamp(nTrans, (sint32)0, (sint32)1); + if (nTrans == 0) + Trans = TransTmp1; + else + Trans = TransTmp2; + + zoneBank.addAndSwitch ("transnum", NLMISC::toString(Trans.Num)); + zoneBank.getSelection (selection); + + if (selection.size() > 0) + { + if (zoneBankElement != NULL) + { + dataZoneTemp.zoneName = zoneBankElement->getName(); + } + else + { + nTrans = (uint32)(NLMISC::frand (1.0) * selection.size()); + NLMISC::clamp(nTrans, (sint32)0, (sint32)(selection.size() - 1)); + dataZoneTemp.zoneName = selection[nTrans]->getName(); + } + dataZoneTemp.posX = dataZoneTemp.posY = 0; + dataZoneTemp.rot = Trans.Rot; + dataZoneTemp.flip = Trans.Flip; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); +} + +std::string BuilderZoneRegion::getNextMatInTree (const std::string &matA, const std::string &matB) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + uint32 i, posA = 10000, posB = 10000; + + if (matA == matB) + return matA; + + for (i = 0; i < m_matTree.size(); ++i) + { + if (m_matTree[i].Name == matA) + posA = i; + if (m_matTree[i].Name == matB) + posB = i; + } + if ((posA == 10000) || (posB == 10000)) + return STRING_UNUSED; + + std::vector vTemp; + tryPath (posA, posB, vTemp); + if (vTemp.size() <= 1) + return STRING_UNUSED; + else + return m_matTree[vTemp[1]].Name; +} + +struct SNode +{ + sint32 NodePos, Dist, PrevNodePos; + + SNode() + { + NodePos = Dist = PrevNodePos = -1; + } +}; + +void BuilderZoneRegion::tryPath(uint32 posA, uint32 posB, std::vector &path) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + + // Build the adjascence matrix + std::vector matAdj; + sint32 numNodes = m_matTree.size(); + sint32 i, j, cost; + matAdj.resize(numNodes * numNodes, -1); + for (i = 0; i < numNodes; ++i) + for (j = 0; j < (sint32)m_matTree[i].Arcs.size(); ++j) + matAdj[i + m_matTree[i].Arcs[j] * numNodes] = 1; + + std::vector vNodes; // NodesPos == index + vNodes.resize (numNodes); + for (i = 0; i < numNodes; ++i) + vNodes[i].NodePos = i; + vNodes[posA].Dist = 0; + + std::queue qNodes; + qNodes.push (vNodes[posA]); + + while (qNodes.size() > 0) + { + SNode node = qNodes.front(); + qNodes.pop (); + + for (i = 0; i < numNodes; ++i) + { + cost = matAdj[node.NodePos + i * numNodes]; + if (cost != -1) + { + if ((vNodes[i].Dist == -1) || (vNodes[i].Dist > (cost + node.Dist))) + { + vNodes[i].Dist = cost + node.Dist; + vNodes[i].PrevNodePos = node.NodePos; + qNodes.push(vNodes[i]); + } + } + } + } + + // Get path length + i = posB; + j = 0; + while (i != -1) + { + ++j; + i = vNodes[i].PrevNodePos; + } + + // Write the path in the good order (from posA to posB) + path.resize(j); + i = posB; + while (i != -1) + { + --j; + path[j] = i; + i = vNodes[i].PrevNodePos; + } +} + +void BuilderZoneRegion::del(sint32 x, sint32 y, bool transition, void *pInternal) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + if (!m_zoneBuilder->getZoneMask(x, y)) + return; + + const std::string &nameZone = zoneRegion.getName(x, y); + + ToUpdate *pUpdate = reinterpret_cast(pInternal); + + NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(nameZone); + if (zoneBankElement != NULL) + { + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 posX = zoneRegion.getPosX (x, y), posY = zoneRegion.getPosY (x, y); + uint8 rot = zoneRegion.getRot (x, y); + uint8 flip = zoneRegion.getFlip (x, y); + sint32 i, j; + sint32 deltaX, deltaY; + + if (flip == 0) + { + switch (rot) + { + case 0: + deltaX = -posX; + deltaY = -posY; + break; + case 1: + deltaX = -(sizeY - 1 - posY); + deltaY = -posX; + break; + case 2: + deltaX = -(sizeX - 1 - posX); + deltaY = -(sizeY - 1 - posY); + break; + case 3: + deltaX = -posY; + deltaY = -(sizeX - 1 - posX); + break; + } + } + else + { + switch (rot) + { + case 0: + deltaX = -(sizeX - 1 - posX); + deltaY = -posY; + break; + case 1: + deltaX = -(sizeY - 1 - posY); + deltaY = -(sizeX - 1 - posX); + break; + case 2: + deltaX = -posX; + deltaY = -(sizeY - 1 - posY); + break; + case 3: + deltaX = -posY; + deltaY = -posX; + break; + } + } + + NLLIGO::SPiece mask; + mask.Tab.resize (sizeX * sizeY); + for(i = 0; i < sizeX * sizeY; ++i) + mask.Tab[i] = zoneBankElement->getMask()[i]; + mask.w = sizeX; + mask.h = sizeY; + mask.rotFlip (rot, flip); + + for (j = 0; j < mask.h; ++j) + for (i = 0; i < mask.w; ++i) + if (mask.Tab[i + j * mask.w]) + { + set(x + deltaX + i, y + deltaY + j, 0, 0, STRING_UNUSED, true); + setRot(x + deltaX + i, y + deltaY + j, 0); + setFlip(x + deltaX + i, y + deltaY + j, 0); + if (pUpdate != NULL) + { + pUpdate->add(this, x + deltaX + i, y + deltaY + j, ""); + } + } + if (!transition) + reduceMin (); + } + else + { + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + return; + + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + LigoData dataZoneTempOriginal = dataZoneTemp; + + dataZoneTemp.zoneName = STRING_UNUSED; + dataZoneTemp.posX = 0; + dataZoneTemp.posY = 0; + + for (uint32 i = 0; i < 4; ++i) + { + dataZoneTemp.sharingMatNames[i] = STRING_UNUSED; + dataZoneTemp.sharingCutEdges[i] = 0; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + + } +} + +void BuilderZoneRegion::move (sint32 x, sint32 y) +{ + m_zoneBuilder->actionLigoMove(m_regionId, x, y); +} + +uint32 BuilderZoneRegion::countZones () +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + sint32 x, y; + + uint32 counter = 0; + + for (y = zoneRegion.getMinY (); y <= zoneRegion.getMaxY (); ++y) + for (x = zoneRegion.getMinX (); x <= zoneRegion.getMaxX (); ++x) + if (zoneRegion.getName (x, y) != STRING_UNUSED) + ++counter; + + return counter; +} + +void BuilderZoneRegion::set(sint32 x, sint32 y, sint32 posX, sint32 posY, + const std::string &zoneName, bool transition) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + + // Do we need to resize ? + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + { + sint32 newMinX = (x < zoneRegion.getMinX() ? x: zoneRegion.getMinX()), newMinY = (y < zoneRegion.getMinY() ? y: zoneRegion.getMinY()); + sint32 newMaxX = (x > zoneRegion.getMaxX() ? x: zoneRegion.getMaxX()), newMaxY = (y > zoneRegion.getMaxY() ? y: zoneRegion.getMaxY()); + + resize(newMinX, newMaxX, newMinY, newMaxY); + } + + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + LigoData dataZoneTempOriginal = dataZoneTemp; + + dataZoneTemp.zoneName = zoneName; + dataZoneTemp.posX = (uint8)posX; + dataZoneTemp.posY = (uint8)posY; + + if (!transition) + { + NLLIGO::CZoneBankElement *zoneBankElem = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneName); + if (zoneBankElem == NULL) + return; + + const std::string &matName = zoneBankElem->getCategory ("material"); + if (matName == STRING_NO_CAT_TYPE) + return; + for (uint32 i = 0; i < 4; ++i) + { + dataZoneTemp.sharingMatNames[i] = matName; + dataZoneTemp.sharingCutEdges[i] = 0; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + + BuilderZoneRegion *builderZoneRegion = this; + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[3] != matName) + { + data.sharingMatNames[3] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[2] != matName) || (data.sharingMatNames[3] != matName)) + { + data.sharingMatNames[2] = matName; + data.sharingMatNames[3] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[2] != matName) + { + data.sharingMatNames[2] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[1] != matName) || (data.sharingMatNames[3] != matName)) + { + data.sharingMatNames[1] = matName; + data.sharingMatNames[3] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[0] != matName) || (data.sharingMatNames[2] != matName)) + { + data.sharingMatNames[0] = matName; + data.sharingMatNames[2] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y + 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[1] != matName) + { + data.sharingMatNames[1] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x, y + 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[0] != matName) || (data.sharingMatNames[1] != matName)) + { + data.sharingMatNames[0] = matName; + data.sharingMatNames[1] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y + 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[0] != matName) + { + data.sharingMatNames[0] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + } + else + { + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } +} + +void BuilderZoneRegion::setRot (sint32 x, sint32 y, uint8 rot) +{ + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.rot != rot) + { + dataZoneTemp.rot = rot; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } +} + +void BuilderZoneRegion::setFlip(sint32 x, sint32 y, uint8 flip) +{ + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.flip != flip) + { + dataZoneTemp.flip = flip; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } +} + + +void BuilderZoneRegion::reduceMin () +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + sint32 i, j; + + sint32 newMinX = zoneRegion.getMinX(), newMinY = zoneRegion.getMinY (); + sint32 newMaxX = zoneRegion.getMaxX(), newMaxY = zoneRegion.getMaxY (); + bool bCanSuppr; + + // Reduce the MinY + while (true) + { + if (newMinY == newMaxY) + break; + j = newMinY; + bCanSuppr = true; + for (i = newMinX; i <= newMaxX; ++i) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + ++newMinY; + else + break; + } + + // Reduce the MaxY + while (true) + { + if (newMinY == newMaxY) + break; + j = newMaxY; + bCanSuppr = true; + for (i = newMinX; i <= newMaxX; ++i) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + --newMaxY; + else + break; + } + + // Reduce the MinX + while (true) + { + if (newMinX == newMaxX) + break; + i = newMinX; + bCanSuppr = true; + for (j = newMinY; j <= newMaxY; ++j) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + ++newMinX; + else + break; + } + + // Reduce the MaxX + while (true) + { + if (newMinX == newMaxX) + break; + i = newMaxX; + bCanSuppr = true; + for (j = newMinY; j <= newMaxY; ++j) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + --newMaxX; + else + break; + } + + if ((newMinX != zoneRegion.getMinX ()) || + (newMinY != zoneRegion.getMinY ()) || + (newMaxX != zoneRegion.getMaxX ()) || + (newMaxY != zoneRegion.getMaxY ())) + { + resize(newMinX, newMaxX, newMinY, newMaxY); + } +} + +uint BuilderZoneRegion::getRegionId() const +{ + return m_regionId; +} + +void BuilderZoneRegion::resize (sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->zoneRegion(); + if ((zoneRegion.getMinX ()!= newMinX) || + (zoneRegion.getMaxX ()!= newMaxX) || + (zoneRegion.getMinY ()!= newMinY) || + (zoneRegion.getMaxY ()!= newMaxY)) + { + m_zoneBuilder->actionLigoResize(m_regionId, newMinX, newMaxX, newMinY, newMaxY); + } +} + } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h index 158c72715..7322e47b6 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h @@ -1,33 +1,101 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef BUILDER_ZONE_REGION_H -#define BUILDER_ZONE_REGION_H - -// Project includes - -// NeL includes -#include - -// Qt includes - -namespace LandscapeEditor -{ - -} /* namespace LandscapeEditor */ - -#endif // BUILDER_ZONE_REGION_H +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef BUILDER_ZONE_REGION_H +#define BUILDER_ZONE_REGION_H + +// Project includes + +// NeL includes +#include +#include + +// STL includes +#include +#include +#include + +// Qt includes + +namespace LandscapeEditor +{ +class ZoneBuilder; + +// CZoneRegion contains informations about the zones painted +class BuilderZoneRegion +{ +public: + + BuilderZoneRegion(uint regionId); + + // New interface + bool init(ZoneBuilder *zoneBuilder, std::string &error); + void add(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + void invertCutEdge(sint32 x, sint32 y, uint8 cePos); + void cycleTransition(sint32 x, sint32 y); + bool addNotPropagate(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + + /// Brutal adding a zone over empty space do not propagate in any way -> can result + /// in inconsistency when trying the propagation mode + void addForce (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + void del(sint32 x, sint32 y, bool transition = false, void *pInternal = NULL); + void move(sint32 x, sint32 y); + uint32 countZones(); + void reduceMin(); + uint getRegionId() const; + +private: + + // An element of the graph + struct SMatNode + { + std::string Name; + // Position in the tree (vector of nodes) + std::vector Arcs; + }; + + void addTransition(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + + void addToUpdateAndCreate(BuilderZoneRegion* builderZoneRegion, sint32 sharePos, sint32 x, sint32 y, const std::string &newMat, void *pInt1, void *pInt2); + + void putTransitions(sint32 x, sint32 y, const NLLIGO::SPiece &mask, const std::string &matName, void *pInternal); + void updateTrans(sint32 x, sint32 y, NLLIGO::CZoneBankElement *zoneBankElement = NULL); + + std::string getNextMatInTree(const std::string &matA, const std::string &matB); + + /// Find the fastest way between posA and posB in the MatTree (Dijkstra) + void tryPath(uint32 posA, uint32 posB, std::vector &path); + + void set(sint32 x, sint32 y, sint32 posX, sint32 posY, const std::string &zoneName, bool transition=false); + void setRot(sint32 x, sint32 y, uint8 rot); + void setFlip(sint32 x, sint32 y, uint8 flip); + void resize(sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); + + uint m_regionId; + + // To use the global mask + ZoneBuilder *m_zoneBuilder; + + // The tree of transition between materials + std::vector m_matTree; + + bool m_firstInit; +}; + +} /* namespace LandscapeEditor */ + +#endif // BUILDER_ZONE_REGION_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp index 84d59ba8d..95f030631 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp @@ -62,54 +62,111 @@ void NewLandscapeCommand::redo() { } -AddLigoTileCommand::AddLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent) +LigoTileCommand::LigoTileCommand(const LigoData &data, const ZonePosition &zonePos, + ZoneBuilder *zoneBuilder, LandscapeScene *scene, + QUndoCommand *parent) : QUndoCommand(parent), - m_item(0), + m_zoneBuilder(zoneBuilder), m_scene(scene) { - m_ligoData = data; + // Backup position + m_zonePos = zonePos; + + // Backup new data + m_newLigoData = data; + + // Backup old data + m_zoneBuilder->ligoData(m_oldLigoData, m_zonePos); } -AddLigoTileCommand::~AddLigoTileCommand() +LigoTileCommand::~LigoTileCommand() { } -void AddLigoTileCommand::undo() +void LigoTileCommand::undo () { - m_scene->removeItem(m_item); - delete m_item; - m_item = 0; + m_zoneBuilder->setLigoData(m_oldLigoData, m_zonePos); + m_scene->createZoneItem(m_oldLigoData, m_zonePos); } -void AddLigoTileCommand::redo() +void LigoTileCommand::redo () { - m_item = m_scene->createZoneItem(m_ligoData); - setText(QObject::tr("Add tile(%1, %2)").arg(m_ligoData.PosX).arg(m_ligoData.PosY)); + m_zoneBuilder->setLigoData(m_newLigoData, m_zonePos); + m_scene->createZoneItem(m_newLigoData, m_zonePos); } -DelLigoTileCommand::DelLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent) +LigoResizeCommand::LigoResizeCommand(int index, sint32 newMinX, sint32 newMaxX, + sint32 newMinY, sint32 newMaxY, ZoneBuilder *zoneBuilder, + QUndoCommand *parent) : QUndoCommand(parent), - m_item(0), - m_scene(scene) + m_zoneBuilder(zoneBuilder) { - m_ligoData = data; + m_index = index; + m_newMinX = newMinX; + m_newMaxX = newMaxX; + m_newMinY = newMinY; + m_newMaxY = newMaxY; + + // Backup old region zone + m_oldZoneRegion = m_zoneBuilder->zoneRegion(m_index)->zoneRegion(); } -DelLigoTileCommand::~DelLigoTileCommand() +LigoResizeCommand::~LigoResizeCommand() { } -void DelLigoTileCommand::undo() +void LigoResizeCommand::undo () { - m_item = m_scene->createZoneItem(m_ligoData); + // Restore old region zone + m_zoneBuilder->zoneRegion(m_index)->setZoneRegion(m_oldZoneRegion); } -void DelLigoTileCommand::redo() +void LigoResizeCommand::redo () { - m_item = m_scene->itemAt(m_ligoData.PosX * m_scene->cellSize(), m_ligoData.PosY * m_scene->cellSize()); - delete m_item; - m_item = 0; - setText(QObject::tr("Del tile(%1, %2)").arg(m_ligoData.PosX).arg(m_ligoData.PosY)); + // Get the zone region + NLLIGO::CZoneRegion ®ion = m_zoneBuilder->zoneRegion(m_index)->zoneRegion(); + + sint32 i, j; + std::vector newZones; + newZones.resize((1 + m_newMaxX - m_newMinX) * (1 + m_newMaxY - m_newMinY)); + + sint32 newStride = 1 + m_newMaxX - m_newMinX; + sint32 Stride = 1 + region.getMaxX() - region.getMinX(); + + for (j = m_newMinY; j <= m_newMaxY; ++j) + for (i = m_newMinX; i <= m_newMaxX; ++i) + { + // Ref on the new value + LigoData &data = newZones[(i - m_newMinX) + (j - m_newMinY) * newStride]; + + // In the old array ? + if ((i >= region.getMinX()) && (i <= region.getMaxX()) && + (j >= region.getMinY()) && (j <= region.getMaxY())) + { + // Backup values + m_zoneBuilder->ligoData(data, ZonePosition(i, j, m_index)); + } + } + region.resize(m_newMinX, m_newMaxX, m_newMinY, m_newMaxY); + + for (j = m_newMinY; j <= m_newMaxY; ++j) + for (i = m_newMinX; i <= m_newMaxX; ++i) + { + // Ref on the new value + const LigoData &data = newZones[(i - m_newMinX) + (j - m_newMinY) * newStride]; + + region.setName(i, j, data.zoneName); + region.setPosX(i, j, data.posX); + region.setPosY(i, j, data.posY); + region.setRot(i, j, data.rot); + region.setFlip(i, j, data.flip); + uint k; + for (k = 0; k < 4; k++) + { + region.setSharingMatNames(i, j, k, data.sharingMatNames[k]); + region.setSharingCutEdges(i, j, k, data.sharingCutEdges[k]); + } + } } } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h index 7bbd1bd96..e7a39d8b1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h @@ -56,36 +56,64 @@ public: private: }; -class AddLigoTileCommand: public QUndoCommand +// Modify the landscape +class LigoTileCommand: public QUndoCommand { public: - AddLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent = 0); - virtual ~AddLigoTileCommand(); + LigoTileCommand(const LigoData &data, const ZonePosition &zonePos, + ZoneBuilder *zoneBuilder, LandscapeScene *scene, + QUndoCommand *parent = 0); + virtual ~LigoTileCommand(); virtual void undo(); virtual void redo(); private: - - LigoData m_ligoData; - QGraphicsItem *m_item; + ZonePosition m_zonePos; + LigoData m_newLigoData; + LigoData m_oldLigoData; + ZoneBuilder *m_zoneBuilder; LandscapeScene *m_scene; }; - -class DelLigoTileCommand: public QUndoCommand +/* +// Move the landscape +class LigoMoveCommand: public QUndoCommand { public: - DelLigoTileCommand(const LigoData &data, LandscapeScene *scene, QUndoCommand *parent = 0); - virtual ~DelLigoTileCommand(); + + LigoMoveCommand(int index, sint32 deltaX, sint32 deltaY, ZoneBuilder *zoneBuilder, QUndoCommand *parent = 0); + virtual ~LigoMoveCommand(); + + virtual void undo(); + virtual void redo(); +private: + + int m_index; + sint32 m_deltaX; + sint32 m_deltaY; + ZoneBuilder *m_zoneBuilder; +}; +*/ +// Modify the landscape +class LigoResizeCommand: public QUndoCommand +{ +public: + LigoResizeCommand(int index, sint32 newMinX, sint32 newMaxX, + sint32 newMinY, sint32 newMaxY, ZoneBuilder *zoneBuilder, + QUndoCommand *parent = 0); + virtual ~LigoResizeCommand(); virtual void undo(); virtual void redo(); private: - - LigoData m_ligoData; - QGraphicsItem *m_item; - LandscapeScene *m_scene; + int m_index; + sint32 m_newMinX; + sint32 m_newMaxX; + sint32 m_newMinY; + sint32 m_newMaxY; + NLLIGO::CZoneRegion m_oldZoneRegion; + ZoneBuilder *m_zoneBuilder; }; } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp index 5ec3f6196..0c38adbf6 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp @@ -19,6 +19,7 @@ #include "landscape_editor_window.h" #include "landscape_editor_constants.h" #include "builder_zone.h" +#include "zone_region_editor.h" #include "landscape_scene.h" #include "project_settings_dialog.h" #include "snapshot_dialog.h" @@ -45,12 +46,14 @@ LandscapeEditorWindow::LandscapeEditorWindow(QWidget *parent) m_ui.setupUi(this); m_undoStack = new QUndoStack(this); - m_zoneBuilder = new ZoneBuilder(); - m_zoneBuilder->init("e:/-nel-/install/continents/newbieland", false); + m_landscapeScene = new LandscapeScene(this); + + m_zoneBuilder = new ZoneBuilder(m_ui.zoneListWidget, m_landscapeScene, m_undoStack); + m_zoneBuilder->init("e:/-nel-/install/continents/newbieland", true); m_ui.zoneListWidget->setZoneBuilder(m_zoneBuilder); m_ui.zoneListWidget->updateUi(); - m_landscapeScene = new LandscapeScene(m_undoStack, m_ui.zoneListWidget, m_zoneBuilder, this); + m_landscapeScene->setZoneBuilder(m_zoneBuilder); m_ui.graphicsView->setScene(m_landscapeScene); //m_ui.graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer))); m_ui.graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::SampleBuffers))); @@ -88,11 +91,14 @@ void LandscapeEditorWindow::open() _lastDir = QFileInfo(list.front()).absolutePath(); Q_FOREACH(QString fileName, fileNames) { - m_zoneRegionEditor.load(fileName.toStdString()); - m_landscapeScene->processZoneRegion(m_zoneRegionEditor.zoneRegion()); - m_landscapeScene->setCurrentZoneRegion(&m_zoneRegionEditor.zoneRegion()); - m_ui.graphicsView->centerOn(m_zoneRegionEditor.zoneRegion().getMinX() * m_landscapeScene->cellSize(), - abs(m_zoneRegionEditor.zoneRegion().getMinY()) * m_landscapeScene->cellSize()); + int id = m_zoneBuilder->createZoneRegion(); + ZoneRegionEditor *zoneRegion = m_zoneBuilder->zoneRegion(id); + zoneRegion->load(fileName.toStdString()); + m_landscapeScene->processZoneRegion(zoneRegion->zoneRegion()); + m_ui.graphicsView->centerOn(zoneRegion->zoneRegion().getMinX() * m_landscapeScene->cellSize(), + abs(zoneRegion->zoneRegion().getMinY()) * m_landscapeScene->cellSize()); + + m_zoneBuilder->setCurrentZoneRegion(id); } } setCursor(Qt::ArrowCursor); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h index 311a65013..3a35b90f4 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h @@ -20,7 +20,6 @@ // Project includes #include "ui_landscape_editor_window.h" -#include "zone_region_editor.h" // Qt includes #include @@ -55,8 +54,6 @@ private: void readSettings(); void writeSettings(); - ZoneRegionEditor m_zoneRegionEditor; - LandscapeScene *m_landscapeScene; ZoneBuilder *m_zoneBuilder; QUndoStack *m_undoStack; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp index 96ad0879b..3aa2bbc9a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp @@ -17,9 +17,6 @@ // Project includes #include "landscape_scene.h" -#include "builder_zone.h" -#include "landscape_actions.h" -#include "list_zones_widget.h" // NeL includes #include @@ -32,12 +29,9 @@ namespace LandscapeEditor { -LandscapeScene::LandscapeScene(QUndoStack *undoStack, ListZonesWidget *listZonesWidget, ZoneBuilder *zoneBuilder, QObject *parent) +LandscapeScene::LandscapeScene(QObject *parent) : QGraphicsScene(parent), - m_undoStack(undoStack), - m_listZonesWidget(listZonesWidget), - m_zoneBuilder(zoneBuilder), - m_zoneRegion(0) + m_zoneBuilder(0) { m_cellSize = 160; } @@ -51,20 +45,34 @@ int LandscapeScene::cellSize() const return m_cellSize; } -QGraphicsItem *LandscapeScene::createZoneItem(const LigoData &data) +void LandscapeScene::setZoneBuilder(ZoneBuilder *zoneBuilder) { + m_zoneBuilder = zoneBuilder; +} + +QGraphicsItem *LandscapeScene::createZoneItem(const LigoData &data, const ZonePosition &zonePos) +{ + if (data.zoneName == STRING_UNUSED) + return createEmptyZoneItem(zonePos); + + if ((m_zoneBuilder == 0) || (data.zoneName.empty()) || + (data.posX != 0) || (data.posY != 0)) + return 0; + + checkUnderZone(data, zonePos); + // Get image from pixmap database - QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(data.ZoneName.c_str())); + QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(data.zoneName.c_str())); if (pixmap == 0) return 0; // Rotate the image counterclockwise QMatrix matrix; - matrix.rotate(-data.Rot * 90.0); + matrix.rotate(-data.rot * 90.0); QGraphicsPixmapItem *item; - if (data.Flip == 0) + if (data.flip == 0) { item = new QGraphicsPixmapItem(pixmap->transformed(matrix, Qt::SmoothTransformation), 0, this); } @@ -79,135 +87,156 @@ QGraphicsItem *LandscapeScene::createZoneItem(const LigoData &data) item->setTransformationMode(Qt::SmoothTransformation); // Set position graphics item with offset for large piece - NLLIGO::CZoneBankElement *zoneBankItem = m_zoneBuilder->getZoneBank().getElementByZoneName(data.ZoneName); - item->setPos(data.PosX * m_cellSize, (abs(data.PosY) - zoneBankItem->getSizeY() + 1) * m_cellSize); + NLLIGO::CZoneBankElement *zoneBankItem = m_zoneBuilder->getZoneBank().getElementByZoneName(data.zoneName); + item->setPos(zonePos.x * m_cellSize, (abs(zonePos.y) - zoneBankItem->getSizeY() + 1) * m_cellSize); // The size graphics item should be equal or proportional m_cellSize - item->setScale(m_cellSize / 256.0); - - // add debug info - QGraphicsSimpleTextItem *itemText = addSimpleText(QString("%1,%2 R-%3 F-%4"). - arg(data.PosX).arg(data.PosY). - arg(data.Rot * 90.0). - arg(data.Flip), - QFont("Helvetica [Cronyx]", 14)); - - itemText->setZValue(2); - itemText->setPos(data.PosX * m_cellSize + 10, (abs(data.PosY) - zoneBankItem->getSizeY() + 1) * m_cellSize + 10); - itemText->setBrush(QBrush(Qt::white)); + item->setScale(float(m_cellSize) / m_zoneBuilder->pixmapDatabase()->textureSize()); return item; } +QGraphicsItem *LandscapeScene::createEmptyZoneItem(const ZonePosition &zonePos) +{ + if (m_zoneBuilder == 0) + return 0; + + deleteZoneItem(zonePos); + + // Get image from pixmap database + QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(STRING_UNUSED)); + if (pixmap == 0) + return 0; + + QGraphicsPixmapItem *item = new QGraphicsPixmapItem(*pixmap, 0, this); + + // Enable bilinear filtering + item->setTransformationMode(Qt::SmoothTransformation); + + // Set position graphics item + item->setPos(zonePos.x * m_cellSize, abs(int(zonePos.y)) * m_cellSize); + + // The size graphics item should be equal or proportional m_cellSize + item->setScale(float(m_cellSize) / m_zoneBuilder->pixmapDatabase()->textureSize()); + + return item; +} + +void LandscapeScene::deleteZoneItem(const ZonePosition &zonePos) +{ + QGraphicsItem *item = itemAt(zonePos.x * m_cellSize, abs(zonePos.y) * m_cellSize); + if (item != 0) + { + removeItem(item); + delete item; + } +} + void LandscapeScene::processZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) { for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) { for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) { + nlinfo(QString("%1 %2 %3").arg(i).arg(j).arg(zoneRegion.getName(i, j).c_str()).toStdString().c_str()); std::string zoneName = zoneRegion.getName(i, j); - if ((!zoneName.empty()) && - (zoneName != STRING_UNUSED) && - (zoneRegion.getPosX(i, j) == 0) && - (zoneRegion.getPosY(i, j) == 0)) + if (zoneName == STRING_UNUSED) + { + ZonePosition zonePos(i, j, -1); + QGraphicsItem *item = createEmptyZoneItem(zonePos); + } + else if (!zoneName.empty()) { LigoData data; - data.PosX = i; - data.PosY = j; - data.ZoneName = zoneName; - data.Rot = zoneRegion.getRot(i, j); - data.Flip = zoneRegion.getFlip(i, j); - QGraphicsItem *item = createZoneItem(data); + ZonePosition zonePos(i, j, -1); + data.zoneName = zoneName; + data.rot = zoneRegion.getRot(i, j); + data.flip = zoneRegion.getFlip(i, j); + data.posX = zoneRegion.getPosX(i, j); + data.posY = zoneRegion.getPosY(i, j); + QGraphicsItem *item = createZoneItem(data, zonePos); } } } } -void LandscapeScene::setCurrentZoneRegion(NLLIGO::CZoneRegion *zoneRegion) -{ - m_zoneRegion = zoneRegion; -} - void LandscapeScene::snapshot(const QString &fileName, int sizeSource) { - if (m_zoneRegion == 0) - return; + /* if (m_zoneRegion == 0) + return; - sint32 regionMinX = m_zoneRegion->getMinX(); - sint32 regionMaxX = m_zoneRegion->getMaxX(); - sint32 regionMinY = m_zoneRegion->getMinY(); - sint32 regionMaxY = m_zoneRegion->getMaxY(); + sint32 regionMinX = m_zoneRegion->getMinX(); + sint32 regionMaxX = m_zoneRegion->getMaxX(); + sint32 regionMinY = m_zoneRegion->getMinY(); + sint32 regionMaxY = m_zoneRegion->getMaxY(); - int regionWidth = (regionMaxX - regionMinX + 1); - int regionHeight = (regionMaxY - regionMinY + 1); + int regionWidth = (regionMaxX - regionMinX + 1); + int regionHeight = (regionMaxY - regionMinY + 1); - snapshot(fileName, regionWidth * sizeSource, regionHeight * sizeSource); + snapshot(fileName, regionWidth * sizeSource, regionHeight * sizeSource); + */ } void LandscapeScene::snapshot(const QString &fileName, int width, int height) { - if (m_zoneRegion == 0) + if (m_zoneBuilder == 0) return; - sint32 regionMinX = m_zoneRegion->getMinX(); - sint32 regionMaxX = m_zoneRegion->getMaxX(); - sint32 regionMinY = m_zoneRegion->getMinY(); - sint32 regionMaxY = m_zoneRegion->getMaxY(); + /* if (m_zoneRegion == 0) + return; - int regionWidth = (regionMaxX - regionMinX + 1); - int regionHeight = (regionMaxY - regionMinY + 1); + sint32 regionMinX = m_zoneRegion->getMinX(); + sint32 regionMaxX = m_zoneRegion->getMaxX(); + sint32 regionMinY = m_zoneRegion->getMinY(); + sint32 regionMaxY = m_zoneRegion->getMaxY(); - QImage image(width, height, QImage::Format_RGB888); - QPainter painter(&image); - painter.setRenderHint(QPainter::Antialiasing, true); + int regionWidth = (regionMaxX - regionMinX + 1); + int regionHeight = (regionMaxY - regionMinY + 1); - // add white background - painter.setBrush(QBrush(Qt::white)); - painter.setPen(Qt::NoPen); - painter.drawRect(0, 0, width, height); + QImage image(width, height, QImage::Format_RGB888); + QPainter painter(&image); + painter.setRenderHint(QPainter::Antialiasing, true); - render(&painter, QRectF(0, 0, width, height), - QRectF(regionMinX * m_cellSize, abs(regionMaxY) * m_cellSize, regionWidth * m_cellSize, regionHeight * m_cellSize)); + // add white background + painter.setBrush(QBrush(Qt::white)); + painter.setPen(Qt::NoPen); + painter.drawRect(0, 0, width, height); - image.save(fileName); + render(&painter, QRectF(0, 0, width, height), + QRectF(regionMinX * m_cellSize, abs(regionMaxY) * m_cellSize, regionWidth * m_cellSize, regionHeight * m_cellSize)); + image.save(fileName); + */ } void LandscapeScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) { + if (m_zoneBuilder == 0) + return; + qreal x = mouseEvent->scenePos().rx(); qreal y = mouseEvent->scenePos().ry(); if ((x < 0) || (y < 0)) return; + sint32 posX = sint32(floor(x / m_cellSize)); + sint32 posY = sint32(-floor(y / m_cellSize)); + if (mouseEvent->button() == Qt::LeftButton) - { - // Add new zone brick - LigoData ligoData = m_listZonesWidget->currentLigoData(); - if (ligoData.ZoneName == "") - return; + m_zoneBuilder->addZone(posX, posY); + else if (mouseEvent->button() == Qt::RightButton) + m_zoneBuilder->delZone(posX, posY); - ligoData.PosX = int(floor(x / m_cellSize)); - ligoData.PosY = int(-floor(y / m_cellSize)); - - AddLigoTileCommand *action = new AddLigoTileCommand(ligoData, this); - m_undoStack->push(action); - } - - /*if (mouseEvent->button() == Qt::RightButton) - { - // Delete zone brick - LigoData ligoData; - - ligoData.PosX = int(floor(x / m_cellSize)); - ligoData.PosY = int(floor(y / m_cellSize)); - ligoData.ZoneName = m_zoneRegion->getName(ligoData.PosX, -ligoData.PosY); - ligoData.Flip = m_zoneRegion->getFlip(ligoData.PosX, -ligoData.PosY); - ligoData.Rot = m_zoneRegion->getRot(ligoData.PosX, -ligoData.PosY); - DelLigoTileCommand *action = new DelLigoTileCommand(ligoData, this); - m_undoStack->push(action); - }*/ QGraphicsScene::mousePressEvent(mouseEvent); } +void LandscapeScene::checkUnderZone(const LigoData &data, const ZonePosition &zonePos) +{ +// NLLIGO::CZoneBankElement *zoneBankItem = m_zoneBuilder->getZoneBank().getElementByZoneName(data.zoneName); +// uint8 sizeX = zoneBankItem->getSizeX(); +// uint8 sizeY = zoneBankItem->getSizeY(); +// std::vector &mask = zoneBankItem->getMask(); + deleteZoneItem(zonePos); +} + } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h index 2af45bf4b..ea314faac 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h @@ -19,6 +19,8 @@ #define LANDSCAPE_SCENE_H // Project includes +#include "zone_region_editor.h" +#include "builder_zone.h" // NeL includes #include @@ -26,54 +28,25 @@ // Qt includes #include #include -#include namespace LandscapeEditor { -class ZoneBuilder; -class ListZonesWidget; - -// Data -struct LigoData -{ - sint32 PosX; - sint32 PosY; - uint8 Rot; - uint8 Flip; - std::string ZoneName; - std::string SharingMatNames[4]; - uint8 SharingCutEdges[4]; - bool operator!= (const LigoData& other) const - { - return (PosX != other.PosX) || - (PosY != other.PosY) || - (Rot != other.Rot) || - (Flip != other.Flip) || - (ZoneName != other.ZoneName) || - (SharingMatNames[0] != other.SharingMatNames[0]) || - (SharingMatNames[1] != other.SharingMatNames[1]) || - (SharingMatNames[2] != other.SharingMatNames[2]) || - (SharingMatNames[3] != other.SharingMatNames[3]) || - (SharingCutEdges[0] != other.SharingCutEdges[0]) || - (SharingCutEdges[1] != other.SharingCutEdges[1]) || - (SharingCutEdges[2] != other.SharingCutEdges[2]) || - (SharingCutEdges[3] != other.SharingCutEdges[3]); - } -}; class LandscapeScene : public QGraphicsScene { Q_OBJECT public: - LandscapeScene(QUndoStack *undoStack, ListZonesWidget *listZonesWidget, ZoneBuilder *zoneBuilder, QObject *parent = 0); + LandscapeScene(QObject *parent = 0); virtual ~LandscapeScene(); int cellSize() const; + void setZoneBuilder(ZoneBuilder *zoneBuilder); - QGraphicsItem *createZoneItem(const LigoData &data); + QGraphicsItem *createZoneItem(const LigoData &data, const ZonePosition &zonePos); + QGraphicsItem *createEmptyZoneItem(const ZonePosition &zonePos); + void deleteZoneItem(const ZonePosition &zonePos); void processZoneRegion(const NLLIGO::CZoneRegion &zoneRegion); - void setCurrentZoneRegion(NLLIGO::CZoneRegion *zoneRegion); void snapshot(const QString &fileName, int sizeSource); void snapshot(const QString &fileName, int width, int height); @@ -82,12 +55,10 @@ protected: virtual void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent); private: + void checkUnderZone(const LigoData &data, const ZonePosition &zonePos); int m_cellSize; - ListZonesWidget *m_listZonesWidget; - QUndoStack *m_undoStack; ZoneBuilder *m_zoneBuilder; - NLLIGO::CZoneRegion *m_zoneRegion; }; } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp index 66d31479b..7ce3f5421 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp @@ -18,6 +18,7 @@ // Project includes #include "list_zones_widget.h" #include "list_zones_model.h" +#include "builder_zone.h" // NeL includes #include @@ -100,17 +101,34 @@ void ListZonesWidget::updateUi() m_listZonesModel->rebuildModel(m_zoneBuilder->pixmapDatabase()); } -LigoData ListZonesWidget::currentLigoData() const +QString ListZonesWidget::currentZoneName() const { - LigoData ligoData; - ligoData.ZoneName = ""; + QString zoneName = ""; QModelIndex index = m_ui.listView->currentIndex(); if (index.isValid()) - ligoData.ZoneName = index.data().toString().toStdString(); + zoneName = index.data().toString(); - ligoData.Rot = m_ui.rotComboBox->currentIndex(); - ligoData.Flip = m_ui.flipComboBox->currentIndex(); - return ligoData; + return zoneName; +} + +int ListZonesWidget::currentRot() const +{ + return m_ui.rotComboBox->currentIndex(); +} + +int ListZonesWidget::currentFlip() const +{ + return m_ui.flipComboBox->currentIndex(); +} + +bool ListZonesWidget::isNotPropogate() const +{ + return m_ui.propogateCheckBox->isChecked(); +} + +bool ListZonesWidget::isForce() const +{ + return m_ui.forceCheckBox->isChecked(); } void ListZonesWidget::setZoneBuilder(ZoneBuilder *zoneBuilder) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h index 8ad5d4c25..c35e7b0fa 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h @@ -20,8 +20,6 @@ // Project includes #include "ui_list_zones_widget.h" -#include "builder_zone.h" -#include "landscape_scene.h" // NeL includes @@ -30,6 +28,7 @@ namespace LandscapeEditor { class ListZonesModel; +class ZoneBuilder; /** @class ZoneListWidget @@ -46,7 +45,11 @@ public: void updateUi(); void setZoneBuilder(ZoneBuilder *zoneBuilder); - LigoData currentLigoData() const; + QString currentZoneName() const; + int currentRot() const; + int currentFlip() const; + bool isNotPropogate() const; + bool isForce() const; Q_SIGNALS: private Q_SLOTS: diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp index a3f109ada..045b342fd 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp @@ -30,6 +30,23 @@ namespace LandscapeEditor { +LigoData::LigoData() +{ + posX = 0; + posY = 0; + zoneName = ""; + rot = 0; + flip = 0; + sharingMatNames[0] = ""; + sharingMatNames[1] = ""; + sharingMatNames[2] = ""; + sharingMatNames[3] = ""; + sharingCutEdges[0] = 0; + sharingCutEdges[1] = 0; + sharingCutEdges[2] = 0; + sharingCutEdges[3] = 0; +} + ZoneRegionEditor::ZoneRegionEditor() { m_fileName = ""; @@ -111,9 +128,58 @@ void ZoneRegionEditor::setFileName(const std::string &fileName) m_fileName = fileName; } +void ZoneRegionEditor::ligoData(LigoData &data, const sint32 x, const sint32 y) +{ + nlassert((x >= m_zoneRegion.getMinX()) && + (x <= m_zoneRegion.getMaxX()) && + (y >= m_zoneRegion.getMinY()) && + (y <= m_zoneRegion.getMaxY())); + + data.posX = m_zoneRegion.getPosX(x, y); + data.posY = m_zoneRegion.getPosY(x, y); + data.zoneName = m_zoneRegion.getName(x, y); + data.rot = m_zoneRegion.getRot(x, y); + data.flip = m_zoneRegion.getFlip(x, y); + data.sharingMatNames[0] = m_zoneRegion.getSharingMatNames(x, y, 0); + data.sharingMatNames[1] = m_zoneRegion.getSharingMatNames(x, y, 1); + data.sharingMatNames[2] = m_zoneRegion.getSharingMatNames(x, y, 2); + data.sharingMatNames[3] = m_zoneRegion.getSharingMatNames(x, y, 3); + data.sharingCutEdges[0] = m_zoneRegion.getSharingCutEdges(x, y, 0); + data.sharingCutEdges[1] = m_zoneRegion.getSharingCutEdges(x, y, 1); + data.sharingCutEdges[2] = m_zoneRegion.getSharingCutEdges(x, y, 2); + data.sharingCutEdges[3] = m_zoneRegion.getSharingCutEdges(x, y, 3); +} + +void ZoneRegionEditor::setLigoData(const LigoData &data, const sint32 x, const sint32 y) +{ + nlassert((x >= m_zoneRegion.getMinX()) && + (x <= m_zoneRegion.getMaxX()) && + (y >= m_zoneRegion.getMinY()) && + (y <= m_zoneRegion.getMaxY())); + + m_zoneRegion.setPosX(x, y, data.posX); + m_zoneRegion.setPosY(x, y, data.posY); + m_zoneRegion.setName(x, y, data.zoneName); + m_zoneRegion.setRot(x, y, data.rot); + m_zoneRegion.setFlip(x, y, data.flip); + m_zoneRegion.setSharingMatNames(x, y, 0, data.sharingMatNames[0]); + m_zoneRegion.setSharingMatNames(x, y, 1, data.sharingMatNames[1]); + m_zoneRegion.setSharingMatNames(x, y, 2, data.sharingMatNames[2]); + m_zoneRegion.setSharingMatNames(x, y, 3, data.sharingMatNames[3]); + m_zoneRegion.setSharingCutEdges(x, y, 0, data.sharingCutEdges[0]); + m_zoneRegion.setSharingCutEdges(x, y, 1, data.sharingCutEdges[1]); + m_zoneRegion.setSharingCutEdges(x, y, 2, data.sharingCutEdges[2]); + m_zoneRegion.setSharingCutEdges(x, y, 3, data.sharingCutEdges[3]); +} + NLLIGO::CZoneRegion &ZoneRegionEditor::zoneRegion() { return m_zoneRegion; } +void ZoneRegionEditor::setZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) +{ + m_zoneRegion = zoneRegion; +} + } /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h index fd53d5483..50fab0e58 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h @@ -32,6 +32,36 @@ namespace LandscapeEditor { +struct LigoData +{ + uint8 posX; + uint8 posY; + uint8 rot; + uint8 flip; + std::string zoneName; + std::string sharingMatNames[4]; + uint8 sharingCutEdges[4]; + + LigoData(); + + bool operator!= (const LigoData& other) const + { + return (posX != other.posX) || + (posY != other.posY) || + (rot != other.rot) || + (flip != other.flip) || + (zoneName != other.zoneName) || + (sharingMatNames[0] != other.sharingMatNames[0]) || + (sharingMatNames[1] != other.sharingMatNames[1]) || + (sharingMatNames[2] != other.sharingMatNames[2]) || + (sharingMatNames[3] != other.sharingMatNames[3]) || + (sharingCutEdges[0] != other.sharingCutEdges[0]) || + (sharingCutEdges[1] != other.sharingCutEdges[1]) || + (sharingCutEdges[2] != other.sharingCutEdges[2]) || + (sharingCutEdges[3] != other.sharingCutEdges[3]); + } +}; + class ZoneRegionEditor { public: @@ -44,11 +74,17 @@ public: // Save landscape data to file bool save(); + void ligoData(LigoData &data, const sint32 x, const sint32 y); + + void setLigoData(const LigoData &data, const sint32 x, const sint32 y); + // Set file name void setFileName(const std::string &fileName); NLLIGO::CZoneRegion &zoneRegion(); + void setZoneRegion(const NLLIGO::CZoneRegion &zoneRegion); + private: bool m_modified;