From 76d9373223b10346f0fe5b13b70f586a73fbaa6d Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Thu, 24 Apr 2025 18:53:18 -0500 Subject: [PATCH] You can place stuff now ish --- imgui.ini | 20 ++-- remake/build.log | 3 +- src/src/Components/AnimationComponent.cpp | 4 +- src/src/Components/TilemapComponent.cpp | 36 ++++++ src/src/Components/TilemapComponent.h | 54 +++++++-- src/src/Engine.cpp | 127 ++++++++++++++++++++-- src/src/core/utils/TextureAtlas.h | 3 +- src/src/editor/windows/Inspector.cpp | 32 +++++- 8 files changed, 240 insertions(+), 39 deletions(-) diff --git a/imgui.ini b/imgui.ini index 109ae1e..f2138cf 100644 --- a/imgui.ini +++ b/imgui.ini @@ -14,8 +14,8 @@ Size=1280,701 Collapsed=0 [Window][Inspector] -Pos=790,19 -Size=490,701 +Pos=772,19 +Size=508,701 Collapsed=0 DockId=0x00000006,0 @@ -27,7 +27,7 @@ DockId=0x00000003,0 [Window][Viewport] Pos=344,19 -Size=444,390 +Size=426,390 Collapsed=0 DockId=0x00000007,0 @@ -37,13 +37,13 @@ Collapsed=0 [Window][Performance Info] Pos=344,411 -Size=444,309 +Size=426,309 Collapsed=0 DockId=0x00000008,3 [Window][Console] Pos=344,411 -Size=444,309 +Size=426,309 Collapsed=0 DockId=0x00000008,0 @@ -55,7 +55,7 @@ DockId=0x00000007,1 [Window][Profiler] Pos=344,411 -Size=444,309 +Size=426,309 Collapsed=0 DockId=0x00000008,2 @@ -79,7 +79,7 @@ DockId=0x00000008,1 [Window][Color Correction] Pos=344,411 -Size=444,309 +Size=426,309 Collapsed=0 DockId=0x00000008,1 @@ -96,12 +96,12 @@ Collapsed=0 [Docking][Data] DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X - DockNode ID=0x00000005 Parent=0x11111111 SizeRef=788,1158 Split=X + DockNode ID=0x00000005 Parent=0x11111111 SizeRef=1410,1158 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,575 HiddenTabBar=1 Selected=0x12EF0F59 DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,581 HiddenTabBar=1 Selected=0x36AF052B - DockNode ID=0x00000002 Parent=0x00000005 SizeRef=444,701 Split=Y Selected=0xC450F867 + DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1066,701 Split=Y Selected=0xC450F867 DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,847 CentralNode=1 HiddenTabBar=1 Selected=0xC450F867 DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,309 Selected=0x9B5D3198 - DockNode ID=0x00000006 Parent=0x11111111 SizeRef=490,1158 HiddenTabBar=1 Selected=0x36DC96AB + DockNode ID=0x00000006 Parent=0x11111111 SizeRef=508,1158 HiddenTabBar=1 Selected=0x36DC96AB diff --git a/remake/build.log b/remake/build.log index 18b9b59..081a50b 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,3 +1,4 @@ -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Components\AnimationComponent.cpp -o src\build\Components\AnimationComponent.o +[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -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\Components\TilemapComponent.o [COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -Isrc/vendor/xxhash -IC:/msys64/mingw64/include -IC:\msys64\mingw64\lib\libyaml-cpp.a -Isrc\vendor\imgui -MMD -MP -c src\src\Engine.cpp -o src\build\Engine.o [LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\utils\AssetManager.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o src\build\xxhash.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto +[RUN] Executed app.exe successfully. diff --git a/src/src/Components/AnimationComponent.cpp b/src/src/Components/AnimationComponent.cpp index d826071..1a53e02 100644 --- a/src/src/Components/AnimationComponent.cpp +++ b/src/src/Components/AnimationComponent.cpp @@ -107,7 +107,7 @@ void AnimationComponent::Update(float dt) time += dt * speed; if (time >= frameDuration) { - time -= frameDuration; + time = 0; currentFrame++; if (currentFrame > endFrame) @@ -116,7 +116,7 @@ void AnimationComponent::Update(float dt) currentFrame = startFrame; else { - currentFrame = startFrame; + currentFrame = endFrame; playing = false; } } diff --git a/src/src/Components/TilemapComponent.cpp b/src/src/Components/TilemapComponent.cpp index dc337b1..078f68d 100644 --- a/src/src/Components/TilemapComponent.cpp +++ b/src/src/Components/TilemapComponent.cpp @@ -6,6 +6,7 @@ TilemapComponent::TilemapComponent(Object* owner) : Component(owner) { renderType = RenderType::Unlit; + hasSelection = false; } uint64_t TilemapComponent::PackCoord(int x, int y) @@ -20,6 +21,14 @@ void TilemapComponent::UnpackCoord(uint64_t key, int& x, int& y) y = static_cast(key & 0xFFFFFFFF); } + +bool TilemapComponent::HasSelection() +{ + return hasSelection; + +} + + void TilemapComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texelHeight) { textureUAID = uaid; @@ -61,6 +70,33 @@ int TilemapComponent::GetTile(int x, int y) const +void TilemapComponent::PlaceSelection(int gx, int gy) +{ + if (!hasSelection) return; + + int x0 = std::min(selStartX, selEndX); + int y0 = std::min(selStartY, selEndY); + int x1 = std::max(selStartX, selEndX); + int y1 = std::max(selStartY, selEndY); + + int width = x1 - x0 + 1; + int height = y1 - y0 + 1; + + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + int srcX = x0 + x; + int srcY = y0 + y; + int index = srcY * GetAtlasColumns() + srcX; + + SetTile(gx + x, gy + y, index); + } + } +} + + + // Accessors uint64_t TilemapComponent::GetTextureUAID() const { return textureUAID; } std::shared_ptr TilemapComponent::GetTexture() const { return texture; } diff --git a/src/src/Components/TilemapComponent.h b/src/src/Components/TilemapComponent.h index 984d107..0a57f4f 100644 --- a/src/src/Components/TilemapComponent.h +++ b/src/src/Components/TilemapComponent.h @@ -8,30 +8,64 @@ class TilemapComponent : public Component { public: - TilemapComponent(Object* owner); + TilemapComponent(Object *owner); void SetTextureAtlas(uint64_t uaid, int texelWidth, int texelHeight); void SetTile(int x, int y, int index); - int GetTile(int x, int y) const; - + int GetTile(int x, int y) const; // Overrides std::string GetName() const override { return "TilemapComponent"; } - void Save(YAML::Emitter& out) const override; - void Load(const YAML::Node& node) override; + void Save(YAML::Emitter &out) const override; + void Load(const YAML::Node &node) override; // Accessors uint64_t GetTextureUAID() const; std::shared_ptr GetTexture() const; - const TextureAtlas& GetAtlas() const; - const core::types::Vec2& GetTileSize() const; - void SetTileSize(const core::types::Vec2& size); + const TextureAtlas &GetAtlas() const; + const core::types::Vec2 &GetTileSize() const; + void SetTileSize(const core::types::Vec2 &size); int GetAtlasColumns() const; int GetAtlasRows() const; - const std::unordered_map& GetTileData() const; + const std::unordered_map &GetTileData() const; + + void PlaceSelection(int gx, int gy); + + bool HasSelection(); static uint64_t PackCoord(int x, int y); - static void UnpackCoord(uint64_t key, int& x, int& y); + static void UnpackCoord(uint64_t key, int &x, int &y); + + bool hasSelection; + + int selStartX = 0, selStartY = 0; + int selEndX = 0, selEndY = 0; + + void SetSelection(int startX, int startY, int endX, int endY) + { + hasSelection = true; + selStartX = startX; + selStartY = startY; + selEndX = endX; + selEndY = endY; + } + + void ClearSelection() { hasSelection = false; } + bool HasSelection() const { return hasSelection; } + + void GetSelectionBounds(int &outX0, int &outY0, int &outX1, int &outY1) const + { + if (!hasSelection) + { + outX0 = outY0 = outX1 = outY1 = 0; + return; + } + + outX0 = std::min(selStartX, selEndX); + outY0 = std::min(selStartY, selEndY); + outX1 = std::max(selStartX, selEndX); + outY1 = std::max(selStartY, selEndY); + } private: uint64_t textureUAID = 0; diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp index d248b5c..55bc775 100644 --- a/src/src/Engine.cpp +++ b/src/src/Engine.cpp @@ -739,14 +739,13 @@ void Engine::Run() PROFILE_ENGINE_SCOPE("Engine::DrawSceneTree"); ImGui::Begin("Scene Tree"); - + if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImGui::IsKeyPressed(ImGuiKey_Delete) && selected) { ImGui::OpenPopup("Confirm Deletion"); } - if (ImGui::BeginPopupModal("Confirm Deletion", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Text("Are you sure you want to delete this object?"); @@ -1001,12 +1000,126 @@ void Engine::Run() GLuint texID = Renderer::GetFinalTexture(); ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0)); - // Get window position and size to detect where mouse is ImVec2 winPos = ImGui::GetWindowPos(); ImVec2 winSize = ImGui::GetWindowSize(); ImVec2 mousePos = ImGui::GetMousePos(); + core::types::Vec2 viewportSize(winSize.x, winSize.y); + core::types::Vec2 screenMousePos(mousePos.x - winPos.x, mousePos.y - winPos.y); + + if (selected) + { + auto tilemap = selected->GetComponent(); + if (tilemap && tilemap->HasSelection()) + { + const auto tileSize = tilemap->GetTileSize(); + const uint64_t uaid = tilemap->GetTextureUAID(); + const auto *asset = AssetManager::GetAssetByID(uaid); + + if (asset && asset->loaded) + { + auto *drawList = ImGui::GetWindowDrawList(); + const auto texSize = asset->size; + int maxCols = static_cast(texSize.x / tileSize.x); + int maxRows = static_cast(texSize.y / tileSize.y); + + core::types::Vec2 screenMouse(mousePos.x - winPos.x, mousePos.y - winPos.y); + core::types::Vec2 worldMouse = ScreenToWorld(screenMouse, {winSize.x, winSize.y}, cameraPos, cameraZoom); + + int centerCol = static_cast(worldMouse.x / tileSize.x); + int centerRow = static_cast(worldMouse.y / tileSize.y); + + int radius = 15; + int minCol = centerCol - radius; + int maxCol = centerCol + radius; + int minRow = centerRow - radius; + int maxRow = centerRow + radius; + + core::types::Vec2 screenCenter = {winPos.x + winSize.x * 0.5f, winPos.y + winSize.y * 0.5f}; + float maxDist = static_cast(radius) * tileSize.x * cameraZoom; + + for (int y = minRow; y <= maxRow; ++y) + { + for (int x = minCol; x <= maxCol; ++x) + { + float gx = x * tileSize.x; + float gy = y * tileSize.y; + + float sx = (gx - cameraPos.x) * cameraZoom + screenCenter.x; + float sy = (gy - cameraPos.y) * cameraZoom + screenCenter.y; + float sx2 = (gx + tileSize.x - cameraPos.x) * cameraZoom + screenCenter.x; + float sy2 = (gy + tileSize.y - cameraPos.y) * cameraZoom + screenCenter.y; + + float centerGX = gx + tileSize.x * 0.5f; + float centerGY = gy + tileSize.y * 0.5f; + float dx = (centerGX - worldMouse.x); + float dy = (centerGY - worldMouse.y); + float dist = std::sqrt(dx * dx + dy * dy) * cameraZoom; + float fade = std::clamp(1.0f - dist / maxDist, 0.0f, 0.9f); + int alpha = static_cast(fade * 255.0f); + + ImU32 color = IM_COL32(255, 255, 0, alpha); + + drawList->AddLine(ImVec2(sx, sy), ImVec2(sx2, sy), color); + drawList->AddLine(ImVec2(sx2, sy), ImVec2(sx2, sy2), color); + drawList->AddLine(ImVec2(sx2, sy2), ImVec2(sx, sy2), color); + drawList->AddLine(ImVec2(sx, sy2), ImVec2(sx, sy), color); + } + } + + Texture *texture = tilemap->GetTexture().get(); + int atlasCols = tilemap->GetAtlasColumns(); + int atlasRows = tilemap->GetAtlasRows(); + + if (texture && texture->GetID() != 0 && atlasCols > 0 && atlasRows > 0) + { + int x0 = tilemap->selStartX; + int y0 = tilemap->selStartY; + int x1 = tilemap->selEndX; + int y1 = tilemap->selEndY; + + // Normalize + if (x1 < x0) + std::swap(x0, x1); + if (y1 < y0) + std::swap(y0, y1); + + int widthInTiles = x1 - x0 + 1; + int heightInTiles = y1 - y0 + 1; + + float tileW = tileSize.x; + float tileH = tileSize.y; + + float snappedGX = std::floor(worldMouse.x / tileW) * tileW; + float snappedGY = std::floor(worldMouse.y / tileH) * tileH; + + float sx = (snappedGX - cameraPos.x) * cameraZoom + screenCenter.x; + float sy = (snappedGY - cameraPos.y) * cameraZoom + screenCenter.y; + float sx2 = (snappedGX + tileW * widthInTiles - cameraPos.x) * cameraZoom + screenCenter.x; + float sy2 = (snappedGY + tileH * heightInTiles - cameraPos.y) * cameraZoom + screenCenter.y; + + float texWidth = static_cast(texture->GetSize().x); + float texHeight = static_cast(texture->GetSize().y); + + float uvTileW = tileW / texWidth; + float uvTileH = tileH / texHeight; + + ImVec2 uvMin(x0 * uvTileW, y0 * uvTileH); + ImVec2 uvMax((x1 + 1) * uvTileW, (y1 + 1) * uvTileH); + + ImTextureID previewTexID = (ImTextureID)(uintptr_t)texture->GetID(); + drawList->AddImage(previewTexID, ImVec2(sx, sy), ImVec2(sx2, sy2), uvMin, uvMax, IM_COL32(255, 255, 255, 180)); + + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) + { + int gx = static_cast(snappedGX / tileSize.x); + int gy = static_cast(snappedGY / tileSize.y); + tilemap->PlaceSelection(gx, gy); + } + } + } + } + } - // Check if payload is being dropped inside the scene area if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("ASSET_TEXTURE")) @@ -1015,11 +1128,7 @@ void Engine::Run() { uint64_t uaid = *(const uint64_t *)payload->Data; - glm::vec2 worldPos = ScreenToWorld( - core::types::Vec2(mousePos.x - winPos.x, mousePos.y - winPos.y), - core::types::Vec2(winSize.x, winSize.y), - cameraPos, - cameraZoom); + glm::vec2 worldPos = ScreenToWorld(screenMousePos, viewportSize, cameraPos, cameraZoom); auto obj = std::make_shared("New Sprite"); obj->SetLocalPosition(worldPos); diff --git a/src/src/core/utils/TextureAtlas.h b/src/src/core/utils/TextureAtlas.h index 02536a6..2db4f48 100644 --- a/src/src/core/utils/TextureAtlas.h +++ b/src/src/core/utils/TextureAtlas.h @@ -28,7 +28,8 @@ struct TextureAtlas return core::types::Vec2(frameWidth, frameHeight); } - core::types::Vec2 GetFrameUV(int index) const + core::types::Vec2 GetFrameUV(int index) + const { if (!texture || frameWidth <= 0 || frameHeight <= 0) return core::types::Vec2(0.0f); diff --git a/src/src/editor/windows/Inspector.cpp b/src/src/editor/windows/Inspector.cpp index 9349f1e..1df0f11 100644 --- a/src/src/editor/windows/Inspector.cpp +++ b/src/src/editor/windows/Inspector.cpp @@ -13,10 +13,13 @@ #include "imgui.h" #include "imgui_internal.h" +#include + + void DrawInspectorUI(std::shared_ptr selected) { PROFILE_ENGINE_SCOPE("Engine::DrawInspectorUI"); - ImGui::Begin("Inspector"); + ImGui::Begin("Inspector", nullptr, ImGuiWindowFlags_NoScrollbar); if (!selected) { @@ -468,15 +471,17 @@ void DrawInspectorUI(std::shared_ptr selected) tilemap->SetTextureAtlas(texAsset->uaid, texelWidth, texelHeight); } - if (tilemap->GetTexture()) + if (auto texture = tilemap->GetTexture(); texture && texture.use_count() > 0 && texture->GetID() != 0) { ImGui::SeparatorText("Atlas Preview"); - auto texture = tilemap->GetTexture(); - ImTextureID texID = (ImTextureID)(uintptr_t)texture->GetID(); + - int texWidth = (int)texture->GetSize().x; - int texHeight = (int)texture->GetSize().y; + ImTextureID texID = (ImTextureID)(uintptr_t)texture->GetID(); + core::types::Vec2 texSize = texture->GetSize(); + + int texWidth = (int)texSize.x; + int texHeight = (int)texSize.y; // Validate texel size if (texelWidth <= 0 || texelHeight <= 0) @@ -504,6 +509,7 @@ void DrawInspectorUI(std::shared_ptr selected) // Draw the atlas ImGui::Image(texID, imageSize); + // Grid cell size in pixels float scaleX = imageSize.x / (float)texWidth; float scaleY = imageSize.y / (float)texHeight; @@ -625,6 +631,7 @@ void DrawInspectorUI(std::shared_ptr selected) } // ─ Selection‐region preview ─ + tilemap->hasSelection = hasSelection; if (hasSelection) { int x0 = std::min(selStartX, selEndX); @@ -632,6 +639,8 @@ void DrawInspectorUI(std::shared_ptr selected) int x1 = std::max(selStartX, selEndX); int y1 = std::max(selStartY, selEndY); + tilemap->SetSelection(x0, y0, x1, y1); + ImGui::SeparatorText("Selection Preview"); ImVec2 uv0( x0 * (float)texelWidth / texWidth, @@ -643,6 +652,11 @@ void DrawInspectorUI(std::shared_ptr selected) (x1 - x0 + 1) * (float)texelWidth * scaleX, (y1 - y0 + 1) * (float)texelHeight * scaleY); ImGui::Image(texID, imgSz, uv0, uv1); + + } + else + { + tilemap->ClearSelection(); } // Debug info @@ -656,6 +670,12 @@ void DrawInspectorUI(std::shared_ptr selected) ImGui::Separator(); } + else + { + ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1), "Texture is missing or not loaded properly."); + ImGui::Separator(); + } + ImGui::Separator(); if (ImGui::Button("Remove TilemapComponent"))