diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 502f4cd9ac..24ea6b2f7c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,7 @@ set(SOURCE_FILES engine/common/enums.hxx engine/common/platform.hxx engine/common/JsonSerialization.hxx + engine/events/GameEvents.{hxx,cxx} engine/GameObjects/MapNode.{hxx,cxx} engine/map/MapFunctions.{hxx,cxx} engine/GameObjects/MapGrid.hxx diff --git a/src/MainMenu.cxx b/src/MainMenu.cxx index cc74284f6c..174041222b 100644 --- a/src/MainMenu.cxx +++ b/src/MainMenu.cxx @@ -56,7 +56,8 @@ bool mainMenu() int logoTexW, logoTexH; SDL_QueryTexture(logoTex, nullptr, nullptr, &logoTexW, &logoTexH); - auto beginFrame = [] { + auto beginFrame = [] + { SDL_RenderClear(WindowManager::instance().getRenderer()); WindowManager::instance().newImGuiFrame(); @@ -66,10 +67,13 @@ bool mainMenu() ui::SetNextWindowSize(ui::GetIO().DisplaySize); bool open = true; - ui::Begin("MainWnd", &open, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); + ui::Begin("MainWnd", &open, + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | + ImGuiWindowFlags_NoScrollWithMouse); }; - auto renderFrame = [] { + auto renderFrame = [] + { ui::End(); WindowManager::instance().renderScreen(); @@ -82,7 +86,7 @@ bool mainMenu() { beginFrame(); - // break the loop if an event occurs + // break the loop if an event occurs const bool has_event = SDL_PollEvent(&event) != 0; if (has_event && event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_KEYDOWN) opacity = 254; @@ -93,7 +97,6 @@ bool mainMenu() ui::Image(logoTex, ImVec2(logoTexW, logoTexH), ImVec2(0, 0), ImVec2(1, 1), ImVec4{op, op, op, op}); ui::PopStyleVar(1); - renderFrame(); } @@ -102,10 +105,12 @@ bool mainMenu() { beginFrame(); - while (SDL_PollEvent(&event) != 0) { + while (SDL_PollEvent(&event) != 0) + { ImGui_ImplSDL2_ProcessEvent(&event); - if (event.type == SDL_QUIT) { + if (event.type == SDL_QUIT) + { startGame = false; mainMenuLoop = false; } @@ -123,27 +128,30 @@ bool mainMenu() constexpr int buttonInterval = 20; ImVec2 buttonPos(screenWidth / 2 - buttonSize.x / 2, screenHeight / 2 - buttonSize.y); ui::SetCursorPos(buttonPos); - if (ui::ButtonCt("New Game", { 200, 40 })) { - #ifdef USE_AUDIO + if (ui::ButtonCt("New Game", {200, 40})) + { +#ifdef USE_AUDIO playAudioMajorSelection(); - #endif // USE_AUDIO +#endif // USE_AUDIO mainMenuLoop = false; SignalMediator::instance().signalNewGame.emit(true); } buttonPos.y += buttonSize.y + buttonInterval; ui::SetCursorPos(buttonPos); - if (ui::ButtonCt("Load Game", { 200, 40 })) { - #ifdef USE_AUDIO + if (ui::ButtonCt("Load Game", {200, 40})) + { +#ifdef USE_AUDIO playAudioMajorSelection(); - #endif // USE_AUDIO +#endif // USE_AUDIO SignalMediator::instance().signalLoadGame.emit("save.cts"); mainMenuLoop = false; } buttonPos.y += buttonSize.y + buttonInterval; ui::SetCursorPos(buttonPos); - if (ui::ButtonCt("Quit Game", { 200, 40 })) { + if (ui::ButtonCt("Quit Game", {200, 40})) + { startGame = false; mainMenuLoop = false; } @@ -151,13 +159,15 @@ bool mainMenu() constexpr int xOffset = 5, btnSize = 32; ImVec2 leftBottom(xOffset, screenHeight - btnSize - xOffset * 2); ui::SetCursorPos(leftBottom); - if (ui::ImageButton(discordTex, ImVec2(btnSize, btnSize))) { + if (ui::ImageButton(discordTex, ImVec2(btnSize, btnSize))) + { OSystem::openDir("https://discord.gg/MG3tgYV6ce"); } leftBottom.x += xOffset * 2 + btnSize; // xOffset * 2 because, need interval between buttons ui::SetCursorPos(leftBottom); - if (ui::ImageButton(githubTex, ImVec2(btnSize, btnSize))) { + if (ui::ImageButton(githubTex, ImVec2(btnSize, btnSize))) + { OSystem::openDir("https://github.com/CytopiaTeam/Cytopia/issues/new"); } diff --git a/src/engine/EventManager.cxx b/src/engine/EventManager.cxx index be21503cc5..a962283436 100644 --- a/src/engine/EventManager.cxx +++ b/src/engine/EventManager.cxx @@ -12,6 +12,8 @@ #include "Sprite.hxx" #include "UIManager.hxx" #include +// #include +#include "events/GameEvents.hxx" #include "LOG.hxx" @@ -54,21 +56,21 @@ void EventManager::pickTileUnderCursor(Point mouseIsoCoords) // update placement mode switch (topMostActiveLayer) { - case Layer::BUILDINGS: - GameStates::instance().placementMode = PlacementMode::SINGLE; - break; - case Layer::ROAD: - case Layer::POWERLINES: - case Layer::UNDERGROUND: - GameStates::instance().placementMode = PlacementMode::LINE; - break; - case Layer::GROUND_DECORATION: - case Layer::WATER: - case Layer::ZONE: - GameStates::instance().placementMode = PlacementMode::RECTANGLE; - break; - default: - break; + case Layer::BUILDINGS: + GameStates::instance().placementMode = PlacementMode::SINGLE; + break; + case Layer::ROAD: + case Layer::POWERLINES: + case Layer::UNDERGROUND: + GameStates::instance().placementMode = PlacementMode::LINE; + break; + case Layer::GROUND_DECORATION: + case Layer::WATER: + case Layer::ZONE: + GameStates::instance().placementMode = PlacementMode::RECTANGLE; + break; + default: + break; } mapNodeData = node.getMapNodeData(); tileToPlace = mapNodeData[topMostActiveLayer].tileID; @@ -88,6 +90,9 @@ void EventManager::checkEvents(SDL_Event &event) while (SDL_PollEvent(&event)) { ImGui_ImplSDL2_ProcessEvent(&event); + //TODO: Handle UI Events before game + + GameEvents::instance().processEvents(event); switch (event.type) { @@ -302,31 +307,14 @@ void EventManager::checkEvents(SDL_Event &event) { // clear highlighting unHighlightNodes(); + // GameEvents::instance().unHighlightNodes; - // if we're panning, move the camera and break - if (m_panning) - { - if ((event.motion.xrel == 0) && (event.motion.yrel == 0)) - { - return; - } - Camera::instance().moveCamera(event.motion.xrel, event.motion.yrel); - } // check if we should highlight tiles and if we're in placement mode if (highlightSelection) { mouseScreenCoords = {event.button.x, event.button.y}; mouseIsoCoords = convertScreenToIsoCoordinates(mouseScreenCoords); - // if it's a multi-node tile, get the origin corner point - Point origCornerPoint = - MapFunctions::instance().getNodeOrigCornerPoint(mouseIsoCoords, TileManager::instance().getTileLayer(tileToPlace)); - - if (origCornerPoint == Point::INVALID()) - { - origCornerPoint = mouseIsoCoords; - } - // canceling transparent buildings for (const auto &it : m_transparentBuildings) { @@ -420,12 +408,13 @@ void EventManager::checkEvents(SDL_Event &event) } m_placementAllowed = MapFunctions::instance().isPlacementOnAreaAllowed(m_nodesToHighlight, tileToPlace); - + // Finally highlight all the tiles we've found // Set highlighted tiles that can be placed and can't be placed different color for (const auto &highlitNode : m_nodesToHighlight) { - if (!MapFunctions::instance().isPlacementOnNodeAllowed(highlitNode, tileToPlace) || demolishMode) + if (!m_placementAllowed || demolishMode) + // if (!MapFunctions::instance().isPlacementOnNodeAllowed(highlitNode, tileToPlace) || demolishMode) { // mark red MapFunctions::instance().highlightNode(highlitNode, SpriteHighlightColor::RED); @@ -454,7 +443,7 @@ void EventManager::checkEvents(SDL_Event &event) } break; case SDL_MOUSEBUTTONDOWN: - m_placementAllowed = false; + // m_placementAllowed = false; m_skipLeftClick = false; // check for UI events first for (const auto &it : uiManager.getAllUiElementsForEventHandling()) @@ -465,14 +454,13 @@ void EventManager::checkEvents(SDL_Event &event) break; } } - - if (event.button.button == SDL_BUTTON_RIGHT) + switch (event.button.button) { + case SDL_BUTTON_RIGHT: m_panning = true; m_cancelTileSelection = true; - } - else if (event.button.button == SDL_BUTTON_LEFT) - { + break; + case SDL_BUTTON_LEFT: // game event handling mouseScreenCoords = {event.button.x, event.button.y}; mouseIsoCoords = convertScreenToIsoCoordinates(mouseScreenCoords); @@ -487,6 +475,7 @@ void EventManager::checkEvents(SDL_Event &event) { if (!coordinate.isWithinMapBoundaries()) { + LOG(LOG_ERROR) << "not canPlac e"; canPlaceTileID = false; break; } @@ -496,7 +485,6 @@ void EventManager::checkEvents(SDL_Event &event) if (canPlaceTileID) { m_clickDownCoords = mouseIsoCoords; - m_placementAllowed = true; // Nodes to place are collected during the mouse move. // In case of multiple left clicks without moving the mouse, node to place will be the node of the mouse click. @@ -506,6 +494,11 @@ void EventManager::checkEvents(SDL_Event &event) } m_isPuttingTile = true; } + else + { + LOG(LOG_ERROR) << "boeser else"; + m_placementAllowed = false; + } } break; @@ -601,7 +594,8 @@ void EventManager::checkEvents(SDL_Event &event) if (highlightSelection) { m_nodesToHighlight.push_back(mouseIsoCoords); - if (!tileToPlace.empty() && !MapFunctions::instance().setTileID(tileToPlace, mouseIsoCoords)) + if (!tileToPlace.empty() && !MapFunctions::instance().isPlacementOnAreaAllowed(m_nodesToHighlight, tileToPlace)) + // if (!tileToPlace.empty() && !MapFunctions::instance().setTileID(tileToPlace, mouseIsoCoords)) { MapFunctions::instance().highlightNode(mouseIsoCoords, SpriteHighlightColor::RED); } @@ -613,16 +607,7 @@ void EventManager::checkEvents(SDL_Event &event) break; } - case SDL_MOUSEWHEEL: - if (event.wheel.y > 0) - { - Camera::instance().increaseZoomLevel(); - } - else if (event.wheel.y < 0) - { - Camera::instance().decreaseZoomLevel(); - } - break; + default: break; diff --git a/src/engine/GameObjects/MapNode.cxx b/src/engine/GameObjects/MapNode.cxx index c23ddd62ab..0ac1edc86e 100644 --- a/src/engine/GameObjects/MapNode.cxx +++ b/src/engine/GameObjects/MapNode.cxx @@ -5,9 +5,10 @@ #include "../map/MapLayers.hxx" #include "GameStates.hxx" #include "Settings.hxx" +#include "MapFunctions.hxx" MapNode::MapNode(Point isoCoordinates, const std::string &terrainID, const std::string &tileID) - : m_isoCoordinates(std::move(isoCoordinates)), m_sprite{std::make_unique(m_isoCoordinates)}, + : m_isoCoordinates(isoCoordinates), m_originCoordinates(isoCoordinates), m_sprite{std::make_unique(m_isoCoordinates)}, m_autotileOrientation(LAYERS_COUNT, TileOrientation::TILE_DEFAULT_ORIENTATION), m_mapNodeData{std::vector(LAYERS_COUNT, MapNodeData{"", nullptr, 0, m_isoCoordinates, TileMap::DEFAULT})}, m_autotileBitmask(LAYERS_COUNT) @@ -49,9 +50,59 @@ void MapNode::setBitmask(unsigned char elevationBitmask, std::vector au void MapNode::setTileID(const std::string &tileID, const Point &origCornerPoint) { + //TODO: don't set ^if not origin, extra function + // set other nodes to invis. + // if other node is not origin, return tileID of origin + // TODO: Reset everything on demolish + // TODO: Find out what's missing for other things to work + // TODO: remove origincornerpoint stuff TileData *tileData = TileManager::instance().getTileData(tileID); if (tileData && !tileID.empty()) { + m_originCoordinates = origCornerPoint; + + std::vector targetCoordinates = TileManager::instance().getTargetCoordsOfTileID(origCornerPoint, tileID); + if (targetCoordinates.size() > 1 && m_isoCoordinates == origCornerPoint) + { // multibuilding placed on this node + // int minZ = m_isoCoordinates.z; + // LOG(LOG_INFO) << "old z " << minZ; + int minY = 0; + // set origin corner node + // for (auto coord : targetCoordinates) + // { + // if (coord.x == origCornerPoint.x) + // { + // minZ = std::min(minZ, MapFunctions::instance().getMapNode(coord).getCoordinates().z); + // LOG(LOG_INFO) << "Setting new z " << minZ; + // } + // } + for (auto coord : targetCoordinates) + { + + if (coord == origCornerPoint) + { + m_originCoordinates = origCornerPoint; + // LOG(LOG_INFO) << "i'm the origin coordinate"; + } + else + { + // LOG(LOG_ERROR) << "it's mjultile"; + // m_isOriginNode = false; + m_multiTileCoords.push_back(coord); + // m_multiTileNodes.push_back(&MapFunctions::instance().getMapNode(coord)); + MapFunctions::instance().getMapNode(coord).getSprite()->setRenderFlag(Layer::BUILDINGS, false); + // MapFunctions::instance().getMapNode(coord).setRenderFlag(Layer::TERRAIN, false); + MapFunctions::instance().getMapNode(coord).updateTexture(Layer::BUILDINGS); + // MapFunctions::instance().getMapNode(coord).updateTexture(Layer::TERRAIN); + // MapFunctions::instance().getMapNode(coord).setTileID(tileID, origCornerPoint); + MapFunctions::instance().getMapNode(coord).setOriginCoordinate(origCornerPoint); + // MapFunctions::instance().getMapNode(coord).setTileID("terrain_basalt", origCornerPoint); + // MapFunctions::instance().getMapNode(coord).setZIndex(minZ); + + // LOG(LOG_INFO) << "i'm a multinode"; + } + } + } const Layer layer = TileManager::instance().getTileLayer(tileID); switch (layer) { @@ -106,7 +157,7 @@ Layer MapNode::getTopMostActiveLayer() const { for (auto currentLayer : layersInActiveOrder) { - if (MapLayers::isLayerActive(currentLayer) && m_mapNodeData[currentLayer].tileData) + if (MapLayers::isLayerActive(currentLayer) && isLayerOccupied(currentLayer)) { return currentLayer; } @@ -168,7 +219,7 @@ bool MapNode::isPlacementAllowed(const std::string &newTileID) const return true; } case Layer::ROAD: - if ((isLayerOccupied(Layer::BUILDINGS) && (m_mapNodeData[Layer::BUILDINGS].tileData->category != "Flora")) || + if ((isLayerOccupied(Layer::BUILDINGS) && getTileData(Layer::BUILDINGS)->category != "Flora") || isLayerOccupied(Layer::WATER) || !isPlacableOnSlope(newTileID)) { // roads cannot be placed: // - on buildings that are not category flora. @@ -178,13 +229,13 @@ bool MapNode::isPlacementAllowed(const std::string &newTileID) const } return true; case Layer::GROUND_DECORATION: - if (m_mapNodeData[Layer::GROUND_DECORATION].tileData || m_mapNodeData[Layer::BUILDINGS].tileData) + if (isLayerOccupied(Layer::GROUND_DECORATION) || isLayerOccupied(Layer::BUILDINGS)) { // allow placement of ground decoration on existing ground decoration and on buildings. return true; } break; case Layer::FLORA: - if (m_mapNodeData[Layer::FLORA].tileData && m_mapNodeData[Layer::FLORA].tileData->isOverPlacable) + if (isLayerOccupied(Layer::FLORA) && getTileData(Layer::FLORA)->isOverPlacable) { // flora with overplacable flag return true; } @@ -195,8 +246,7 @@ bool MapNode::isPlacementAllowed(const std::string &newTileID) const break; case Layer::BUILDINGS: { - TileData *tileDataBuildings = m_mapNodeData[Layer::BUILDINGS].tileData; - if (tileDataBuildings && tileDataBuildings->isOverPlacable) + if (isLayerOccupied(Layer::BUILDINGS) && getTileData(Layer::BUILDINGS)->isOverPlacable) { // buildings with overplacable flag return true; } @@ -265,18 +315,17 @@ void MapNode::updateTexture(const Layer &layer) { layersToGoOver.insert(layersToGoOver.begin(), std::begin(allLayersOrdered), std::end(allLayersOrdered)); } - for (auto currentLayer : layersToGoOver) { - if (m_mapNodeData[currentLayer].tileData) + const TileData *tileData = getTileData(currentLayer); + if (tileData) { size_t spriteCount = 1; m_mapNodeData[currentLayer].tileMap = TileMap::DEFAULT; if (m_elevationOrientation == TileSlopes::DEFAULT_ORIENTATION) { - if (m_mapNodeData[currentLayer].tileData->tileType == +TileType::WATER || - m_mapNodeData[currentLayer].tileData->tileType == +TileType::TERRAIN || - m_mapNodeData[currentLayer].tileData->tileType == +TileType::BLUEPRINT) + if (tileData->tileType == +TileType::WATER || tileData->tileType == +TileType::TERRAIN || + tileData->tileType == +TileType::BLUEPRINT) { m_autotileOrientation[currentLayer] = TileManager::instance().calculateTileOrientation(m_autotileBitmask[currentLayer]); m_mapNodeData[currentLayer].tileMap = TileMap::DEFAULT; @@ -295,7 +344,7 @@ void MapNode::updateTexture(const Layer &layer) } else if (m_elevationOrientation >= TileSlopes::N && m_elevationOrientation <= TileSlopes::BETWEEN) { - if (m_mapNodeData[currentLayer].tileData->slopeTiles.fileName.empty()) + if (tileData->slopeTiles.fileName.empty()) { m_mapNodeData[currentLayer].tileMap = TileMap::DEFAULT; m_autotileOrientation[currentLayer] = TileOrientation::TILE_DEFAULT_ORIENTATION; @@ -306,18 +355,19 @@ void MapNode::updateTexture(const Layer &layer) m_autotileOrientation[currentLayer] = static_cast(m_elevationOrientation); } } + const TileData *tileData = getTileData(currentLayer); switch (m_mapNodeData[currentLayer].tileMap) { case TileMap::DEFAULT: - m_clippingWidth = m_mapNodeData[currentLayer].tileData->tiles.clippingWidth; + m_clippingWidth = tileData->tiles.clippingWidth; if (m_mapNodeData[currentLayer].tileIndex != 0) { clipRect.x = m_clippingWidth * m_mapNodeData[currentLayer].tileIndex; } else { - if (m_mapNodeData[currentLayer].tileData->tileType == +TileType::POWERLINE && + if (tileData->tileType == +TileType::POWERLINE && std::any_of(layersPowerlinesCanCross.begin(), layersPowerlinesCanCross.end(), [this](const Layer &_layer) { return this->m_mapNodeData[_layer].tileData; })) { // if we place a power line cross low terrain (eg, roads, water, flora) @@ -334,7 +384,7 @@ void MapNode::updateTexture(const Layer &layer) } } // only check for rectangular roads when there are frames for it. Spritesheets with rect-roads have 20 items - if (GameStates::instance().rectangularRoads && m_mapNodeData[currentLayer].tileData->tiles.count == 20) + if (GameStates::instance().rectangularRoads && tileData->tiles.count == 20) { switch (m_autotileOrientation[currentLayer]) { @@ -360,17 +410,17 @@ void MapNode::updateTexture(const Layer &layer) if (!m_mapNodeData[currentLayer].tileID.empty()) { - m_sprite->setClipRect({clipRect.x + m_clippingWidth * m_mapNodeData[currentLayer].tileData->tiles.offset, 0, - m_clippingWidth, m_mapNodeData[currentLayer].tileData->tiles.clippingHeight}, - static_cast(currentLayer)); + m_sprite->setClipRect( + {clipRect.x + m_clippingWidth * tileData->tiles.offset, 0, m_clippingWidth, tileData->tiles.clippingHeight}, + static_cast(currentLayer)); m_sprite->setTexture(TileManager::instance().getTexture(m_mapNodeData[currentLayer].tileID), static_cast(currentLayer)); } - spriteCount = m_mapNodeData[currentLayer].tileData->tiles.count; + spriteCount = tileData->tiles.count; break; case TileMap::SHORE: - m_clippingWidth = m_mapNodeData[currentLayer].tileData->shoreTiles.clippingWidth; + m_clippingWidth = tileData->shoreTiles.clippingWidth; if (m_mapNodeData[currentLayer].tileIndex != 0) { clipRect.x = m_clippingWidth * m_mapNodeData[currentLayer].tileIndex; @@ -382,31 +432,29 @@ void MapNode::updateTexture(const Layer &layer) if (!m_mapNodeData[currentLayer].tileID.empty()) { - m_sprite->setClipRect({clipRect.x + m_clippingWidth * m_mapNodeData[currentLayer].tileData->shoreTiles.offset, 0, - m_clippingWidth, m_mapNodeData[currentLayer].tileData->shoreTiles.clippingHeight}, + m_sprite->setClipRect({clipRect.x + m_clippingWidth * tileData->shoreTiles.offset, 0, m_clippingWidth, + tileData->shoreTiles.clippingHeight}, static_cast(currentLayer)); m_sprite->setTexture(TileManager::instance().getTexture(m_mapNodeData[currentLayer].tileID + "_shore"), static_cast(currentLayer)); } - spriteCount = m_mapNodeData[currentLayer].tileData->shoreTiles.count; + spriteCount = tileData->shoreTiles.count; break; case TileMap::SLOPES: - if (m_mapNodeData[currentLayer].tileData->slopeTiles.fileName.empty()) + if (tileData->slopeTiles.fileName.empty()) { break; } - m_clippingWidth = m_mapNodeData[currentLayer].tileData->slopeTiles.clippingWidth; - clipRect.x = m_mapNodeData[currentLayer].tileData->slopeTiles.clippingWidth * - static_cast(m_autotileOrientation[currentLayer]); - spriteCount = m_mapNodeData[currentLayer].tileData->slopeTiles.count; + m_clippingWidth = tileData->slopeTiles.clippingWidth; + clipRect.x = tileData->slopeTiles.clippingWidth * static_cast(m_autotileOrientation[currentLayer]); + spriteCount = tileData->slopeTiles.count; if (clipRect.x <= static_cast(spriteCount) * m_clippingWidth) { - m_sprite->setClipRect({clipRect.x + m_mapNodeData[currentLayer].tileData->slopeTiles.offset * m_clippingWidth, 0, - m_clippingWidth, m_mapNodeData[currentLayer].tileData->slopeTiles.clippingHeight}, + m_sprite->setClipRect({clipRect.x + tileData->slopeTiles.offset * m_clippingWidth, 0, m_clippingWidth, + tileData->slopeTiles.clippingHeight}, static_cast(currentLayer)); - m_sprite->setTexture(TileManager::instance().getTexture(m_mapNodeData[currentLayer].tileID), - static_cast(currentLayer)); + m_sprite->setTexture(TileManager::instance().getTexture(getTileID(currentLayer)), static_cast(currentLayer)); } break; default: @@ -418,7 +466,7 @@ void MapNode::updateTexture(const Layer &layer) m_mapNodeData[currentLayer].tileID = m_previousTileID; if (m_previousTileID.empty()) { - m_mapNodeData[currentLayer].tileData = nullptr; + tileData = nullptr; } updateTexture(currentLayer); } @@ -478,20 +526,23 @@ void MapNode::demolishNode(const Layer &demolishLayer) for (auto &layer : layersToDemolish) { - if (MapLayers::isLayerActive(layer) && m_mapNodeData[layer].tileData) + if (MapLayers::isLayerActive(layer) && isLayerOccupied(layer)) { - if ((GameStates::instance().demolishMode == DemolishMode::DEFAULT && - m_mapNodeData[layer].tileData->tileType == +TileType::ZONE) || - (GameStates::instance().demolishMode == DemolishMode::DE_ZONE && - m_mapNodeData[layer].tileData->tileType != +TileType::ZONE) || + if ((GameStates::instance().demolishMode == DemolishMode::DEFAULT && getTileData(layer)->tileType == +TileType::ZONE) || + (GameStates::instance().demolishMode == DemolishMode::DE_ZONE && getTileData(layer)->tileType != +TileType::ZONE) || (GameStates::instance().demolishMode == DemolishMode::GROUND_DECORATION && - m_mapNodeData[layer].tileData->tileType != +TileType::GROUNDDECORATION)) + getTileData(layer)->tileType != +TileType::GROUNDDECORATION)) { continue; } this->demolishLayer(layer); if (layer == Layer::BUILDINGS) { + for (auto coord : m_multiTileCoords) + { + MapFunctions::instance().getMapNode(coord).demolishNode(layer); + MapFunctions::instance().getMapNode(coord).getSprite()->setRenderFlag(layer, true); + } this->setNodeTransparency(0, Layer::BLUEPRINT); } updateTexture(demolishLayer); @@ -501,12 +552,43 @@ void MapNode::demolishNode(const Layer &demolishLayer) const bool MapNode::isConductive() const { - if (getTileData(Layer::BUILDINGS) || getTileData(Layer::POWERLINES) || getTileData(Layer::ZONE)) + std::vector conductiveLayers = {Layer::BUILDINGS, Layer::POWERLINES, Layer::ZONE}; + + for (auto layer : conductiveLayers) { - return true; + if ((!isOriginNode() && MapFunctions::instance().getMapNode(m_originCoordinates).getTileData(layer)) || + (isOriginNode() && getTileData(layer))) + { // if it's part of a multitilenode (not an originnode, has coordinates of the originnode and there's something placed on a conductive layer) + // or if it an origin node and a conductive layer + return true; + } } - else + return false; +} + +const TileData *MapNode::getTileData(Layer layer) const +{ + if (!isOriginNode()) + { + return MapFunctions::instance().getMapNode(m_originCoordinates).getTileData(layer); + } + return m_mapNodeData[layer].tileData; +} + +const std::string &MapNode::getTileID(Layer layer) const +{ + if (!isOriginNode()) { - return false; + return MapFunctions::instance().getMapNode(m_originCoordinates).getMapNodeDataForLayer(layer).tileID; } + return m_mapNodeData[layer].tileID; } + +const MapNodeData &MapNode::getMapNodeDataForLayer(Layer layer) const +{ + if (!isOriginNode()) + { + return MapFunctions::instance().getMapNode(m_originCoordinates).getMapNodeDataForLayer(layer); + } + return m_mapNodeData[layer]; +}; diff --git a/src/engine/GameObjects/MapNode.hxx b/src/engine/GameObjects/MapNode.hxx index cdd5e79ee8..4d2f4b25b5 100644 --- a/src/engine/GameObjects/MapNode.hxx +++ b/src/engine/GameObjects/MapNode.hxx @@ -35,11 +35,11 @@ public: /** @brief Move constructor. */ MapNode(MapNode &&mn) noexcept - : m_isoCoordinates(std::move(mn.m_isoCoordinates)), m_sprite(std::move(mn.m_sprite)), - m_previousTileID(std::move(mn.m_previousTileID)), m_autotileOrientation(std::move(mn.m_autotileOrientation)), - m_elevationOrientation(mn.m_elevationOrientation), m_clippingWidth(mn.m_clippingWidth), - m_mapNodeData(std::move(mn.m_mapNodeData)), m_autotileBitmask(std::move(mn.m_autotileBitmask)), - m_elevationBitmask(mn.m_elevationBitmask){}; + : m_isoCoordinates(std::move(mn.m_isoCoordinates)), m_originCoordinates(std::move(mn.m_originCoordinates)), + m_sprite(std::move(mn.m_sprite)), m_previousTileID(std::move(mn.m_previousTileID)), + m_autotileOrientation(std::move(mn.m_autotileOrientation)), m_elevationOrientation(mn.m_elevationOrientation), + m_clippingWidth(mn.m_clippingWidth), m_mapNodeData(std::move(mn.m_mapNodeData)), + m_autotileBitmask(std::move(mn.m_autotileBitmask)), m_elevationBitmask(mn.m_elevationBitmask){}; /** * @brief Destroys the MapNode object @@ -81,12 +81,12 @@ public: unsigned char getElevationBitmask() const { return m_elevationBitmask; }; - const TileData *getTileData(Layer layer) const { return m_mapNodeData[layer].tileData; }; + const TileData *getTileData(Layer layer) const; /** @brief get TileID of specific layer inside NodeData. * @param layer what layer should be checked on. */ - const std::string &getTileID(Layer layer) const { return m_mapNodeData[layer].tileID; }; + const std::string &getTileID(Layer layer) const; bool isPlacementAllowed(const std::string &newTileID) const; @@ -94,7 +94,7 @@ public: void setMapNodeData(std::vector &&mapNodeData); const std::vector &getMapNodeData() const { return m_mapNodeData; }; - const MapNodeData &getMapNodeDataForLayer(Layer layer) const { return m_mapNodeData[layer]; }; + const MapNodeData &getMapNodeDataForLayer(Layer layer) const; const MapNodeData &getActiveMapNodeData() const; @@ -122,6 +122,12 @@ public: */ void demolishLayer(const Layer &layer); + /** + * @brief Set the Tile I D object on this node + * This function does not check if a tile can be placed, just bluntly places it. The checks need to happen in MapFunctions + * @param tileType + * @param origPoint + */ void setTileID(const std::string &tileType, const Point &origPoint); /** @@ -130,7 +136,7 @@ public: * @param layer the layer that should be checked * @return const Point& */ - const Point &getOrigCornerPoint(Layer layer) const { return getMapNodeDataForLayer(layer).origCornerPoint; } + const Point &getOrigCornerPoint(Layer layer) const { return m_originCoordinates; } /** * @brief If this is the origin node of a multitile building. @@ -140,7 +146,7 @@ public: */ bool isOriginNode(Layer layer = Layer::BUILDINGS) const { - return (m_isoCoordinates == getMapNodeDataForLayer(layer).origCornerPoint); + return (m_originCoordinates != Point::INVALID() && m_isoCoordinates == m_originCoordinates); } /** @brief return topmost active layer. @@ -149,7 +155,7 @@ public: */ Layer getTopMostActiveLayer() const; - bool isLayerOccupied(const Layer &layer) const { return m_mapNodeData[layer].tileData != nullptr; } + bool isLayerOccupied(const Layer &layer) const { return getTileData(layer) != nullptr; } /** @brief Set elevation bit mask. * @param bitMask @@ -182,7 +188,17 @@ public: /// Maximum height of the node. static const int maxHeight = 32; + void setOriginCoordinate(Point coordinate) + { + m_originCoordinates = coordinate; + // if(m_isoCoordinates)!= coordinate){m_originCoordinates} + }; + + const std::vector &getMultiTileCoords() const { return m_multiTileCoords; }; + private: + bool m_isOriginNode = true; + Point m_originCoordinates; Point m_isoCoordinates; std::unique_ptr m_sprite; std::string m_previousTileID = "terrain"; @@ -192,5 +208,6 @@ private: std::vector m_mapNodeData; std::vector m_autotileBitmask; unsigned char m_elevationBitmask = 0; + std::vector m_multiTileCoords; // keep coords to other nodes if this is a multile building }; #endif diff --git a/src/engine/TileManager.cxx b/src/engine/TileManager.cxx index 7904c3e046..3bedf28394 100644 --- a/src/engine/TileManager.cxx +++ b/src/engine/TileManager.cxx @@ -19,10 +19,10 @@ SDL_Texture *TileManager::getTexture(const std::string &tileID) const return ResourcesManager::instance().getTileTexture(tileID); } -TileData *TileManager::getTileData(const std::string &id) noexcept +TileData *TileManager::getTileData(const std::string &tileID) noexcept { - if (m_tileData.count(id)) - return &m_tileData[id]; + if (m_tileData.count(tileID)) + return &m_tileData[tileID]; return nullptr; } diff --git a/src/engine/TileManager.hxx b/src/engine/TileManager.hxx index f57ee05cc5..165eda7a45 100644 --- a/src/engine/TileManager.hxx +++ b/src/engine/TileManager.hxx @@ -87,7 +87,7 @@ public: * @param id TileID * @return A pointer to the TileData Struct */ - TileData *getTileData(const std::string &id) noexcept; + TileData *getTileData(const std::string &tileID) noexcept; /** @brief Get the Layer that is associated with a tileID. The Tile will be placed on this layer * @param tileID the tileID to get the Layer for diff --git a/src/engine/UIManager.cxx b/src/engine/UIManager.cxx index 58e0f45005..1aceb19a70 100644 --- a/src/engine/UIManager.cxx +++ b/src/engine/UIManager.cxx @@ -90,7 +90,8 @@ void UIManager::initializeImGuiFonts() { } } -void UIManager::loadSettings(json& uiLayout) { +void UIManager::loadSettings(json &uiLayout) +{ std::string jsonFileContent = fs::readFileAsString(Settings::instance().uiLayoutJSONFile.get()); uiLayout = json::parse(jsonFileContent, nullptr, false); @@ -99,7 +100,7 @@ void UIManager::loadSettings(json& uiLayout) { throw ConfigurationError(TRACE_INFO "Error parsing JSON File " + Settings::instance().uiLayoutJSONFile.get()); } -void UIManager::parseLayouts(const json& uiLayout) +void UIManager::parseLayouts(const json &uiLayout) { // parse Layout for (const auto &it : uiLayout["LayoutGroups"].items()) @@ -141,7 +142,8 @@ void UIManager::parseLayouts(const json& uiLayout) continue; } - layoutGroup.layout.fontSize = uiLayout["LayoutGroups"][it.key()][id].value("FontSize", Settings::instance().defaultFontSize); + layoutGroup.layout.fontSize = + uiLayout["LayoutGroups"][it.key()][id].value("FontSize", Settings::instance().defaultFontSize); layoutGroup.layout.padding = uiLayout["LayoutGroups"][it.key()][id].value("Padding", 0); layoutGroup.layout.paddingToParent = uiLayout["LayoutGroups"][it.key()][id].value("PaddingToParent", 0); layoutGroup.layout.alignmentOffset = uiLayout["LayoutGroups"][it.key()][id].value("AlignmentOffset", 0.0F); @@ -157,7 +159,8 @@ void UIManager::parseLayouts(const json& uiLayout) } } -void UIManager::parseElements(const json &uiLayout) { +void UIManager::parseElements(const json &uiLayout) +{ // parse UiElements for (const auto &it : uiLayout["UiElements"].items()) { @@ -206,7 +209,7 @@ void UIManager::parseElements(const json &uiLayout) { auto buttonGroupID = element.value("ButtonGroup", ""); auto buildMenuID = element.value("BuildMenuID", ""); - SDL_Rect elementRect{ 0, 0, 0, 0 }; + SDL_Rect elementRect{0, 0, 0, 0}; elementRect.x = element.value("Position_x", 0); elementRect.y = element.value("Position_y", 0); elementRect.w = element.value("Width", 0); @@ -215,7 +218,8 @@ void UIManager::parseElements(const json &uiLayout) { uint32_t defaultFontSize = m_layoutGroups[layoutGroupName].layout.fontSize; uint32_t fontSize = defaultFontSize; - if (element.count("FontSize")) { + if (element.count("FontSize")) + { fontSize = element["FontSize"].get(); } diff --git a/src/engine/WindowManager.cxx b/src/engine/WindowManager.cxx index 4cac1a827c..6f9d6efcc6 100644 --- a/src/engine/WindowManager.cxx +++ b/src/engine/WindowManager.cxx @@ -36,8 +36,7 @@ WindowManager::WindowManager() if (!m_window) throw UIError(TRACE_INFO "Failed to create window: " + string{SDL_GetError()}); - rendererFlags = SDL_RENDERER_ACCELERATED - | (Settings::instance().vSync ? SDL_RENDERER_PRESENTVSYNC : 0); + rendererFlags = SDL_RENDERER_ACCELERATED | (Settings::instance().vSync ? SDL_RENDERER_PRESENTVSYNC : 0); #if defined(TESTING_ENABLED) && defined(__linux) // Set the index to 2 for running tests @@ -179,7 +178,7 @@ void WindowManager::initializeImguiRenderer() ImGui_ImplSDLRenderer_Init(m_renderer); } -void WindowManager::destroyImGuiRenderer() +void WindowManager::destroyImGuiRenderer() { ImGui_ImplSDLRenderer_Shutdown(); ImGui_ImplSDL2_Shutdown(); @@ -226,7 +225,7 @@ void WindowManager::newImGuiFrame() { ImGui_ImplSDLRenderer_NewFrame(); ImGui_ImplSDL2_NewFrame(); - ImGui::NewFrame(); + ImGui::NewFrame(); } void WindowManager::renderScreen() diff --git a/src/engine/events/GameEvents.cxx b/src/engine/events/GameEvents.cxx new file mode 100644 index 0000000000..ae8bf8c048 --- /dev/null +++ b/src/engine/events/GameEvents.cxx @@ -0,0 +1,88 @@ +#include "GameEvents.hxx" +#include +#include +#include "../basics/isoMath.hxx" + +#include + +void GameEvents::unHighlightNodes() +{ + // if (!m_isPuttingTile) + // { + // for (auto node : m_nodesToPlace) + // { + // MapFunctions::instance().unHighlightNode(node); + // } + // m_nodesToPlace.clear(); + // } + for (auto node : m_nodesToHighlight) + { + MapFunctions::instance().unHighlightNode(node); + } + m_nodesToHighlight.clear(); +} + +void GameEvents::processEvents(SDL_Event &event) +{ + if (!MapFunctions::instance().getMap()) + { // abort if there's no map to interact with + return; + } + + SDL_Point mouseScreenCoords = {event.button.x, event.button.y}; + Point mouseIsoCoords = convertScreenToIsoCoordinates(mouseScreenCoords); + + switch (event.type) + { + // ----- MOUSE MOTION + case SDL_MOUSEMOTION: + if (mouseDownRight) + { // if the right mouse button is being held down, pan the map + if ((event.motion.xrel == 0) && (event.motion.yrel == 0)) + { + return; + } + Camera::instance().moveCamera(event.motion.xrel, event.motion.yrel); + break; // when we're panning, don't handle other events + } + + // clear highlighting, we'll rebuild it now + unHighlightNodes(); + + break; + + // ----- MOUSEBUTTON DOWN + case SDL_MOUSEBUTTONUP: + //reset all states when we lift the mouse button + mouseDown = false; + mouseDownLeft = false; + mouseDownRight = false; + + break; + case SDL_MOUSEBUTTONDOWN: + mouseDown = true; + LOG(LOG_DEBUG) << "Hello from GameEvents()"; + switch (event.button.button) + { + case SDL_BUTTON_RIGHT: + mouseDownRight = true; + // m_panning = true; + // m_cancelTileSelection = true; + break; + case SDL_BUTTON_LEFT: + mouseDownLeft = true; + break; + } + break; + case SDL_MOUSEWHEEL: + if (event.wheel.y > 0) + { + Camera::instance().increaseZoomLevel(); + } + else if (event.wheel.y < 0) + { + Camera::instance().decreaseZoomLevel(); + } + break; + } +} diff --git a/src/engine/events/GameEvents.hxx b/src/engine/events/GameEvents.hxx new file mode 100644 index 0000000000..88b37cedf6 --- /dev/null +++ b/src/engine/events/GameEvents.hxx @@ -0,0 +1,25 @@ +#ifndef GAME_EVENTS_HXX_ +#define GAME_EVENTS_HXX_ + +#include +#include + +class GameEvents : public Singleton +{ +public: + GameEvents() = default; + + void unHighlightNodes(); + void addNodesToHighlight(); + + void processEvents(SDL_Event &event); + +private: + std::vector m_nodesToHighlight = {}; + + bool mouseDown=false; + bool mouseDownLeft=false; + bool mouseDownRight=false; +}; + +#endif \ No newline at end of file diff --git a/src/engine/map/MapFunctions.cxx b/src/engine/map/MapFunctions.cxx index 5b85faa621..68c8a66a9e 100644 --- a/src/engine/map/MapFunctions.cxx +++ b/src/engine/map/MapFunctions.cxx @@ -13,10 +13,7 @@ #include #include -MapFunctions::MapFunctions() -{ - SignalMediator::instance().registerCbSaveGame(Signal::slot(this, &MapFunctions::saveMapToFile)); -} +MapFunctions::MapFunctions() { SignalMediator::instance().registerCbSaveGame(Signal::slot(this, &MapFunctions::saveMapToFile)); } bool MapFunctions::updateHeight(Point coordinate, const bool elevate) { @@ -120,7 +117,7 @@ void MapFunctions::updateNodeNeighbors(const std::vector &nodes) if (std::abs(heightDiff) > 1) { - updatedNodes.push(getMapNode(neighborCoords).getCoordinates()); + updatedNodes.push(neighborCoords); updateHeight(neighborCoords, (heightDiff > 1) ? true : false); } } @@ -194,19 +191,19 @@ std::vector MapFunctions::getNeighborNodes(const Point &isoCoordin return neighbors; } -bool MapFunctions::isPlacementOnNodeAllowed(const Point &isoCoordinates, const std::string &tileID) const +bool MapFunctions::isPlacementOnNodeAllowed(const Point &isoCoordinates, const std::string &tileID) { - return m_map->mapNodes[isoCoordinates.toIndex()].isPlacementAllowed(tileID); + // LOG(LOG_DEBUG) << "isPlacementOnAreaAllowed called for " << isoCoordinates.x << ", " << isoCoordinates.y; + return getOriginMapNode(isoCoordinates).isPlacementAllowed(tileID); } -bool MapFunctions::isPlacementOnAreaAllowed(const std::vector &targetCoordinates, const std::string &tileID) const +bool MapFunctions::isPlacementOnAreaAllowed(const std::vector &targetCoordinates, const std::string &tileID) { + // LOG(LOG_FATAL) << "isPlacementOnAreaAllowed() called"; // This function can be divided into two policies: // Whether we need all nodes in the area to be placed or not bool shouldAllNodesPlaced = true; - bool areaPlacementAllowed = true; bool tilePlacementAllowed = true; - const Layer layer = TileManager::instance().getTileLayer(tileID); // Only buildings and roads has to be placed on all of the tile selected. // Other layers can be placed on part of tile in the area, such as zone, water, flora. @@ -218,25 +215,33 @@ bool MapFunctions::isPlacementOnAreaAllowed(const std::vector &targetCoor { shouldAllNodesPlaced = false; } - areaPlacementAllowed = shouldAllNodesPlaced; for (auto coord : targetCoordinates) { - tilePlacementAllowed = isPlacementOnNodeAllowed(coord, tileID); + // tilePlacementAllowed = isPlacementOnNodeAllowed(coord, tileID); - if (tilePlacementAllowed && !shouldAllNodesPlaced) - { - areaPlacementAllowed = true; - break; - } - if (!tilePlacementAllowed && shouldAllNodesPlaced) + if (!isPlacementOnNodeAllowed(coord, tileID)) { - areaPlacementAllowed = false; - break; + // LOG(LOG_DEBUG) << "----- DISALLOWED"; + tilePlacementAllowed = false; } - } - - return areaPlacementAllowed; + // if (tilePlacementAllowed && !shouldAllNodesPlaced) + // { + // continue; + // } + // if (!tilePlacementAllowed && shouldAllNodesPlaced) + // { + // LOG(LOG_DEBUG) << "isPlacementOnNodeAllowed return false can't place"; + + // return false; + // break; + // } + } + // if (!tilePlacementAllowed && !shouldAllNodesPlaced) + // tilePlacementAllowed = true; + // if(tilePlacementAllowed) + // LOG(LOG_DEBUG) << "----- ALLOWED"; + return tilePlacementAllowed; } unsigned char MapFunctions::getElevatedNeighborBitmask(Point centerCoordinates) @@ -271,7 +276,7 @@ std::vector MapFunctions::calculateAutotileBitmask(Point coordinate) for (auto currentLayer : allLayersOrdered) { - auto pCurrentTileData = getMapNode(coordinate).getMapNodeDataForLayer(currentLayer).tileData; + auto pCurrentTileData = getMapNode(coordinate).getTileData(currentLayer); if (pCurrentTileData) { @@ -279,7 +284,7 @@ std::vector MapFunctions::calculateAutotileBitmask(Point coordinate) { for (const auto &neighbor : getNeighborNodes(coordinate, false)) { - const auto pTileData = neighbor.pNode->getMapNodeDataForLayer(Layer::WATER).tileData; + const auto pTileData = neighbor.pNode->getTileData(Layer::WATER); if (pTileData && pTileData->tileType == +TileType::WATER) { @@ -289,14 +294,14 @@ std::vector MapFunctions::calculateAutotileBitmask(Point coordinate) } // only auto-tile categories that can be tiled. - const std::string &nodeTileId = getMapNode(coordinate).getMapNodeDataForLayer(currentLayer).tileID; + const std::string &nodeTileId = getMapNode(coordinate).getTileID(currentLayer); if (TileManager::instance().isTileIDAutoTile(nodeTileId)) { for (const auto &neighbor : getNeighborNodes(coordinate, false)) { - const MapNodeData &nodeData = neighbor.pNode->getMapNodeDataForLayer(currentLayer); - - if (nodeData.tileData && ((nodeData.tileID == nodeTileId) || (pCurrentTileData->tileType == +TileType::ROAD))) + const auto tileData = neighbor.pNode->getTileData(currentLayer); + if (tileData && + ((neighbor.pNode->getTileID(currentLayer) == nodeTileId) || (pCurrentTileData->tileType == +TileType::ROAD))) { tileOrientationBitmask[currentLayer] |= neighbor.position; } @@ -311,6 +316,7 @@ bool MapFunctions::setTileID(const std::string &tileID, Point coordinate) { TileData *tileData = TileManager::instance().getTileData(tileID); std::vector targetCoordinates = TileManager::instance().getTargetCoordsOfTileID(coordinate, tileID); + LOG(LOG_FATAL) << "I GET CALLED!! " << targetCoordinates.size(); if (!tileData || targetCoordinates.empty()) { // if the node would not outside of map boundaries, targetCoordinates would be empty @@ -318,7 +324,12 @@ bool MapFunctions::setTileID(const std::string &tileID, Point coordinate) } if (!isPlacementOnAreaAllowed(targetCoordinates, tileID)) + { + LOG(LOG_DEBUG) << "playment NOT allowed in setTileID"; return false; + } + else + LOG(LOG_DEBUG) << "placement IS allowed in setTileID"; Layer layer = TileManager::instance().getTileLayer(tileID); std::string randomGroundDecorationTileID; @@ -338,11 +349,24 @@ bool MapFunctions::setTileID(const std::string &tileID, Point coordinate) demolishNode(targetCoordinates, false, Layer::POWERLINES); // remove power lines under buildings } + MapNode ¤tNode = getMapNode(coordinate); + currentNode.setTileID(tileID, coordinate); + // emit a signal that setTileID has been called + SignalMediator::instance().signalSetTileID.emit(currentNode); + LOG(LOG_INFO) << "i return true!"; + return true; + // for (auto coord : targetCoordinates) + // { + + // MapNode ¤tMapNode = mapNodes[nodeIdx(coord.x, coord.y)]; + // nodesToBeUpdated.push_back(¤tMapNode); + // } for (auto coord : targetCoordinates) { // now we can place our building - MapNode ¤tMapNode = getMapNode(coord); + break; // don't doanything + if (coord != coordinate && targetCoordinates.size() > 1) { // for buildings >1x1 set every node on the layer that will be occupied to invisible exepct of the origin node currentMapNode.getSprite()->setRenderFlag(layer, false); @@ -372,16 +396,12 @@ bool MapFunctions::setTileID(const std::string &tileID, Point coordinate) { nodesToBeUpdated.push_back(currentMapNode.getCoordinates()); } - - // emit a signal that setTileID has been called - SignalMediator::instance().signalSetTileID.emit(currentMapNode); } if (!nodesToBeUpdated.empty()) { updateNodeNeighbors(nodesToBeUpdated); } - return true; } bool MapFunctions::setTileID(const std::string &tileID, const std::vector &coordinates) @@ -447,21 +467,18 @@ void MapFunctions::demolishNode(const std::vector &isoCoordinates, bool u } } -void MapFunctions::getNodeInformation(const Point &isoCoordinates) const +void MapFunctions::getNodeInformation(const Point &isoCoordinates) { - const MapNode &mapNode = m_map->mapNodes[isoCoordinates.toIndex()]; - const MapNodeData &mapNodeData = mapNode.getActiveMapNodeData(); - const TileData *tileData = mapNodeData.tileData; + const MapNode &mapNode = getMapNode(isoCoordinates); + const TileData *tileData = mapNode.getTileData(mapNode.getTopMostActiveLayer()); LOG(LOG_INFO) << "===== TILE at " << isoCoordinates.x << ", " << isoCoordinates.y << ", " << mapNode.getCoordinates().height << "====="; - LOG(LOG_INFO) << "[Layer: TERRAIN] ID: " << mapNode.getMapNodeDataForLayer(Layer::TERRAIN).tileID; - LOG(LOG_INFO) << "[Layer: WATER] ID: " << mapNode.getMapNodeDataForLayer(Layer::WATER).tileID; - LOG(LOG_INFO) << "[Layer: BUILDINGS] ID: " << mapNode.getMapNodeDataForLayer(Layer::BUILDINGS).tileID; + LOG(LOG_INFO) << "[Layer: TERRAIN] ID: " << mapNode.getTileID(Layer::BUILDINGS); + LOG(LOG_INFO) << "[Layer: WATER] ID: " << mapNode.getTileID(Layer::BUILDINGS); + LOG(LOG_INFO) << "[Layer: BUILDINGS] ID: " << mapNode.getTileID(Layer::BUILDINGS); LOG(LOG_INFO) << "Category: " << tileData->category; LOG(LOG_INFO) << "FileName: " << tileData->tiles.fileName; LOG(LOG_INFO) << "PickRandomTile: " << tileData->tiles.pickRandomTile; - LOG(LOG_INFO) << "TileMap: " << mapNodeData.tileMap; - LOG(LOG_INFO) << "TileIndex: " << mapNodeData.tileIndex; } void MapFunctions::highlightNode(const Point &isoCoordinates, const SpriteRGBColor &rgbColor) @@ -525,7 +542,7 @@ Point MapFunctions::findNodeInMap(const SDL_Point &screenCoordinates, const Laye for (int y = std::max(yMiddlePoint - neighborReach, 0); (y <= yMiddlePoint + neighborReach) && (y < mapSize); ++y) { //get all coordinates for node at x,y - Point coordinate = getMapNode(Point(x, y)).getCoordinates(); + const Point coordinate = getMapNode(Point(x, y)).getCoordinates(); if (isClickWithinTile(screenCoordinates, coordinate, layer)) { @@ -537,15 +554,14 @@ Point MapFunctions::findNodeInMap(const SDL_Point &screenCoordinates, const Laye return Point{-1, -1, 0, 0}; } -bool MapFunctions::isClickWithinTile(const SDL_Point &screenCoordinates, Point isoCoordinate, - const Layer &layer = Layer::NONE) const +bool MapFunctions::isClickWithinTile(const SDL_Point &screenCoordinates, Point isoCoordinate, const Layer &layer = Layer::NONE) { if (!isoCoordinate.isWithinMapBoundaries()) { return false; } - const auto &node = m_map->mapNodes[isoCoordinate.toIndex()]; + const auto &node = getOriginMapNode(isoCoordinate); auto pSprite = node.getSprite(); std::vector layersToGoOver; @@ -699,4 +715,4 @@ void MapFunctions::refreshVisibleMap() { m_map->refresh(); } -} +} \ No newline at end of file diff --git a/src/engine/map/MapFunctions.hxx b/src/engine/map/MapFunctions.hxx index 838fa4393c..e1ab344369 100644 --- a/src/engine/map/MapFunctions.hxx +++ b/src/engine/map/MapFunctions.hxx @@ -27,7 +27,12 @@ public: */ bool updateHeight(Point coordinate, const bool elevate); - /** \brief Get pointer to a single mapNode at specific iso coordinates. + /** \brief Get reference to a single mapNode at specific iso coordinates. + * @param isoCoords The node to retrieve the originNode. + */ + MapNode &getOriginMapNode(Point isoCoords) { return m_map->mapNodes[isoCoords.toIndex()]; }; + + /** \brief Get reference to a single mapNode at specific iso coordinates. * @param isoCoords The node to retrieve. */ MapNode &getMapNode(Point isoCoords) { return m_map->mapNodes[isoCoords.toIndex()]; }; @@ -53,13 +58,13 @@ public: * @param isoCoordinates Tile to inspect * @param tileID tileID which should be checked */ - bool isPlacementOnNodeAllowed(const Point &isoCoordinates, const std::string &tileID) const; + bool isPlacementOnNodeAllowed(const Point &isoCoordinates, const std::string &tileID); /** \brief check if Tile can be placed in an area * @param targetCoordinates Tile array to inspect * @param tileID tileID which should be checked */ - bool isPlacementOnAreaAllowed(const std::vector &targetCoordinates, const std::string &tileID) const; + bool isPlacementOnAreaAllowed(const std::vector &targetCoordinates, const std::string &tileID); /** * @brief Set the Tile ID Of Node object @@ -102,7 +107,7 @@ public: * Used as Tile-Inspector until we implement a GUI variant * @param isoCoordinates Tile to inspect */ - void getNodeInformation(const Point &isoCoordinates) const; + void getNodeInformation(const Point &isoCoordinates); /** * @brief Sets a node to be highlit @@ -174,7 +179,7 @@ private: * @param layer layer to check * @return if a click is within this node */ - bool isClickWithinTile(const SDL_Point &screenCoordinates, Point isoCoordinate, const Layer &layer) const; + bool isClickWithinTile(const SDL_Point &screenCoordinates, Point isoCoordinate, const Layer &layer); /** \brief Save Map to file * @details Serializes the Map class to json and writes the data to a file. diff --git a/src/engine/map/TerrainGenerator.cxx b/src/engine/map/TerrainGenerator.cxx index 65c838eef2..16b473ae8d 100644 --- a/src/engine/map/TerrainGenerator.cxx +++ b/src/engine/map/TerrainGenerator.cxx @@ -100,7 +100,7 @@ void TerrainGenerator::generateTerrain(std::vector &mapNodes, std::vect if (height < m_terrainSettings.seaLevel) { height = m_terrainSettings.seaLevel; - mapNodes.emplace_back(MapNode{Point{x, y, z, height}, m_biomeInformation[currentBiome].water[0]}); + mapNodes.emplace_back(Point{x, y, z, height}, m_biomeInformation[currentBiome].water[0]); } else { @@ -116,8 +116,8 @@ void TerrainGenerator::generateTerrain(std::vector &mapNodes, std::vect if (tileIndex < 20) { tileIndex = tileIndex % static_cast(m_biomeInformation[currentBiome].treesLight.size()); - mapNodes.emplace_back(MapNode{Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0], - m_biomeInformation[currentBiome].treesLight[tileIndex]}); + mapNodes.emplace_back(Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0], + m_biomeInformation[currentBiome].treesLight[tileIndex]); placed = true; } } @@ -126,8 +126,8 @@ void TerrainGenerator::generateTerrain(std::vector &mapNodes, std::vect if (tileIndex < 50) { tileIndex = tileIndex % static_cast(m_biomeInformation[currentBiome].treesMedium.size()); - mapNodes.emplace_back(MapNode{Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0], - m_biomeInformation[currentBiome].treesMedium[tileIndex]}); + mapNodes.emplace_back(Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0], + m_biomeInformation[currentBiome].treesMedium[tileIndex]); placed = true; } } @@ -135,14 +135,14 @@ void TerrainGenerator::generateTerrain(std::vector &mapNodes, std::vect { tileIndex = tileIndex % static_cast(m_biomeInformation[currentBiome].treesDense.size()); - mapNodes.emplace_back(MapNode{Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0], - m_biomeInformation[currentBiome].treesDense[tileIndex]}); + mapNodes.emplace_back(Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0], + m_biomeInformation[currentBiome].treesDense[tileIndex]); placed = true; } } if (placed == false) { - mapNodes.emplace_back(MapNode{Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0]}); + mapNodes.emplace_back(Point{x, y, z, height}, m_biomeInformation[currentBiome].terrain[0]); } } } diff --git a/src/engine/ui/basics/Layout.hxx b/src/engine/ui/basics/Layout.hxx index 61c0229aa3..136d226cfa 100644 --- a/src/engine/ui/basics/Layout.hxx +++ b/src/engine/ui/basics/Layout.hxx @@ -16,7 +16,7 @@ struct LayoutData int groupHeight = 0; ///< height of all elements in group int groupWidth = 0; ///< Width of all elements in group uint32_t fontSize = 20; ///< default font size of all elements in group - struct ImFont *font = nullptr; ///< font pointer for elements + struct ImFont *font = nullptr; ///< font pointer for elements }; /** diff --git a/src/engine/ui/widgets/Combobox.cxx b/src/engine/ui/widgets/Combobox.cxx index aaff4860fa..d08aa91c81 100644 --- a/src/engine/ui/widgets/Combobox.cxx +++ b/src/engine/ui/widgets/Combobox.cxx @@ -166,10 +166,7 @@ void ComboBox::setActiveID(int ID) clickSignalSender.emit(this); } -void ComboBox::clear() -{ - m_items.clear(); -} +void ComboBox::clear() { m_items.clear(); } std::string ComboBox::getTextFromID(int id) const { diff --git a/src/game/PowerGrid.cxx b/src/game/PowerGrid.cxx index b27b96172b..85b031ab75 100644 --- a/src/game/PowerGrid.cxx +++ b/src/game/PowerGrid.cxx @@ -13,17 +13,23 @@ void PowerGrid::updatePowerLevel() { // reset the power level of this grid before recalculating m_powerLevel = 0; + // LOG(LOG_INFO) << "calling updatePowerLevel" << m_gridNodes.size(); for (const auto &node : m_gridNodes) { - if (MapFunctions::instance().getMapNode(node.coordinate).getTileData(Layer::BUILDINGS) && node.powerProduction == 0) + MapNode &mapNode = MapFunctions::instance().getMapNode(node.coordinate); + if (!mapNode.isOriginNode()) + { // For multi-tile buildings, each tile has the same tiledata (including power level). + // so make sure we only add it once (if it's the origin node) + continue; + } + if (mapNode.getTileData(Layer::BUILDINGS) && node.powerProduction == 0) { // each occupied node consumes one power unit + // LOG(LOG_ERROR) << "i make --"; m_powerLevel--; } - - // For multi-tile buildings, each tile has the same tiledata (including power level). - // so make sure we only add it once (if it's the origin node) - if (MapFunctions::instance().getMapNode(node.coordinate).isOriginNode()) + else { + LOG(LOG_ERROR) << "i add " << node.powerProduction; m_powerLevel += node.powerProduction; } } diff --git a/src/game/PowerManager.cxx b/src/game/PowerManager.cxx index 66ea7f08de..6aa2927426 100644 --- a/src/game/PowerManager.cxx +++ b/src/game/PowerManager.cxx @@ -35,12 +35,21 @@ void PowerManager::update() if (!m_nodesToAdd.empty()) { - for (auto nodeToAdd : m_nodesToAdd) + for (auto &nodeToAdd : m_nodesToAdd) { + // LOG(LOG_INFO) << "ADDING node " << nodeToAdd.powerProduction; addPowerNodeToGrid(nodeToAdd, m_powerGrids); + for (auto &grid : m_powerGrids) + { + // LOG(LOG_DEBUG) << "Grid first: " << grid.getPowerLevel(); + } } m_nodesToAdd.clear(); - + // for (auto &grid : m_powerGrids) + // { + // LOG(LOG_DEBUG) << "Grid: " << grid.getPowerLevel(); + // } + // LOG(LOG_INFO) << "We have " << m_powerGrids.size() << " grids"; updated = true; } @@ -74,7 +83,9 @@ void PowerManager::addPowerNodeToGrid(PowerNode &powerNode, std::vector