diff --git a/imgui.ini b/imgui.ini index 9f93055..1a7bf48 100644 --- a/imgui.ini +++ b/imgui.ini @@ -78,10 +78,10 @@ Collapsed=0 DockId=0x00000005,1 [Window][Color Correction] -Pos=0,19 -Size=342,662 +Pos=1588,867 +Size=332,310 Collapsed=0 -DockId=0x00000009,1 +DockId=0x00000006,1 [Window][Asset Browser] Pos=958,867 @@ -102,5 +102,5 @@ DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split= DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1242,481 Split=X Selected=0x9B5D3198 DockNode ID=0x0000000D Parent=0x00000005 SizeRef=612,248 HiddenTabBar=1 Selected=0xEA83D666 DockNode ID=0x0000000E Parent=0x00000005 SizeRef=628,248 HiddenTabBar=1 Selected=0x36AF052B - DockNode ID=0x00000006 Parent=0x00000008 SizeRef=332,481 HiddenTabBar=1 Selected=0x3FC1A724 + DockNode ID=0x00000006 Parent=0x00000008 SizeRef=332,481 Selected=0x3FC1A724 diff --git a/remake/build.log b/remake/build.log index 2049a02..53a29ba 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,3 +1,3 @@ -[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -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\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\AssetLoader.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\Logging.o src\build\core\utils\Profiler.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 -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -[RUN] Executed app.exe successfully. +[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Renderer.cpp -o src\build\Renderer.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\AssetLoader.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\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 -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto +[ERROR] Interrupted by user. diff --git a/src/src/Components/AnimationComponent.cpp b/src/src/Components/AnimationComponent.cpp index 1c91809..1db0edc 100644 --- a/src/src/Components/AnimationComponent.cpp +++ b/src/src/Components/AnimationComponent.cpp @@ -1,28 +1,18 @@ #include "AnimationComponent.h" -#include "Renderer.h" -AnimationComponent::AnimationComponent(Object* owner): Component(owner) {} +AnimationComponent::AnimationComponent(Object* owner) + : Component(owner) {} -void AnimationComponent::SetTextureAtlas(const std::string& path, int cols, int rows, float duration) { - texture = std::make_shared(path); - columns = cols; - rows = rows; - totalFrames = cols * rows; - frameDuration = duration; - GenerateUVs(); -} - -void AnimationComponent::GenerateUVs() { - uvOffsets.clear(); - float frameW = 1.0f / float(columns); - float frameH = 1.0f / float(rows); - - for (int y = 0; y < rows; ++y) { - for (int x = 0; x < columns; ++x) { - uvOffsets.emplace_back(core::types::Vec2(x * frameW, y * frameH)); - } + void AnimationComponent::SetTextureAtlas(const std::string& path, int cols, int rows, float duration) { + texturePath = path; + texture = std::make_shared(path); + atlas = TextureAtlas(texture, cols, rows); + columns = cols; + rows = rows; + totalFrames = cols * rows; + frameDuration = duration; } -} + void AnimationComponent::Play() { playing = true; } void AnimationComponent::Stop() { playing = false; } @@ -49,12 +39,33 @@ void AnimationComponent::Update(float dt) { } } -void AnimationComponent::Draw() { - if (!texture) return; - float frameW = 1.0f / float(columns); - float frameH = 1.0f / float(rows); - core::types::Vec2 uv = uvOffsets[currentFrame]; - //Renderer::Draw(*texture, GetOwner()->GetWorldPosition(), uv, core::types::Vec2(frameW, frameH)); +std::string AnimationComponent::GetName() const { + return "AnimationComponent"; } + +void AnimationComponent::Save(YAML::Emitter& out) const { + out << YAML::Key << "AnimationComponent"; + out << YAML::BeginMap; + out << YAML::Key << "TexturePath" << YAML::Value << texturePath; + out << YAML::Key << "Columns" << YAML::Value << columns; + out << YAML::Key << "Rows" << YAML::Value << rows; + out << YAML::Key << "FrameDuration" << YAML::Value << frameDuration; + out << YAML::EndMap; +} + +void AnimationComponent::Load(const YAML::Node& node) { + if (!node["AnimationComponent"]) + return; + + const auto& data = node["AnimationComponent"]; + std::string path = data["TexturePath"].as(); + int cols = data["Columns"].as(); + int rows = data["Rows"].as(); + float duration = data["FrameDuration"].as(); + + SetTextureAtlas(path, cols, rows, duration); +} + + diff --git a/src/src/Components/AnimationComponent.h b/src/src/Components/AnimationComponent.h index 3355645..fb3fb81 100644 --- a/src/src/Components/AnimationComponent.h +++ b/src/src/Components/AnimationComponent.h @@ -1,29 +1,47 @@ #pragma once #include "Component.h" -#include "core/types/Vec2.h" +#include "../core/types/Vec2.h" #include #include #include +#include "../core/utils/Texture.h" +#include "../core/utils/TextureAtlas.h" -class Texture; - -class AnimationComponent : public Component { +class AnimationComponent : public Component +{ public: - AnimationComponent(Object* owner);; + AnimationComponent(Object *owner); + + void SetTextureAtlas(const std::string &path, int cols, int rows, float frameDuration); - void SetTextureAtlas(const std::string& path, int cols, int rows, float frameDuration); void Play(); void Stop(); void SetLooping(bool loop); void SetSpeed(float speed); void SetFrame(int frame); + bool IsPlaying() const { return playing; } + bool IsLooping() const { return loop; } + float GetSpeed() const { return speed; } + + TextureAtlas *GetAtlas() { return &atlas; } + int GetCurrentFrame() const { return currentFrame; } + + const std::string &GetTexturePath() const { return texturePath; } + float GetFrameDuration() const { return frameDuration; } + void Update(float dt); - void Draw(); + + std::string GetName() const override; + void Save(YAML::Emitter &out) const override; + void Load(const YAML::Node &node) override; private: + std::string texturePath; + std::shared_ptr texture; - std::vector uvOffsets; + TextureAtlas atlas; + int columns = 1; int rows = 1; int totalFrames = 1; @@ -34,6 +52,4 @@ private: bool playing = true; bool loop = true; float speed = 1.0f; - - void GenerateUVs(); }; diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp index 49e99d8..239b9ff 100644 --- a/src/src/Engine.cpp +++ b/src/src/Engine.cpp @@ -8,6 +8,8 @@ #include "components/ScriptComponent.h" #include "components/PhysicsComponent.h" #include "components/ParticleComponent.h" +#include "components/AnimationComponent.h" + #include "core/utils/FileDialog.h" #include "core/utils/Logging.h" @@ -890,7 +892,16 @@ void Engine::Run() Renderer::DrawSprite(spritePtr.get(), worldPos, cameraZoom, cameraPos); profiler.EndSection(); } + + if (auto animator = obj->GetComponent()) { + profiler.BeginSection("Draw Animation: " + obj->GetName()); + Renderer::DrawTextureAtlas(animator->GetAtlas(), animator->GetCurrentFrame(), obj->GetWorldPosition(), obj->GetWorldRotation(), 1.0f); + + profiler.EndSection(); + } + + if (auto particle = obj->GetComponent()) { diff --git a/src/src/Entitys/Object.cpp b/src/src/Entitys/Object.cpp index 1026edb..c8ceec7 100644 --- a/src/src/Entitys/Object.cpp +++ b/src/src/Entitys/Object.cpp @@ -7,6 +7,8 @@ #include "../Components/TextComponent.h" #include "../Components/ScriptComponent.h" #include "../Components/ParticleComponent.h" +#include "../Components/AnimationComponent.h" + #include "../core/utils/Logging.h" @@ -156,6 +158,8 @@ void Object::Load(const YAML::Node &node) else if (type == "TextComponent") AddComponent()->Load(compNode); else if (type == "ScriptComponent") AddComponent()->Load(compNode); else if (type == "ParticleComponent") AddComponent()->Load(compNode); + else if (type == "AnimationComponent") AddComponent()->Load(compNode); + } } diff --git a/src/src/Renderer.cpp b/src/src/Renderer.cpp index 17b3260..5b2a539 100644 --- a/src/src/Renderer.cpp +++ b/src/src/Renderer.cpp @@ -395,7 +395,6 @@ void Renderer::Resize(int w, int h) width = w; height = h; - // Resize all textures glBindTexture(GL_TEXTURE_2D, textureColorBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); @@ -567,6 +566,39 @@ void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float z sortedDrawList.push_back(drawEntry); } + +void Renderer::DrawTextureAtlas(const TextureAtlas *atlas, int index, const core::types::Vec2 &pos, float rotationDeg, float zoom) +{ + PROFILE_DEEP_SCOPE("DrawTextureAtlas"); + + if (!atlas || !atlas->texture || index >= atlas->GetTotalFrames()) + return; + + const auto &tex = atlas->texture; + const core::types::Vec2 uvMin = atlas->GetFrameUV(index); + const core::types::Vec2 uvMax = uvMin + atlas->GetFrameSizeUV(); + + glm::vec2 screenPos = pos * zoom + glm::vec2(width, height) * 0.5f; + glm::vec2 finalSize = glm::vec2(1.0f) * zoom; + + BatchedSprite entry; + entry.screenPos = screenPos; + entry.size = finalSize; + entry.rotationRad = glm::radians(rotationDeg); + entry.textureID = tex->GetID(); + entry.normalMapID = defaultNormalMap; + entry.renderType = SpriteComponent::RenderType::Unlit; // no lighting for raw atlas drawing + entry.sprite = nullptr; + entry.texCoords = glm::vec4(uvMin.x, uvMin.y, uvMax.x, uvMax.y); + + SortedDrawEntry drawEntry; + drawEntry.sprite = entry; + drawEntry.shader = &unlitShader; + drawEntry.useLighting = false; + + sortedDrawList.push_back(drawEntry); +} + void Renderer::FlushQuads() { PROFILE_ENGINE_SCOPE("Renderer::FlushQuads"); diff --git a/src/src/Renderer.h b/src/src/Renderer.h index 7d9cdd0..18db759 100644 --- a/src/src/Renderer.h +++ b/src/src/Renderer.h @@ -10,6 +10,8 @@ #include "utils/Shader.h" #include "core/utils/Profiler.h" #include "core/types/all.h" +#include "core/utils/TextureAtlas.h" +#include "core/utils/Texture.h" struct ColorCorrection { @@ -80,6 +82,8 @@ public: static void DrawQuad(const core::types::Vec2 &pos, const core::types::Vec2 &size, float rotation, const core::types::Color &color); static void BatchQuad(const core::types::Vec2 &worldPos, const core::types::Vec2 &size, float rotation, const core::types::Color &color, const core::types::Vec2 &cameraPos, float zoom); + static void DrawTextureAtlas(const TextureAtlas *atlas, int index, const core::types::Vec2 &pos, float rotationDeg, float zoom); + static void FlushQuads(); private: diff --git a/src/src/core/utils/Texture.cpp b/src/src/core/utils/Texture.cpp new file mode 100644 index 0000000..6e77442 --- /dev/null +++ b/src/src/core/utils/Texture.cpp @@ -0,0 +1,20 @@ +#include "Texture.h" +#include +#include +#include +#include "utils.h" + + +Texture::Texture(const std::string &path) +{ + id = LoadTextureIfNeeded(path); +} + +Texture::~Texture() +{ +} + +unsigned int Texture::GetID() const +{ + return id; +} diff --git a/src/src/core/utils/Texture.h b/src/src/core/utils/Texture.h new file mode 100644 index 0000000..7917883 --- /dev/null +++ b/src/src/core/utils/Texture.h @@ -0,0 +1,13 @@ +#pragma once +#include + +class Texture { +public: + Texture(const std::string& path); + ~Texture(); + + unsigned int GetID() const; + +private: + unsigned int id = 0; +}; diff --git a/src/src/core/utils/TextureAtlas.h b/src/src/core/utils/TextureAtlas.h index a87e750..df7f578 100644 --- a/src/src/core/utils/TextureAtlas.h +++ b/src/src/core/utils/TextureAtlas.h @@ -1,10 +1,10 @@ #pragma once #include -#include "core/types/Vec2.h" +#include "../types/Vec2.h" +#include "Texture.h" -class Texture; - -struct TextureAtlas { +struct TextureAtlas +{ std::shared_ptr texture; int columns = 1; int rows = 1; @@ -13,19 +13,29 @@ struct TextureAtlas { TextureAtlas(std::shared_ptr tex, int cols, int rows) : texture(std::move(tex)), columns(cols), rows(rows) {} - core::types::Vec2 GetFrameUV(int index) const { - float w = 1.0f / float(columns); - float h = 1.0f / float(rows); + inline core::types::Vec2 GetFrameUV(int index) const + { + if (columns <= 0 || rows <= 0) + { + return core::types::Vec2(0.0f); + } + int x = index % columns; int y = index / columns; - return core::types::Vec2(x * w, y * h); + + float u = static_cast(x) / static_cast(columns); + float v = static_cast(y) / static_cast(rows); + + return core::types::Vec2(u, v); } - core::types::Vec2 GetFrameSizeUV() const { + core::types::Vec2 GetFrameSizeUV() const + { return core::types::Vec2(1.0f / float(columns), 1.0f / float(rows)); } - int GetTotalFrames() const { + int GetTotalFrames() const + { return columns * rows; } }; diff --git a/src/src/editor/windows/Inspector.cpp b/src/src/editor/windows/Inspector.cpp index 2bbd5fb..14d4cbd 100644 --- a/src/src/editor/windows/Inspector.cpp +++ b/src/src/editor/windows/Inspector.cpp @@ -8,6 +8,7 @@ #include "../../components/ScriptComponent.h" #include "../../components/PhysicsComponent.h" #include "../../components/ParticleComponent.h" +#include "../../components/AnimationComponent.h" void DrawInspectorUI(std::shared_ptr selected) { @@ -72,7 +73,8 @@ void DrawInspectorUI(std::shared_ptr selected) "LightComponent", "ScriptComponent", "TilemapComponent", - "ParticleComponent"}; + "ParticleComponent", + "AnimationComponent"}; static int selectedIndex = -1; @@ -106,13 +108,14 @@ void DrawInspectorUI(std::shared_ptr selected) selected->AddComponent(); else if (type == "ParticleComponent" && !selected->GetComponent()) selected->AddComponent(); + else if (type == "AnimationComponent" && !selected->GetComponent()) + selected->AddComponent(); } if (auto sprite = selected->GetComponent()) { ImGui::SeparatorText("Sprite Component"); - // — Render Type (unchanged) — const char *renderTypes[] = {"Unlit", "Lit"}; int currentTypeIndex = static_cast(sprite->GetRenderType()); if (ImGui::Combo("Render Type", ¤tTypeIndex, renderTypes, IM_ARRAYSIZE(renderTypes))) @@ -120,13 +123,10 @@ void DrawInspectorUI(std::shared_ptr selected) ImGui::SeparatorText("Texture"); - // — Texture File with Drag & Drop + Load Button — { std::string texFile = GetFilenameFromPath(sprite->GetTexturePath()); - // filename text ImGui::Text(texFile.c_str()); - // accept drag‑and‑drop here if (ImGui::BeginDragDropTarget()) { if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("ASSET_TEXTURE")) @@ -227,6 +227,7 @@ void DrawInspectorUI(std::shared_ptr selected) if (ImGui::Button("Remove LightComponent")) selected->RemoveComponent(); } + if (auto script = selected->GetComponent()) { ImGui::SeparatorText("Script Component"); @@ -251,6 +252,101 @@ void DrawInspectorUI(std::shared_ptr selected) if (ImGui::Button("Remove ScriptComponent")) selected->RemoveComponent(); } + if (auto anim = selected->GetComponent()) + { + ImGui::SeparatorText("Animation Component"); + + static int columns = anim->GetAtlas()->columns; + static int rows = anim->GetAtlas()->rows; + static float frameDuration = anim->GetFrameDuration(); + static int frameIndex = anim->GetCurrentFrame(); + + // — Texture Preview & Selector — + ImGui::SeparatorText("Texture Atlas"); + + { + std::string texFile = GetFilenameFromPath(anim->GetTexturePath()); + ImGui::Text(texFile.c_str()); + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("ASSET_TEXTURE")) + { + const char *dropped = (const char *)payload->Data; + anim->SetTextureAtlas(dropped, columns, rows, frameDuration); + } + ImGui::EndDragDropTarget(); + } + + if (ImGui::SmallButton("Load##AnimTex")) + { + auto path = OpenFileDialog(FileDialogType::Images); + if (!path.empty()) + anim->SetTextureAtlas(path, columns, rows, frameDuration); + } + } + + // — Grid settings — + ImGui::InputInt("Columns", &columns); + ImGui::InputInt("Rows", &rows); + ImGui::InputFloat("Frame Duration", &frameDuration, 0.01f, 0.1f, "%.3f"); + + if (ImGui::Button("Apply Grid")) + { + anim->SetTextureAtlas(anim->GetTexturePath(), columns, rows, frameDuration); + } + + // — Playback Controls — + ImGui::SeparatorText("Playback"); + + bool isPlaying = anim->IsPlaying(); + if (ImGui::Checkbox("Playing", &isPlaying)) + { + isPlaying ? anim->Play() : anim->Stop(); + } + + bool loop = anim->IsLooping(); + if (ImGui::Checkbox("Loop", &loop)) + { + anim->SetLooping(loop); + } + + float speed = anim->GetSpeed(); + if (ImGui::SliderFloat("Speed", &speed, 0.1f, 5.0f)) + { + anim->SetSpeed(speed); + } + + // Frame scrubber + int maxFrame = columns * rows - 1; + frameIndex = anim->GetCurrentFrame(); + if (ImGui::SliderInt("Current Frame", &frameIndex, 0, maxFrame)) + { + anim->SetFrame(frameIndex); + } + + // — Atlas Viewer — + if (anim->GetAtlas()->texture) + { + ImGui::SeparatorText("Atlas Viewer"); + + const float previewSize = 128.0f; + ImVec2 uv0, uv1; + + core::types::Vec2 uvMin = anim->GetAtlas()->GetFrameUV(frameIndex); + core::types::Vec2 uvSize = anim->GetAtlas()->GetFrameSizeUV(); + uv0 = ImVec2(uvMin.x, uvMin.y); + uv1 = ImVec2(uvMin.x + uvSize.x, uvMin.y + uvSize.y); + + ImGui::Image((ImTextureID)(intptr_t)anim->GetAtlas()->texture->GetID(), ImVec2(previewSize, previewSize), uv0, uv1); + } + + ImGui::Separator(); + + if (ImGui::Button("Remove AnimationComponent")) + selected->RemoveComponent(); + } + if (auto part = selected->GetComponent()) { ImGui::SeparatorText("Particle Component");