diff --git a/imgui.ini b/imgui.ini index cbd1e66..9fec006 100644 --- a/imgui.ini +++ b/imgui.ini @@ -27,7 +27,7 @@ DockId=0x00000001,0 [Window][Viewport] Pos=265,19 -Size=501,412 +Size=501,590 Collapsed=0 DockId=0x00000007,0 @@ -42,14 +42,14 @@ Collapsed=0 DockId=0x00000006,0 [Window][Console] -Pos=265,433 -Size=501,287 +Pos=265,611 +Size=501,109 Collapsed=0 DockId=0x00000008,0 [Window][Tilemap Editor] Pos=265,19 -Size=1141,869 +Size=1141,1047 Collapsed=0 DockId=0x00000007,1 @@ -58,8 +58,8 @@ DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X DockNode ID=0x00000003 Parent=0x11111111 SizeRef=1406,1158 Split=X DockNode ID=0x00000001 Parent=0x00000003 SizeRef=263,701 HiddenTabBar=1 Selected=0x12EF0F59 DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1141,701 Split=Y Selected=0xC450F867 - DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,869 CentralNode=1 Selected=0xC450F867 - DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,287 HiddenTabBar=1 Selected=0xEA83D666 + DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,1047 CentralNode=1 Selected=0xC450F867 + DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,109 Selected=0xEA83D666 DockNode ID=0x00000004 Parent=0x11111111 SizeRef=512,1158 Split=Y Selected=0x36DC96AB DockNode ID=0x00000005 Parent=0x00000004 SizeRef=407,835 HiddenTabBar=1 Selected=0x36DC96AB DockNode ID=0x00000006 Parent=0x00000004 SizeRef=407,321 HiddenTabBar=1 Selected=0x3FC1A724 diff --git a/remake/build.log b/remake/build.log index 0a649dd..e887e7e 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,2 +1,3 @@ +[COMPILE] g++ -std=c++20 -Wall -Isrc/include -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -Isrc/include -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Components\TilemapComponent.cpp -o src\build\src\Components\TilemapComponent.o [LINK] g++ src\build\src\Engine.o src\build\src\main.o src\build\src\Renderer.o src\build\src\Components\CameraComponent.o src\build\src\Components\LightComponent.o src\build\src\Components\SpriteComponent.o src\build\src\Components\TilemapComponent.o src\build\src\Entitys\Object.o src\build\src\utils\EngineConfig.o src\build\src\utils\FileDialog.o src\build\src\utils\Logging.o src\build\src\utils\Shader.o src\build\src\utils\utils.o src\build\vendor\imgui\imgui.o src\build\vendor\imgui\imgui_demo.o src\build\vendor\imgui\imgui_draw.o src\build\vendor\imgui\imgui_impl_glfw.o src\build\vendor\imgui\imgui_impl_opengl3.o src\build\vendor\imgui\imgui_tables.o src\build\vendor\imgui\imgui_widgets.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -[ERROR] Interrupted by user. +[RUN] Executed app.exe successfully. diff --git a/src/src/Components/TilemapComponent.cpp b/src/src/Components/TilemapComponent.cpp index ccd3de7..1153caf 100644 --- a/src/src/Components/TilemapComponent.cpp +++ b/src/src/Components/TilemapComponent.cpp @@ -74,6 +74,28 @@ void TilemapComponent::UpdateAtlasDimensions() } } + +bool TilemapComponent::IsTileFullyTransparent(int col, int row, int texW, int texH, unsigned char* imageData) +{ + int x0 = col * m_AtlasTileWidth; + int y0 = row * m_AtlasTileHeight; + + for (int y = 0; y < m_AtlasTileHeight; ++y) + { + for (int x = 0; x < m_AtlasTileWidth; ++x) + { + int px = x0 + x; + int py = y0 + y; + int idx = (py * texW + px) * 4; + if (imageData[idx + 3] > 0) + return false; + } + } + return true; +} + + + // Serialization: store grid size, tile size, tile data, and atlas settings. void TilemapComponent::Save(YAML::Emitter &out) const { @@ -119,140 +141,122 @@ void TilemapComponent::Load(const YAML::Node &node) UpdateAtlasDimensions(); } -// ----------------------------- -// Editor UI -// ----------------------------- void TilemapComponent::DrawEditorUI() { ImGui::Begin("Tilemap Editor"); - // --- Atlas Settings --- - if (ImGui::CollapsingHeader("Tileset Atlas Settings")) + if (ImGui::BeginTabBar("TilemapEditorTabs")) { - // Display current atlas path - ImGui::Text("Current Atlas: %s", m_AtlasPath.empty() ? "None" : m_AtlasPath.c_str()); - if (ImGui::Button("Import Atlas")) + // --- Atlas Settings --- + if (ImGui::BeginTabItem("Atlas Settings")) { - std::string path = OpenFileDialog(FileDialogType::Images); - if (!path.empty()) + ImGui::Text("Current Atlas: %s", m_AtlasPath.empty() ? "None" : m_AtlasPath.c_str()); + if (ImGui::Button("Import Atlas")) { - // For simplicity, default atlas tile dimensions are set via input later. - m_AtlasPath = path; + std::string path = OpenFileDialog(FileDialogType::Images); + if (!path.empty()) + { + m_AtlasPath = path; + UpdateAtlasDimensions(); + } + } + + int atlasW = m_AtlasTileWidth, atlasH = m_AtlasTileHeight; + if (ImGui::InputInt("Atlas Tile Width", &atlasW)) + { + m_AtlasTileWidth = atlasW; UpdateAtlasDimensions(); } - } - // Configure atlas tile size - int atlasW = m_AtlasTileWidth, atlasH = m_AtlasTileHeight; - if (ImGui::InputInt("Atlas Tile Width", &atlasW)) - { - m_AtlasTileWidth = atlasW; - UpdateAtlasDimensions(); - } - if (ImGui::InputInt("Atlas Tile Height", &atlasH)) - { - m_AtlasTileHeight = atlasH; - UpdateAtlasDimensions(); - } - ImGui::Text("Atlas Grid: %d columns x %d rows", m_AtlasCols, m_AtlasRows); - } - - // --- Map Grid Settings --- - if (ImGui::CollapsingHeader("Map Settings")) - { - glm::ivec2 grid = m_GridSize; - int gridW = grid.x, gridH = grid.y; - if (ImGui::InputInt("Map Grid Width", &gridW) || ImGui::InputInt("Map Grid Height", &gridH)) - { - SetGridSize(glm::ivec2(gridW, gridH)); - } - glm::ivec2 ts = m_TileSize; - int tileW = ts.x, tileH = ts.y; - if (ImGui::InputInt("Tile Width", &tileW) || ImGui::InputInt("Tile Height", &tileH)) - { - SetTileSize(glm::ivec2(tileW, tileH)); - } - } - - // --- Tileset Palette Editor --- - if (ImGui::CollapsingHeader("Tileset Palette")) - { - if (m_AtlasPath.empty()) - { - ImGui::Text("No atlas loaded."); - } - else - { - // Retrieve texture dimensions via stbi_info (for preview UV calculation) - int texW, texH, comp; - if (stbi_info(m_AtlasPath.c_str(), &texW, &texH, &comp)) + if (ImGui::InputInt("Atlas Tile Height", &atlasH)) { - float uvTileW = float(m_AtlasTileWidth) / float(texW); - float uvTileH = float(m_AtlasTileHeight) / float(texH); - // Display each tile as an image button - ImGui::Text("Select a tile:"); - for (int row = 0; row < m_AtlasRows; row++) - { - for (int col = 0; col < m_AtlasCols; col++) - { - int tileIndex = row * m_AtlasCols + col; - // UV coordinates for this tile - float uvX = float(col) * uvTileW; - float uvY = float(row) * uvTileH; - ImVec2 uv0(uvX, uvY); - ImVec2 uv1(uvX + uvTileW, uvY + uvTileH); + m_AtlasTileHeight = atlasH; + UpdateAtlasDimensions(); + } - char buf[32]; - sprintf(buf, "##tile_%d", tileIndex); - // Display a button. Here, 32x32 pixels is used for preview size. - GLuint textureID = LoadTextureIfNeeded(m_AtlasPath); - if (ImGui::ImageButton(buf, (ImTextureID)(uintptr_t)textureID, ImVec2(32, 32), uv0, uv1)) - { - g_selectedTileIndex = tileIndex; - } + ImGui::Text("Atlas Grid: %d x %d", m_AtlasCols, m_AtlasRows); + ImGui::EndTabItem(); + } - ImGui::SameLine(); - } - ImGui::NewLine(); - } - ImGui::Text("Selected Tile: %d", g_selectedTileIndex); + // --- Map Settings --- + if (ImGui::BeginTabItem("Map Settings")) + { + ImGui::Text("Map Size: %d x %d", m_GridSize.x, m_GridSize.y); + ImGui::Text("Tile Size: %d x %d", m_TileSize.x, m_TileSize.y); + ImGui::Text("Tile Count: %zu", m_Tiles.size()); + + + ImGui::EndTabItem(); + } + + // --- Tile Tools --- + if (ImGui::BeginTabItem("Tiles")) + { + + ImGui::Separator(); + + if (m_AtlasPath.empty()) + { + ImGui::Text("No atlas loaded."); } else { - ImGui::Text("Failed to load atlas info."); - } - } - } - - // --- Map Editor --- - if (ImGui::CollapsingHeader("Map Editor")) - { - if (m_GridSize.x == 0 || m_GridSize.y == 0) - { - ImGui::Text("No map created."); - } - else - { - ImGui::Text("Click a cell to paint with the selected tile."); - ImGui::BeginChild("TilemapGrid", ImVec2(0, 300), true); - for (int y = 0; y < m_GridSize.y; y++) - { - for (int x = 0; x < m_GridSize.x; x++) + int texW, texH, comp; + unsigned char* imageData = stbi_load(m_AtlasPath.c_str(), &texW, &texH, &comp, 4); + if (imageData) { - int tile = GetTile(x, y); - char label[32]; - sprintf(label, "%d##%d_%d", tile, x, y); - if (ImGui::Button(label, ImVec2(30, 30))) + float uvTileW = float(m_AtlasTileWidth) / float(texW); + float uvTileH = float(m_AtlasTileHeight) / float(texH); + GLuint textureID = LoadTextureIfNeeded(m_AtlasPath); + + const float tileDisplaySize = 48; + ImGui::BeginChild("TilesetView"); + for (int row = 0; row < m_AtlasRows; ++row) { - SetTile(x, y, g_selectedTileIndex); + for (int col = 0; col < m_AtlasCols; ++col) + { + int tileIndex = row * m_AtlasCols + col; + float uvX = float(col) * uvTileW; + float uvY = float(row) * uvTileH; + ImVec2 uv0(uvX, uvY); + ImVec2 uv1(uvX + uvTileW, uvY + uvTileH); + + char id[32]; + sprintf(id, "##tile_%d", tileIndex); + + bool isEmpty = IsTileFullyTransparent(col, row, texW, texH, imageData); + ImVec4 tint = isEmpty ? ImVec4(0.3f, 0.3f, 0.3f, 0.5f) : ImVec4(1, 1, 1, 1); + if (ImGui::ImageButton(id, (ImTextureID)(uintptr_t)textureID, ImVec2(tileDisplaySize, tileDisplaySize), uv0, uv1)) + { + g_selectedTileIndex = tileIndex; + } + + if (ImGui::IsItemHovered()) + ImGui::SetTooltip("Tile %d", tileIndex); + + ImGui::SameLine(); + } + ImGui::NewLine(); } - ImGui::SameLine(); + stbi_image_free(imageData); + ImGui::EndChild(); } - ImGui::NewLine(); + else + { + ImGui::Text("Failed to load image."); + } + + ImGui::Text("Selected Tile: %d", g_selectedTileIndex); } - ImGui::EndChild(); + + ImGui::EndTabItem(); } + + ImGui::EndTabBar(); } ImGui::End(); } + + + diff --git a/src/src/Components/TilemapComponent.h b/src/src/Components/TilemapComponent.h index 0e116d1..cdce557 100644 --- a/src/src/Components/TilemapComponent.h +++ b/src/src/Components/TilemapComponent.h @@ -53,4 +53,6 @@ private: int m_AtlasRows = 0; void UpdateAtlasDimensions(); + bool IsTileFullyTransparent(int col, int row, int texW, int texH, unsigned char* imageData); + }; diff --git a/src/src/Entitys/Object.cpp b/src/src/Entitys/Object.cpp index 971daa3..c995849 100644 --- a/src/src/Entitys/Object.cpp +++ b/src/src/Entitys/Object.cpp @@ -4,6 +4,8 @@ #include "../Components/SpriteComponent.h" #include "../Components/CameraComponent.h" #include "../Components/LightComponent.h" +#include "../Components/TilemapComponent.h" + #include @@ -90,6 +92,9 @@ void Object::Load(const YAML::Node& node) { } else if (type == "LightComponent") { auto comp = AddComponent(); comp->Load(compNode); + } else if (type == "TilemapComponent") { + auto comp = AddComponent(); + comp->Load(compNode); } } } diff --git a/src/src/utils/utils.cpp b/src/src/utils/utils.cpp index 3c76caa..9f73240 100644 --- a/src/src/utils/utils.cpp +++ b/src/src/utils/utils.cpp @@ -37,3 +37,5 @@ std::string GetFilenameFromPath(const std::string& path) return filename; } + +