Updated Asset Manager and TileMap componenet

This commit is contained in:
OusmBlueNinja 2025-04-24 16:52:36 -05:00
parent e8e93db51f
commit 6b100d6609
18 changed files with 7824 additions and 174 deletions

View File

@ -10,24 +10,24 @@ Collapsed=1
[Window][WindowOverViewport_11111111] [Window][WindowOverViewport_11111111]
Pos=0,19 Pos=0,19
Size=1920,1158 Size=1280,701
Collapsed=0 Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=1573,19 Pos=790,19
Size=347,1158 Size=490,701
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
[Window][Scene Tree] [Window][Scene Tree]
Pos=0,19 Pos=0,19
Size=342,575 Size=342,348
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
[Window][Viewport] [Window][Viewport]
Pos=344,19 Pos=344,19
Size=1227,847 Size=444,390
Collapsed=0 Collapsed=0
DockId=0x00000007,0 DockId=0x00000007,0
@ -36,14 +36,14 @@ Size=1280,19
Collapsed=0 Collapsed=0
[Window][Performance Info] [Window][Performance Info]
Pos=344,868 Pos=344,411
Size=1227,309 Size=444,309
Collapsed=0 Collapsed=0
DockId=0x00000008,3 DockId=0x00000008,3
[Window][Console] [Window][Console]
Pos=344,868 Pos=344,411
Size=1227,309 Size=444,309
Collapsed=0 Collapsed=0
DockId=0x00000008,0 DockId=0x00000008,0
@ -54,8 +54,8 @@ Collapsed=0
DockId=0x00000007,1 DockId=0x00000007,1
[Window][Profiler] [Window][Profiler]
Pos=344,868 Pos=344,411
Size=1227,309 Size=444,309
Collapsed=0 Collapsed=0
DockId=0x00000008,2 DockId=0x00000008,2
@ -78,25 +78,30 @@ Collapsed=0
DockId=0x00000008,1 DockId=0x00000008,1
[Window][Color Correction] [Window][Color Correction]
Pos=344,868 Pos=344,411
Size=1227,309 Size=444,309
Collapsed=0 Collapsed=0
DockId=0x00000008,1 DockId=0x00000008,1
[Window][Asset Browser] [Window][Asset Browser]
Pos=0,596 Pos=0,369
Size=342,581 Size=342,351
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
[Window][Confirm Deletion]
Pos=722,488
Size=325,75
Collapsed=0
[Docking][Data] [Docking][Data]
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X
DockNode ID=0x00000005 Parent=0x11111111 SizeRef=1571,1158 Split=X DockNode ID=0x00000005 Parent=0x11111111 SizeRef=788,1158 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59 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=0x00000003 Parent=0x00000001 SizeRef=342,575 HiddenTabBar=1 Selected=0x12EF0F59
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,581 HiddenTabBar=1 Selected=0x36AF052B DockNode ID=0x00000004 Parent=0x00000001 SizeRef=342,581 HiddenTabBar=1 Selected=0x36AF052B
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1227,701 Split=Y Selected=0xC450F867 DockNode ID=0x00000002 Parent=0x00000005 SizeRef=444,701 Split=Y Selected=0xC450F867
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,847 CentralNode=1 HiddenTabBar=1 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=0x00000008 Parent=0x00000002 SizeRef=606,309 Selected=0x9B5D3198
DockNode ID=0x00000006 Parent=0x11111111 SizeRef=347,1158 HiddenTabBar=1 Selected=0x36DC96AB DockNode ID=0x00000006 Parent=0x11111111 SizeRef=490,1158 HiddenTabBar=1 Selected=0x36DC96AB

View File

@ -5,6 +5,8 @@ src_dirs:
- src/include/lua - src/include/lua
- src/vendor/imgui - src/vendor/imgui
- src/vendor/box2d - src/vendor/box2d
- src/vendor/xxhash
# Include directories (-I) # Include directories (-I)
include_dirs: include_dirs:
@ -13,8 +15,8 @@ include_dirs:
- src/vendor - src/vendor
- src/vendor/imgui - src/vendor/imgui
- src/vendor/box2d - src/vendor/box2d
- src/vendor/xxhash
- C:/msys64/mingw64/include - C:/msys64/mingw64/include
# Library search paths (-L) # Library search paths (-L)

View File

@ -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\editor\windows\Inspector.cpp -o src\build\editor\windows\Inspector.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\AnimationComponent.cpp -o src\build\Components\AnimationComponent.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 -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto [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
[RUN] Executed app.exe successfully. [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

View File

@ -1,10 +1,10 @@
engine_version: 0.1.0 engine_version: 0.1.0
scene_name: TilemapTest scene_name: TilemapTest
scene_hash: da1e2dee8a989a2dc8390342cf9c900f4de6ad42a54b5f9250189f01645bbf27 scene_hash: 83d59efe885ac3d8546339353a2b5ed05c4f264ae8b17ad3695475e23e925ee6
format_version: 1 format_version: 1
objects: objects:
- name: Hello, Create - name: Hello, Create
uid: ef684c7c34b34d81a41d052066bc806c uid: b6da0e9b788248759d630d5599fdf8df
id: 0 id: 0
position: [0, 0] position: [0, 0]
rotation: 0 rotation: 0
@ -13,28 +13,28 @@ objects:
components: components:
- type: TilemapComponent - type: TilemapComponent
TextureUAID: 1 TextureUAID: 1
TexelWidth: 16 TexelWidth: 32
TexelHeight: 16 TexelHeight: 32
TileSize: TileSize:
x: 32 x: 32
y: 32 y: 32
Tiles: Tiles: []
- [6, 1, 15] children: []
- [6, 2, 14] - name: NewObject
- [0, 0, 1] uid: 248c6524f6b447cca4a249eb85500d59
- [6, 0, 16] id: 1
- [4, 3, 11] position: [0, 0]
- [1, 0, 2] rotation: 0
- [5, 3, 12] layer: 0
- [2, 0, 3] visable: true
- [6, 3, 13] components:
- [0, 1, 4] - type: AnimationComponent
- [1, 1, 5] TextureUAID: 2
- [2, 1, 6] TexelWidth: 64
- [0, 2, 7] TexelHeight: 64
- [1, 2, 8] FrameDuration: 0.0500000007
- [2, 2, 9] StartFrame: 0
- [3, 3, 10] EndFrame: 56
children: [] children: []
color_correction: color_correction:
brightness: 1 brightness: 1
@ -44,9 +44,33 @@ color_correction:
intensity: 1.20000005 intensity: 1.20000005
threshold: 1 threshold: 1
Assets: Assets:
- uaid: 3
path: C:\Users\spenc\OneDrive\Pictures\Pixel Holy Spell Effect 32x32 Pack 3\01.png
filename: 01.png
filetype: png
type: 0
size: [704, 576]
hash: 82866fcf3324b785
channels: 4
format: GL_RGBA
lastModified: 1687052107
- uaid: 2
path: C:\Users\spenc\OneDrive\Pictures\Pixel Holy Spell Effect 32x32 Pack 3\00.png
filename: 00.png
filetype: png
type: 0
size: [1216, 192]
hash: 2b0b3c20179d6f12
channels: 4
format: GL_RGBA
lastModified: 1687052065
- uaid: 1 - uaid: 1
path: C:\Users\spenc\OneDrive\Pictures\6656e7221e49a1774d2fb280357e56f8d25d9d95.png path: C:\Users\spenc\OneDrive\Pictures\6656e7221e49a1774d2fb280357e56f8d25d9d95.png
filename: 6656e7221e49a1774d2fb280357e56f8d25d9d95.png filename: 6656e7221e49a1774d2fb280357e56f8d25d9d95.png
filetype: png filetype: png
type: 0 type: 0
size: [1024, 1024] size: [1024, 1024]
hash: e8aaee6025f21557
channels: 4
format: GL_RGBA
lastModified: 1744577923

View File

@ -49,15 +49,14 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
startFrame = 0; startFrame = 0;
endFrame = totalFrames > 0 ? totalFrames - 1 : 0; endFrame = totalFrames > 0 ? totalFrames - 1 : 0;
if (start != 0) if (start != 0)
{ {
startFrame = start; startFrame = start;
} }
if (end != 0) if (end != 0)
{ {
endFrame = end; endFrame = end;
} }
frameDuration = duration; frameDuration = duration;
@ -66,8 +65,8 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe
renderType = RenderType::Unlit; renderType = RenderType::Unlit;
} }
void AnimationComponent::Play() { playing = true; } void AnimationComponent::Play() { playing = true; }
void AnimationComponent::Stop() { playing = false; } void AnimationComponent::Stop() { playing = false; }
void AnimationComponent::SetLooping(bool loop_) { loop = loop_; } void AnimationComponent::SetLooping(bool loop_) { loop = loop_; }
bool AnimationComponent::IsPlaying() const { return playing; } bool AnimationComponent::IsPlaying() const { return playing; }
@ -80,25 +79,25 @@ void AnimationComponent::SetTextureUAID(uint64_t uaid) { textureUAID = uaid; }
bool AnimationComponent::IsLooping() const { return loop; } bool AnimationComponent::IsLooping() const { return loop; }
void AnimationComponent::SetSpeed(float speed_) { speed = speed_; } void AnimationComponent::SetSpeed(float speed_) { speed = speed_; }
float AnimationComponent::GetSpeed() const { return speed; } float AnimationComponent::GetSpeed() const { return speed; }
void AnimationComponent::SetFrame(int frame) void AnimationComponent::SetFrame(int frame)
{ {
currentFrame = std::clamp(frame, startFrame, endFrame); currentFrame = std::clamp(frame, startFrame, endFrame);
time = 0.0f; time = 0.0f;
} }
int AnimationComponent::GetCurrentFrame() const { return currentFrame; } int AnimationComponent::GetCurrentFrame() const { return currentFrame; }
int AnimationComponent::GetStartFrame() const { return startFrame; } int AnimationComponent::GetStartFrame() const { return startFrame; }
void AnimationComponent::SetStartFrame(int start) { startFrame = std::clamp(start, 0, totalFrames - 1); } void AnimationComponent::SetStartFrame(int start) { startFrame = std::clamp(start, 0, totalFrames - 1); }
int AnimationComponent::GetEndFrame() const { return endFrame; } int AnimationComponent::GetEndFrame() const { return endFrame; }
void AnimationComponent::SetEndFrame(int end) { endFrame = std::clamp(end, 0, totalFrames - 1); } void AnimationComponent::SetEndFrame(int end) { endFrame = std::clamp(end, 0, totalFrames - 1); }
int AnimationComponent::GetTotalFrames() const { return totalFrames; } int AnimationComponent::GetTotalFrames() const { return totalFrames; }
float AnimationComponent::GetFrameDuration() const { return frameDuration; } float AnimationComponent::GetFrameDuration() const { return frameDuration; }
void AnimationComponent::SetFrameDuration(float duration) { frameDuration = duration; } void AnimationComponent::SetFrameDuration(float duration) { frameDuration = duration; }
TextureAtlas* AnimationComponent::GetAtlas() { return &atlas; } TextureAtlas *AnimationComponent::GetAtlas() { return &atlas; }
const TextureAtlas* AnimationComponent::GetAtlas() const { return &atlas; } const TextureAtlas *AnimationComponent::GetAtlas() const { return &atlas; }
void AnimationComponent::Update(float dt) void AnimationComponent::Update(float dt)
{ {
@ -117,7 +116,7 @@ void AnimationComponent::Update(float dt)
currentFrame = startFrame; currentFrame = startFrame;
else else
{ {
currentFrame = endFrame; currentFrame = startFrame;
playing = false; playing = false;
} }
} }
@ -128,8 +127,8 @@ std::string AnimationComponent::GetName() const { return "AnimationComponent"; }
void AnimationComponent::Save(YAML::Emitter &out) const void AnimationComponent::Save(YAML::Emitter &out) const
{ {
out << YAML::Key << "AnimationComponent";
out << YAML::BeginMap; out << YAML::BeginMap;
out << YAML::Key << "type" << YAML::Value << GetName();
out << YAML::Key << "TextureUAID" << YAML::Value << textureUAID; out << YAML::Key << "TextureUAID" << YAML::Value << textureUAID;
out << YAML::Key << "TexelWidth" << YAML::Value << atlas.frameWidth; out << YAML::Key << "TexelWidth" << YAML::Value << atlas.frameWidth;
out << YAML::Key << "TexelHeight" << YAML::Value << atlas.frameHeight; out << YAML::Key << "TexelHeight" << YAML::Value << atlas.frameHeight;
@ -141,16 +140,13 @@ void AnimationComponent::Save(YAML::Emitter &out) const
void AnimationComponent::Load(const YAML::Node &node) void AnimationComponent::Load(const YAML::Node &node)
{ {
if (!node["AnimationComponent"])
return;
const auto &data = node["AnimationComponent"]; uint64_t uaid = node["TextureUAID"].as<uint64_t>();
uint64_t uaid = data["TextureUAID"].as<uint64_t>(); int texelWidth = node["TexelWidth"].as<int>();
int texelWidth = data["TexelWidth"].as<int>(); int texelHeight = node["TexelHeight"].as<int>();
int texelHeight = data["TexelHeight"].as<int>(); float duration = node["FrameDuration"].as<float>();
float duration = data["FrameDuration"].as<float>(); int start = node["StartFrame"] ? node["StartFrame"].as<int>() : 0;
int start = data["StartFrame"] ? data["StartFrame"].as<int>() : 0; int end = node["EndFrame"] ? node["EndFrame"].as<int>() : 0;
int end = data["EndFrame"] ? data["EndFrame"].as<int>() : INT_MAX;
SetTextureAtlas(uaid, texelWidth, texelHeight, duration, start, end); SetTextureAtlas(uaid, texelWidth, texelHeight, duration, start, end);
} }

View File

@ -16,6 +16,7 @@ void LightComponent::Save(YAML::Emitter& out) const
out << YAML::EndMap; out << YAML::EndMap;
} }
void LightComponent::Load(const YAML::Node& node) void LightComponent::Load(const YAML::Node& node)
{ {
if (node["color"]) if (node["color"])

View File

@ -53,8 +53,6 @@ static std::shared_ptr<Object> selected = nullptr;
static bool playing = false; static bool playing = false;
static bool lastPlaying = false; static bool lastPlaying = false;
static std::vector<std::shared_ptr<Object>> pendingDeletion;
static glm::vec2 cameraPos = {0, 0}; static glm::vec2 cameraPos = {0, 0};
static float cameraZoom = 1.0f; static float cameraZoom = 1.0f;
static ImVec2 lastMousePos = {}; static ImVec2 lastMousePos = {};
@ -514,19 +512,25 @@ void Engine::Init()
Logger::LogVerbose("Resverving Objects"); Logger::LogVerbose("Resverving Objects");
// These values were AI Generated.
// These values were AI Generated.
m_toDraw.reserve(2048); // ~2K sprites per frame (including UI, particles, objects) m_toDraw.reserve(2048); // ~2K sprites per frame (including UI, particles, objects)
m_scriptUpdates.reserve(256); // ~256 active script components per frame m_scriptUpdates.reserve(256); // ~256 active script components per frame
m_collectStack.reserve(2048); // Used for internal temp memory, 512 is safe unless deep recursion m_collectStack.reserve(2048); // Used for internal temp memory, 512 is safe unless deep recursion
m_physicsUpdates.reserve(512); // 256-512 physics bodies/entities with Box2D m_physicsUpdates.reserve(512); // 256-512 physics bodies/entities with Box2D
m_particleUpdates.reserve(24); // ~1K particle systems active is fair in effects-heavy scenes m_particleUpdates.reserve(24); // ~1K particle systems active is fair in effects-heavy scenes
m_animationsUpdates.reserve(512); // ~500 animated objects (characters, FX, etc.) m_animationsUpdates.reserve(512); // ~500 animated objects (characters, FX, etc.)
Logger::LogInfo("Initialized Engine"); Logger::LogInfo("Initialized Engine");
} }
core::types::Vec2 ScreenToWorld(const core::types::Vec2 &screenPos, const core::types::Vec2 &viewportSize, const core::types::Vec2 &cameraPos, float zoom)
{
core::types::Vec2 viewportCenter = viewportSize * 0.5f;
core::types::Vec2 world = (screenPos - viewportCenter) / zoom + cameraPos;
return world;
}
void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom) void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom)
{ {
@ -576,7 +580,6 @@ void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom
if (auto animator = obj->GetComponent<AnimationComponent>()) if (auto animator = obj->GetComponent<AnimationComponent>())
m_animationsUpdates.push_back(animator.get()); m_animationsUpdates.push_back(animator.get());
if (playing) if (playing)
{ {
if (auto script = obj->GetComponent<ScriptComponent>()) if (auto script = obj->GetComponent<ScriptComponent>())
@ -725,7 +728,7 @@ void Engine::Run()
ImGui::EndMainMenuBar(); ImGui::EndMainMenuBar();
} }
profiler.EndEngineSection(); // End BeginMainMenuBar profiler.EndEngineSection();
if (g_engineConfig.settings.show_color_correction_window) if (g_engineConfig.settings.show_color_correction_window)
ShowColorCorrectionWindow(); ShowColorCorrectionWindow();
@ -736,6 +739,35 @@ void Engine::Run()
PROFILE_ENGINE_SCOPE("Engine::DrawSceneTree"); PROFILE_ENGINE_SCOPE("Engine::DrawSceneTree");
ImGui::Begin("Scene Tree"); 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?");
ImGui::Separator();
if (ImGui::Button("Delete"))
{
pendingDeletion.push_back(selected);
selected = nullptr;
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Cancel"))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (ImGui::BeginPopupContextWindow("SceneTreeContext", ImGuiPopupFlags_MouseButtonRight)) if (ImGui::BeginPopupContextWindow("SceneTreeContext", ImGuiPopupFlags_MouseButtonRight))
{ {
@ -968,7 +1000,41 @@ void Engine::Run()
GLuint texID = Renderer::GetFinalTexture(); GLuint texID = Renderer::GetFinalTexture();
ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0)); 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();
// Check if payload is being dropped inside the scene area
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("ASSET_TEXTURE"))
{
if (payload->DataSize == sizeof(uint64_t))
{
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);
auto obj = std::make_shared<Object>("New Sprite");
obj->SetLocalPosition(worldPos);
auto sprite = obj->AddComponent<SpriteComponent>();
sprite->SetTexture(uaid);
objects.push_back(obj);
}
}
ImGui::EndDragDropTarget();
}
ImGui::End(); ImGui::End();
profiler.EndEngineSection(); profiler.EndEngineSection();
ShowProfilerTimeline(); ShowProfilerTimeline();
@ -1204,7 +1270,6 @@ void Engine::LoadScene(const std::string &path)
loadingUI.Update(currentStep, currentDetail, 0.05f); loadingUI.Update(currentStep, currentDetail, 0.05f);
Logger::LogVerbose("[LoadScene] Loading Assets"); Logger::LogVerbose("[LoadScene] Loading Assets");
AssetManager::ClearAllAssets();
AssetManager::Load(root["Assets"]); AssetManager::Load(root["Assets"]);
} }

View File

@ -5,25 +5,25 @@
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h> #include <stb_image.h>
#include <future> #include <future>
#include <iostream>
// Static definitions // Static definitions
std::unordered_map<uint64_t, AssetInfo> AssetManager::s_Assets; std::unordered_map<uint64_t, AssetInfo> AssetManager::s_Assets;
std::unordered_map<std::string, uint64_t> AssetManager::s_PathToUAID; std::unordered_map<std::string, uint64_t> AssetManager::s_PathToUAID;
std::mutex AssetManager::s_Mutex;
uint64_t AssetManager::s_NextUAID = 1; uint64_t AssetManager::s_NextUAID = 1;
void AssetManager::Init() {} void AssetManager::Init() {}
uint64_t AssetManager::GenerateUAID() uint64_t AssetManager::GenerateUAID()
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
return s_NextUAID++; return s_NextUAID++;
} }
void AssetManager::LoadAssetAsync(const std::string &path, AssetType type) void AssetManager::LoadAssetAsync(const std::string &path, AssetType type)
{ {
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
auto itPath = s_PathToUAID.find(path); auto itPath = s_PathToUAID.find(path);
if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded) if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded)
{ {
@ -40,7 +40,7 @@ void AssetManager::LoadAssetAsync(const std::string &path, AssetType type)
info.filename = GetFilenameFromPath(path); info.filename = GetFilenameFromPath(path);
info.filetype = ::GetFileExtension(path); info.filetype = ::GetFileExtension(path);
info.type = type; info.type = type;
std::lock_guard<std::mutex> lock(s_Mutex);
s_Assets[uaid] = info; s_Assets[uaid] = info;
s_PathToUAID[path] = uaid; s_PathToUAID[path] = uaid;
} }
@ -59,10 +59,10 @@ void AssetManager::LoadAssetAsync(const std::string &path, AssetType type)
void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid) void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid)
{ {
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
auto it = s_Assets.find(uaid); auto it = s_Assets.find(uaid);
if (it != s_Assets.end() && it->second.loaded) if (it != s_Assets.end() && it->second.loaded)
return; return;
auto itPath = s_PathToUAID.find(path); auto itPath = s_PathToUAID.find(path);
if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded) if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded)
return; return;
@ -70,6 +70,7 @@ void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid)
Logger::LogVerbose("[AssetManager] Begin loading image: %s (UAID: %llu)", path.c_str(), uaid); Logger::LogVerbose("[AssetManager] Begin loading image: %s (UAID: %llu)", path.c_str(), uaid);
stbi_set_flip_vertically_on_load(false); stbi_set_flip_vertically_on_load(false);
int w, h, channels; int w, h, channels;
stbi_uc *pixels = stbi_load(path.c_str(), &w, &h, &channels, STBI_rgb_alpha); stbi_uc *pixels = stbi_load(path.c_str(), &w, &h, &channels, STBI_rgb_alpha);
if (!pixels) if (!pixels)
@ -88,33 +89,35 @@ void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(pixels); stbi_image_free(pixels);
if (texID == 0) if (texID == 0)
{ {
Logger::LogError("[AssetManager] Failed to Load asset."); Logger::LogError("[AssetManager] Failed to Load asset.");
return; return;
} }
{ auto &asset = s_Assets[uaid];
std::lock_guard<std::mutex> lock(s_Mutex); asset.size = {static_cast<float>(w), static_cast<float>(h)};
auto &asset = s_Assets[uaid]; asset.textureID = texID;
asset.size = {static_cast<float>(w), static_cast<float>(h)}; asset.loaded = true;
asset.textureID = texID; asset.channels = channels;
asset.loaded = true; asset.format = "GL_RGBA";
} asset.lastModified = GetFileLastWrite(path);
asset.hash = GetFileHash(path);
Logger::LogVerbose("[AssetManager] Finished loading image: %s (%dx%d) (UAID: %llu, Texture ID: %u)", path.c_str(), w, h, uaid, texID); Logger::LogVerbose("[AssetManager] Finished loading image: %s (%dx%d) (UAID: %llu, Texture ID: %u)", path.c_str(), w, h, uaid, texID);
} }
const AssetInfo *AssetManager::GetAssetByID(uint64_t uaid) const AssetInfo *AssetManager::GetAssetByID(uint64_t uaid)
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
auto it = s_Assets.find(uaid); auto it = s_Assets.find(uaid);
return it != s_Assets.end() ? &it->second : nullptr; return it != s_Assets.end() ? &it->second : nullptr;
} }
const AssetInfo *AssetManager::GetAssetByPath(const std::string &path) const AssetInfo *AssetManager::GetAssetByPath(const std::string &path)
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
auto it = s_PathToUAID.find(path); auto it = s_PathToUAID.find(path);
return it != s_PathToUAID.end() ? &s_Assets[it->second] : nullptr; return it != s_PathToUAID.end() ? &s_Assets[it->second] : nullptr;
} }
@ -126,7 +129,7 @@ const std::unordered_map<uint64_t, AssetInfo> &AssetManager::GetAllAssets()
void AssetManager::UnloadAsset(uint64_t uaid) void AssetManager::UnloadAsset(uint64_t uaid)
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
auto it = s_Assets.find(uaid); auto it = s_Assets.find(uaid);
if (it != s_Assets.end()) if (it != s_Assets.end())
{ {
@ -139,7 +142,7 @@ void AssetManager::UnloadAsset(uint64_t uaid)
void AssetManager::ClearAllAssets() void AssetManager::ClearAllAssets()
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
for (auto &kv : s_Assets) for (auto &kv : s_Assets)
if (kv.second.textureID) if (kv.second.textureID)
glDeleteTextures(1, &kv.second.textureID); glDeleteTextures(1, &kv.second.textureID);
@ -149,7 +152,6 @@ void AssetManager::ClearAllAssets()
void AssetManager::Save(YAML::Emitter &out) void AssetManager::Save(YAML::Emitter &out)
{ {
std::lock_guard<std::mutex> lock(s_Mutex);
out << YAML::Key << "Assets" << YAML::BeginSeq; out << YAML::Key << "Assets" << YAML::BeginSeq;
for (const auto &kv : s_Assets) for (const auto &kv : s_Assets)
{ {
@ -161,6 +163,10 @@ void AssetManager::Save(YAML::Emitter &out)
<< YAML::Key << "filetype" << YAML::Value << a.filetype << YAML::Key << "filetype" << YAML::Value << a.filetype
<< YAML::Key << "type" << YAML::Value << static_cast<int>(a.type) << YAML::Key << "type" << YAML::Value << static_cast<int>(a.type)
<< YAML::Key << "size" << YAML::Value << YAML::Flow << YAML::BeginSeq << a.size.x << a.size.y << YAML::EndSeq << YAML::Key << "size" << YAML::Value << YAML::Flow << YAML::BeginSeq << a.size.x << a.size.y << YAML::EndSeq
<< YAML::Key << "hash" << YAML::Value << a.hash
<< YAML::Key << "channels" << YAML::Value << a.channels
<< YAML::Key << "format" << YAML::Value << a.format
<< YAML::Key << "lastModified" << YAML::Value << a.lastModified
<< YAML::EndMap; << YAML::EndMap;
} }
out << YAML::EndSeq; out << YAML::EndSeq;
@ -170,6 +176,7 @@ void AssetManager::Load(const YAML::Node &node)
{ {
if (!node) if (!node)
return; return;
for (const auto &item : node) for (const auto &item : node)
{ {
uint64_t uaid = item["uaid"].as<uint64_t>(); uint64_t uaid = item["uaid"].as<uint64_t>();
@ -178,35 +185,32 @@ void AssetManager::Load(const YAML::Node &node)
float sx = item["size"][0].as<float>(); float sx = item["size"][0].as<float>();
float sy = item["size"][1].as<float>(); float sy = item["size"][1].as<float>();
bool already = false; AssetInfo asset;
{ asset.uaid = uaid;
std::lock_guard<std::mutex> lock(s_Mutex); asset.path = path;
auto it = s_Assets.find(uaid); asset.filename = item["filename"] ? item["filename"].as<std::string>() : GetFilenameFromPath(path);
if (it != s_Assets.end() && it->second.loaded) asset.filetype = item["filetype"] ? item["filetype"].as<std::string>() : ::GetFileExtension(path);
{ asset.type = type;
already = true; asset.size = {sx, sy};
} asset.hash = item["hash"] ? item["hash"].as<std::string>() : "";
else asset.channels = item["channels"] ? item["channels"].as<int>() : 4;
{ asset.format = item["format"] ? item["format"].as<std::string>() : "GL_RGBA";
AssetInfo asset; asset.lastModified = item["lastModified"] ? item["lastModified"].as<std::time_t>() : 0;
asset.uaid = uaid; asset.loaded = false;
asset.path = path; asset.textureID = 0;
asset.filename = GetFilenameFromPath(path);
asset.filetype = ::GetFileExtension(path); s_Assets[uaid] = asset;
asset.type = type; s_PathToUAID[path] = uaid;
asset.size = {sx, sy};
asset.loaded = false; if (uaid >= s_NextUAID)
asset.textureID = 0; s_NextUAID = uaid + 1;
s_Assets[uaid] = asset;
s_PathToUAID[path] = uaid; if (type == AssetType::Image)
if (uaid >= s_NextUAID)
s_NextUAID = uaid + 1;
}
}
if (!already && type == AssetType::Image)
{ {
Logger::LogVerbose("[AssetManager] Reloading from file: %s (UAID: %llu)", path.c_str(), uaid); Logger::LogVerbose("[AssetManager] Reloading from file: %s (UAID: %llu)", path.c_str(), uaid);
LoadImageInternal(path, uaid); LoadImageInternal(path, uaid);
} }
} }
} }

View File

@ -20,6 +20,12 @@ struct AssetInfo
AssetType type; AssetType type;
core::types::Vec2 size; core::types::Vec2 size;
std::string hash;
int channels = 4;
std::string format;
std::time_t lastModified = 0;
bool loaded = false; bool loaded = false;
GLuint textureID = 0; GLuint textureID = 0;
}; };
@ -43,7 +49,6 @@ public:
private: private:
static std::unordered_map<uint64_t, AssetInfo> s_Assets; static std::unordered_map<uint64_t, AssetInfo> s_Assets;
static std::unordered_map<std::string, uint64_t> s_PathToUAID; static std::unordered_map<std::string, uint64_t> s_PathToUAID;
static std::mutex s_Mutex;
static uint64_t s_NextUAID; static uint64_t s_NextUAID;
static uint64_t GenerateUAID(); static uint64_t GenerateUAID();

View File

@ -20,6 +20,8 @@ Texture::Texture(const std::string &path)
} }
} }
Texture::Texture(uint64_t uaid) Texture::Texture(uint64_t uaid)
{ {
const auto *asset = AssetManager::GetAssetByID(uaid); const auto *asset = AssetManager::GetAssetByID(uaid);

View File

@ -4,8 +4,18 @@
#include <windows.h> #include <windows.h>
#include <filesystem> #include <filesystem>
#include <string> #include <string>
#include <sstream>
#include <unordered_map> #include <unordered_map>
#include <mutex> #include <mutex>
#include <xxhash.h>
#include <filesystem>
#include <chrono>
#include <ctime>
#include "imgui.h"
#include "imgui_internal.h" // for ImGuiWindow, ImGuiDockNode
#include <fstream>
#include <sstream>
std::unordered_map<std::string, ImageCacheEntry> textureCache; std::unordered_map<std::string, ImageCacheEntry> textureCache;
std::unordered_map<std::string, ImageCacheEntry> engineTextureCache; std::unordered_map<std::string, ImageCacheEntry> engineTextureCache;
@ -151,4 +161,51 @@ bool DeleteLatestLogFile()
} }
return false; // File didn't exist return false; // File didn't exist
} }
bool IsWindowVisibleTab(const char* name)
{
ImGuiWindow* win = ImGui::FindWindowByName(name);
if (!win || !win->DockNode)
return false;
return win->DockNode->SelectedTabId == win->ID;
}
std::string HashString(const std::string& data)
{
uint64_t hash = XXH3_64bits(data.data(), data.size());
std::ostringstream oss;
oss << std::hex << std::setfill('0') << std::setw(16) << hash;
return oss.str(); // returns lowercase 16-char hex string
}
std::string GetFileHash(const std::string &path)
{
std::ifstream stream(path, std::ios::binary);
if (!stream)
return "";
std::string data((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
return HashString(data);
}
std::time_t GetFileLastWrite(const std::string &path)
{
try
{
auto ftime = std::filesystem::last_write_time(path);
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
ftime - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now());
return std::chrono::system_clock::to_time_t(sctp);
}
catch (...)
{
return 0; // return 0 if file doesn't exist or error occurs
}
}

View File

@ -1,8 +1,11 @@
#pragma once #pragma once
#include <string> #include <string>
#include <GL/glew.h> #include <GL/glew.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <ctime>
// here so i only need to include once. // here so i only need to include once.
@ -35,6 +38,13 @@ GLuint EngineLoadTextureIfNeeded(const std::string &path);
bool DeleteLatestLogFile(); bool DeleteLatestLogFile();
bool IsWindowVisibleTab(const char* name);
std::string HashString(const std::string& data);
std::time_t GetFileLastWrite(const std::string &path);
std::string GetFileHash(const std::string &path);
// HSV → RGB helper // HSV → RGB helper
inline glm::vec3 HSVtoRGB(float h, float s, float v) inline glm::vec3 HSVtoRGB(float h, float s, float v)

View File

@ -50,7 +50,7 @@ void ShowAssetBrowser()
ImGui::Columns(columns, nullptr, false); ImGui::Columns(columns, nullptr, false);
int idx = 0; int idx = 0;
for (const auto& [uaid, asset] : AssetManager::GetAllAssets()) for (const auto &[uaid, asset] : AssetManager::GetAllAssets())
{ {
if (asset.type != AssetType::Image || !asset.loaded) if (asset.type != AssetType::Image || !asset.loaded)
continue; continue;

View File

@ -71,13 +71,13 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
ImGui::SeparatorText("Add Component"); ImGui::SeparatorText("Add Component");
static const char *componentTypes[] = { static const char *componentTypes[] = {
"SpriteComponent", "Sprite",
"CameraComponent", "Camera",
"LightComponent", "Light",
"ScriptComponent", "Script",
"TilemapComponent", "Tilemap",
"ParticleComponent", "Particle",
"AnimationComponent"}; "Animation"};
static int selectedIndex = -1; static int selectedIndex = -1;
@ -99,19 +99,19 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
{ {
const std::string type = componentTypes[selectedIndex]; const std::string type = componentTypes[selectedIndex];
if (type == "SpriteComponent" && !selected->GetComponent<SpriteComponent>()) if (type == "Sprite" && !selected->GetComponent<SpriteComponent>())
selected->AddComponent<SpriteComponent>(); selected->AddComponent<SpriteComponent>();
else if (type == "CameraComponent" && !selected->GetComponent<CameraComponent>()) else if (type == "Camera" && !selected->GetComponent<CameraComponent>())
selected->AddComponent<CameraComponent>(); selected->AddComponent<CameraComponent>();
else if (type == "LightComponent" && !selected->GetComponent<LightComponent>()) else if (type == "Light" && !selected->GetComponent<LightComponent>())
selected->AddComponent<LightComponent>(); selected->AddComponent<LightComponent>();
else if (type == "ScriptComponent" && !selected->GetComponent<ScriptComponent>()) else if (type == "Script" && !selected->GetComponent<ScriptComponent>())
selected->AddComponent<ScriptComponent>(); selected->AddComponent<ScriptComponent>();
else if (type == "TilemapComponent" && !selected->GetComponent<TilemapComponent>()) else if (type == "Tilemap" && !selected->GetComponent<TilemapComponent>())
selected->AddComponent<TilemapComponent>(); selected->AddComponent<TilemapComponent>();
else if (type == "ParticleComponent" && !selected->GetComponent<ParticleComponent>()) else if (type == "Particle" && !selected->GetComponent<ParticleComponent>())
selected->AddComponent<ParticleComponent>(); selected->AddComponent<ParticleComponent>();
else if (type == "AnimationComponent" && !selected->GetComponent<AnimationComponent>()) else if (type == "Animation" && !selected->GetComponent<AnimationComponent>())
selected->AddComponent<AnimationComponent>(); selected->AddComponent<AnimationComponent>();
} }
@ -468,7 +468,6 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
tilemap->SetTextureAtlas(texAsset->uaid, texelWidth, texelHeight); tilemap->SetTextureAtlas(texAsset->uaid, texelWidth, texelHeight);
} }
// Atlas preview and grid
if (tilemap->GetTexture()) if (tilemap->GetTexture())
{ {
ImGui::SeparatorText("Atlas Preview"); ImGui::SeparatorText("Atlas Preview");
@ -484,26 +483,28 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
{ {
ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1), "Invalid texel size (must be >= 1)"); ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1), "Invalid texel size (must be >= 1)");
ImGui::Separator(); ImGui::Separator();
return;
} }
int numCols = texWidth / texelWidth; int numCols = texWidth / texelWidth;
int numRows = texHeight / texelHeight; int numRows = texHeight / texelHeight;
if (numCols == 0 || numRows == 0) if (numCols == 0 || numRows == 0)
{ {
ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1), "Texel size too large for atlas resolution."); ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1), "Texel size too large for atlas resolution.");
ImGui::Separator(); ImGui::Separator();
return;
} }
// Maintain aspect ratio // Maintain aspect ratio
float previewSize = ImGui::GetContentRegionAvail().x; float previewSize = ImGui::GetContentRegionAvail().x * 0.98;
float aspect = texHeight / (float)texWidth; float aspect = texHeight / (float)texWidth;
ImVec2 imageSize = ImVec2(previewSize, previewSize * aspect); ImVec2 imageSize(previewSize, previewSize * aspect);
ImVec2 imagePos = ImGui::GetCursorScreenPos(); ImVec2 imagePos = ImGui::GetCursorScreenPos();
// Draw the atlas
ImGui::Image(texID, imageSize); ImGui::Image(texID, imageSize);
// Grid scale (tile-to-preview size) // Grid cell size in pixels
float scaleX = imageSize.x / (float)texWidth; float scaleX = imageSize.x / (float)texWidth;
float scaleY = imageSize.y / (float)texHeight; float scaleY = imageSize.y / (float)texHeight;
float cellW = texelWidth * scaleX; float cellW = texelWidth * scaleX;
@ -513,66 +514,154 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
const ImU32 gridColor = IM_COL32(255, 255, 255, 48); const ImU32 gridColor = IM_COL32(255, 255, 255, 48);
int linesDrawn = 0; int linesDrawn = 0;
// Vertical lines // Vertical grid lines
for (int col = 0; col <= numCols; ++col) for (int col = 0; col <= numCols; ++col)
{ {
float x = imagePos.x + col * cellW; float x = imagePos.x + col * cellW;
if (x > imagePos.x + imageSize.x) if (x > imagePos.x + imageSize.x)
break; break;
drawList->AddLine(ImVec2(x, imagePos.y), ImVec2(x, imagePos.y + imageSize.y), gridColor); drawList->AddLine(
ImVec2(x, imagePos.y),
ImVec2(x, imagePos.y + imageSize.y),
gridColor);
linesDrawn++; linesDrawn++;
} }
// Horizontal lines // Horizontal grid lines
for (int row = 0; row <= numRows; ++row) for (int row = 0; row <= numRows; ++row)
{ {
float y = imagePos.y + row * cellH; float y = imagePos.y + row * cellH;
if (y > imagePos.y + imageSize.y) if (y > imagePos.y + imageSize.y)
break; break;
drawList->AddLine(ImVec2(imagePos.x, y), ImVec2(imagePos.x + imageSize.x, y), gridColor); drawList->AddLine(
ImVec2(imagePos.x, y),
ImVec2(imagePos.x + imageSize.x, y),
gridColor);
linesDrawn++; linesDrawn++;
} }
// --- Highlight tile under mouse --- // ─────── Hover & Selection State ───────
static bool selecting = false;
static bool hasSelection = false;
static int selStartX = 0, selStartY = 0, selEndX = 0, selEndY = 0;
ImVec2 mousePos = ImGui::GetMousePos(); ImVec2 mousePos = ImGui::GetMousePos();
bool mouseOver = ImGui::IsItemHovered(); bool mouseOver = ImGui::IsItemHovered();
// Convert mouse → tile coords
int tileX = (int)((mousePos.x - imagePos.x) / cellW);
int tileY = (int)((mousePos.y - imagePos.y) / cellH);
// ─ Hover highlight (yellow glow) ─
if (mouseOver && tileX >= 0 && tileX < numCols && tileY >= 0 && tileY < numRows)
{
ImVec2 min(
imagePos.x + tileX * cellW,
imagePos.y + tileY * cellH);
ImVec2 max(
min.x + cellW,
min.y + cellH);
drawList->AddRectFilled(min, max, IM_COL32(255, 255, 0, 64), 2.0f);
drawList->AddRect(min, max, IM_COL32(255, 255, 0, 128), 2.0f);
}
// ─ Dragtoselect & singleclick selection ─
if (mouseOver) if (mouseOver)
{ {
// Convert mouse position to tile coordinates if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
float localX = mousePos.x - imagePos.x;
float localY = mousePos.y - imagePos.y;
int tileX = (int)(localX / cellW);
int tileY = (int)(localY / cellH);
if (tileX >= 0 && tileX < numCols && tileY >= 0 && tileY < numRows)
{ {
float highlightX = imagePos.x + tileX * cellW; selecting = true;
float highlightY = imagePos.y + tileY * cellH; hasSelection = true;
selStartX = selEndX = tileX;
ImVec2 min = ImVec2(highlightX, highlightY); selStartY = selEndY = tileY;
ImVec2 max = ImVec2(highlightX + cellW, highlightY + cellH); }
if (selecting && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
const ImU32 glowColor = IM_COL32(255, 255, 0, 64); // translucent yellow {
drawList->AddRectFilled(min, max, glowColor, 2.0f); selEndX = tileX;
selEndY = tileY;
// Optional: Outline }
drawList->AddRect(min, max, IM_COL32(255, 255, 0, 128), 2.0f); if (selecting && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
{
ImGui::Text("Hovered Tile: (%d, %d)", tileX, tileY); selecting = false;
} }
} }
// Debug // ─ Draw selection rectangle ─
if (hasSelection)
{
int x0 = std::min(selStartX, selEndX);
int y0 = std::min(selStartY, selEndY);
int x1 = std::max(selStartX, selEndX);
int y1 = std::max(selStartY, selEndY);
ImVec2 selMin(
imagePos.x + x0 * cellW,
imagePos.y + y0 * cellH);
ImVec2 selMax(
imagePos.x + (x1 + 1) * cellW,
imagePos.y + (y1 + 1) * cellH);
drawList->AddRectFilled(selMin, selMax, IM_COL32(0, 255, 255, 32));
drawList->AddRect(selMin, selMax, IM_COL32(0, 255, 255, 128), 2.0f);
}
// ─ Hovertile preview ─
if (mouseOver && tileX >= 0 && tileX < numCols && tileY >= 0 && tileY < numRows)
{
ImGui::SeparatorText("Hovered Tile");
ImVec2 uv0(
tileX * (float)texelWidth / texWidth,
tileY * (float)texelHeight / texHeight);
ImVec2 uv1(
(tileX + 1) * (float)texelWidth / texWidth,
(tileY + 1) * (float)texelHeight / texHeight);
ImGui::Image(texID, ImVec2(64, 64), uv0, uv1);
}
else
{
ImGui::SeparatorText("Hovered Tile");
ImGui::Dummy(ImVec2(64, 64));
}
// ─ Selectionregion preview ─
if (hasSelection)
{
int x0 = std::min(selStartX, selEndX);
int y0 = std::min(selStartY, selEndY);
int x1 = std::max(selStartX, selEndX);
int y1 = std::max(selStartY, selEndY);
ImGui::SeparatorText("Selection Preview");
ImVec2 uv0(
x0 * (float)texelWidth / texWidth,
y0 * (float)texelHeight / texHeight);
ImVec2 uv1(
(x1 + 1) * (float)texelWidth / texWidth,
(y1 + 1) * (float)texelHeight / texHeight);
ImVec2 imgSz(
(x1 - x0 + 1) * (float)texelWidth * scaleX,
(y1 - y0 + 1) * (float)texelHeight * scaleY);
ImGui::Image(texID, imgSz, uv0, uv1);
}
// Debug info
ImGui::Text("Atlas Resolution: %d x %d", texWidth, texHeight); ImGui::Text("Atlas Resolution: %d x %d", texWidth, texHeight);
ImGui::Text("Tile Grid: %d x %d", numCols, numRows); if (mouseOver && tileX >= 0 && tileX < numCols && tileY >= 0 && tileY < numRows)
ImGui::Text("Grid Lines: %d", linesDrawn); {
ImGui::Text("Selected Tile: %d x %d (%d)", tileX, tileY, (tileX * tileY));
}
ImGui::Text("Tile Grid: %d x %d", numCols, numRows);
ImGui::Text("Grid Lines: %d", linesDrawn);
ImGui::Separator();
} }
ImGui::Separator(); ImGui::Separator();
if (ImGui::Button("Remove TilemapComponent")) if (ImGui::Button("Remove TilemapComponent"))
selected->RemoveComponent<TilemapComponent>(); selected->RemoveComponent<TilemapComponent>();
ImGui::Spacing();
} }
ImGui::End(); ImGui::End();

View File

@ -4,6 +4,9 @@
std::vector<std::shared_ptr<Object>> objects; std::vector<std::shared_ptr<Object>> objects;
std::string savedStateYAML; std::string savedStateYAML;
std::vector<std::shared_ptr<Object>> pendingDeletion;
std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag) { std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag) {
if (obj->GetName() == tag) if (obj->GetName() == tag)

View File

@ -6,5 +6,7 @@
extern std::vector<std::shared_ptr<Object>> objects; extern std::vector<std::shared_ptr<Object>> objects;
extern std::string savedStateYAML; extern std::string savedStateYAML;
extern std::vector<std::shared_ptr<Object>> pendingDeletion;
std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag); std::shared_ptr<Object> FindByTagRecursive(const std::shared_ptr<Object>& obj, const std::string& tag);

42
src/vendor/xxhash/xxhash.c vendored Normal file
View File

@ -0,0 +1,42 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2012-2023 Yann Collet
*
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* xxhash.c instantiates functions defined in xxhash.h
*/
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
#define XXH_IMPLEMENTATION /* access definitions */
#include "xxhash.h"

7343
src/vendor/xxhash/xxhash.h vendored Normal file

File diff suppressed because it is too large Load Diff