diff --git a/imgui.ini b/imgui.ini index 33240e3..f95f81e 100644 --- a/imgui.ini +++ b/imgui.ini @@ -10,24 +10,24 @@ Collapsed=1 [Window][WindowOverViewport_11111111] Pos=0,19 -Size=1920,1158 +Size=1280,701 Collapsed=0 [Window][Inspector] -Pos=1578,19 -Size=342,1158 +Pos=938,19 +Size=342,701 Collapsed=0 DockId=0x00000006,0 [Window][Scene Tree] Pos=0,19 -Size=342,575 +Size=342,348 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] Pos=344,19 -Size=1232,847 +Size=592,390 Collapsed=0 DockId=0x00000007,0 @@ -36,14 +36,14 @@ Size=1920,19 Collapsed=0 [Window][Performance Info] -Pos=0,19 -Size=342,575 +Pos=344,411 +Size=592,309 Collapsed=0 -DockId=0x00000003,1 +DockId=0x00000008,3 [Window][Console] -Pos=344,868 -Size=1232,309 +Pos=344,411 +Size=592,309 Collapsed=0 DockId=0x00000008,0 @@ -54,10 +54,10 @@ Collapsed=0 DockId=0x00000007,1 [Window][Profiler] -Pos=344,868 -Size=1232,309 +Pos=344,411 +Size=592,309 Collapsed=0 -DockId=0x00000008,1 +DockId=0x00000008,2 [Window][Profiler Timeline] Pos=265,69 @@ -78,25 +78,25 @@ Collapsed=0 DockId=0x00000008,1 [Window][Color Correction] -Pos=1588,867 -Size=332,310 +Pos=344,411 +Size=592,309 Collapsed=0 DockId=0x00000008,1 [Window][Asset Browser] -Pos=0,596 -Size=342,581 +Pos=0,369 +Size=342,351 Collapsed=0 DockId=0x00000004,0 [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=1576,1158 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59 - DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,575 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=1576,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=342,1158 Selected=0x36DC96AB + DockNode ID=0x00000006 Parent=0x11111111 SizeRef=342,1158 HiddenTabBar=1 Selected=0x36DC96AB diff --git a/remake/build.log b/remake/build.log index 261f46c..ee9679b 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,5 +1,2 @@ -[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\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 -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 [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\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] Runtime crash -Command 'src\build\app.exe' returned non-zero exit status 3221225477. +[RUN] Executed app.exe successfully. diff --git a/src/assets/lua/animation.lua b/src/assets/lua/animation.lua new file mode 100644 index 0000000..a0eaa9f --- /dev/null +++ b/src/assets/lua/animation.lua @@ -0,0 +1,25 @@ +-- EffectAnimation.lua + +-- cache references +local effectObj = nil +local anim = nil + +function OnInit() + effectObj = Engine.GetObjectByTag("Effect") + if effectObj then + anim = effectObj:GetComponent("AnimationComponent") + if anim then + anim:Play() + end + end +end + +function OnUpdate(dt) + if anim and Engine.KeyDown(Keycode.Space) then + + + anim:SetStartFrame(36) + anim:SetEndFrame(54) + anim:SetFrame(36) + end +end diff --git a/src/assets/scenes/lighting_test_2.cene b/src/assets/scenes/lighting_test_2.cene index 1bb5069..ca39956 100644 --- a/src/assets/scenes/lighting_test_2.cene +++ b/src/assets/scenes/lighting_test_2.cene @@ -253,39 +253,9 @@ color_correction: intensity: 0.200000003 threshold: 1.75999999 Assets: - - uaid: 1 - path: C:\Users\spenc\OneDrive\Pictures\textures\bark_willow_02_diff_1k.png - filename: bark_willow_02_diff_1k.png - filetype: png - type: 0 - size: [1024, 1024] - - uaid: 2 - path: C:\Users\spenc\OneDrive\Pictures\textures\bark_willow_02_nor_gl_1k.png - filename: bark_willow_02_nor_gl_1k.png - filetype: png - type: 0 - size: [1024, 1024] - - uaid: 3 - path: C:\Users\spenc\OneDrive\Pictures\textures\wood_floor_worn_diff_1k.png - filename: wood_floor_worn_diff_1k.png - filetype: png - type: 0 - size: [1024, 1024] - - uaid: 4 - path: C:\Users\spenc\OneDrive\Pictures\textures\wood_floor_worn_nor_gl_1k.png - filename: wood_floor_worn_nor_gl_1k.png - filetype: png - type: 0 - size: [1024, 1024] - - uaid: 5 - path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_nor_gl_1k.png - filename: ganges_river_pebbles_nor_gl_1k.png - filetype: png - type: 0 - size: [1024, 1024] - - uaid: 6 - path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_diff_1k.png - filename: ganges_river_pebbles_diff_1k.png + - uaid: 8 + path: C:\Users\spenc\OneDrive\Pictures\textures\metal_plate_nor_gl_1k.png + filename: metal_plate_nor_gl_1k.png filetype: png type: 0 size: [1024, 1024] @@ -295,9 +265,39 @@ Assets: filetype: png type: 0 size: [1024, 1024] - - uaid: 8 - path: C:\Users\spenc\OneDrive\Pictures\textures\metal_plate_nor_gl_1k.png - filename: metal_plate_nor_gl_1k.png + - uaid: 6 + path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_diff_1k.png + filename: ganges_river_pebbles_diff_1k.png + filetype: png + type: 0 + size: [1024, 1024] + - uaid: 5 + path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_nor_gl_1k.png + filename: ganges_river_pebbles_nor_gl_1k.png + filetype: png + type: 0 + size: [1024, 1024] + - uaid: 4 + path: C:\Users\spenc\OneDrive\Pictures\textures\wood_floor_worn_nor_gl_1k.png + filename: wood_floor_worn_nor_gl_1k.png + filetype: png + type: 0 + size: [1024, 1024] + - uaid: 3 + path: C:\Users\spenc\OneDrive\Pictures\textures\wood_floor_worn_diff_1k.png + filename: wood_floor_worn_diff_1k.png + filetype: png + type: 0 + size: [1024, 1024] + - uaid: 2 + path: C:\Users\spenc\OneDrive\Pictures\textures\bark_willow_02_nor_gl_1k.png + filename: bark_willow_02_nor_gl_1k.png + filetype: png + type: 0 + size: [1024, 1024] + - uaid: 1 + path: C:\Users\spenc\OneDrive\Pictures\textures\bark_willow_02_diff_1k.png + filename: bark_willow_02_diff_1k.png filetype: png type: 0 size: [1024, 1024] \ No newline at end of file diff --git a/src/src/Components/AnimationComponent.cpp b/src/src/Components/AnimationComponent.cpp index afb9efd..10700d3 100644 --- a/src/src/Components/AnimationComponent.cpp +++ b/src/src/Components/AnimationComponent.cpp @@ -49,17 +49,56 @@ void AnimationComponent::SetTextureAtlas(uint64_t uaid, int texelWidth, int texe startFrame = 0; endFrame = totalFrames > 0 ? totalFrames - 1 : 0; + + if (start != 0) + { + startFrame = start; + } + + if (end != 0) + { + endFrame = end; + } + frameDuration = duration; currentFrame = startFrame; renderType = RenderType::Unlit; } -void AnimationComponent::Play() { playing = true; } -void AnimationComponent::Stop() { playing = false; } -void AnimationComponent::SetLooping(bool l) { loop = l; } -void AnimationComponent::SetSpeed(float s) { speed = s; } -void AnimationComponent::SetFrame(int f) { currentFrame = std::clamp(f, startFrame, endFrame); } +void AnimationComponent::Play() { playing = true; } +void AnimationComponent::Stop() { playing = false; } +void AnimationComponent::SetLooping(bool loop_) { loop = loop_; } + +bool AnimationComponent::IsPlaying() const { return playing; } + +void AnimationComponent::SetPlaying(bool play) { playing = play; } + +uint64_t AnimationComponent::GetTextureUAID() const { return textureUAID; } + +void AnimationComponent::SetTextureUAID(uint64_t uaid) { textureUAID = uaid; } + +bool AnimationComponent::IsLooping() const { return loop; } +void AnimationComponent::SetSpeed(float speed_) { speed = speed_; } +float AnimationComponent::GetSpeed() const { return speed; } + +void AnimationComponent::SetFrame(int frame) +{ + currentFrame = std::clamp(frame, startFrame, endFrame); + time = 0.0f; +} +int AnimationComponent::GetCurrentFrame() const { return currentFrame; } +int AnimationComponent::GetStartFrame() const { return startFrame; } +void AnimationComponent::SetStartFrame(int start) { startFrame = std::clamp(start, 0, totalFrames - 1); } +int AnimationComponent::GetEndFrame() const { return endFrame; } +void AnimationComponent::SetEndFrame(int end) { endFrame = std::clamp(end, 0, totalFrames - 1); } +int AnimationComponent::GetTotalFrames() const { return totalFrames; } + +float AnimationComponent::GetFrameDuration() const { return frameDuration; } +void AnimationComponent::SetFrameDuration(float duration) { frameDuration = duration; } + +TextureAtlas* AnimationComponent::GetAtlas() { return &atlas; } +const TextureAtlas* AnimationComponent::GetAtlas() const { return &atlas; } void AnimationComponent::Update(float dt) { diff --git a/src/src/Components/AnimationComponent.h b/src/src/Components/AnimationComponent.h index 47cd3ed..25cd067 100644 --- a/src/src/Components/AnimationComponent.h +++ b/src/src/Components/AnimationComponent.h @@ -9,41 +9,65 @@ #include "../core/utils/AssetManager.h" #include "../core/utils/Logging.h" - class AnimationComponent : public Component { public: AnimationComponent(Object *owner); - void SetTextureAtlasPath(const std::string &path, int texelWidth, int texelHeight, float frameDuration, int startFrame = 0, int endFrame = INT_MAX); - void SetTextureAtlas(uint64_t uaid, int texelWidth, int texelHeight, float frameDuration, int startFrame = 0, int endFrame = INT_MAX); + // Initialize with texture atlas path or UAID + void SetTextureAtlasPath(const std::string &path, + int texelWidth, + int texelHeight, + float frameDuration, + int startFrame = 0, + int endFrame = INT_MAX); + void SetTextureAtlas(uint64_t uaid, + int texelWidth, + int texelHeight, + float frameDuration, + int startFrame = 0, + int endFrame = INT_MAX); + // Playback controls void Play(); void Stop(); void SetLooping(bool loop); + bool IsLooping() const; void SetSpeed(float speed); + float GetSpeed() const; + + void SetPlaying(bool play); + bool IsPlaying() const; + + // Frame controls void SetFrame(int frame); + int GetCurrentFrame() const; + int GetStartFrame() const; + void SetStartFrame(int start); + int GetEndFrame() const; + void SetEndFrame(int end); + int GetTotalFrames() const; - bool IsPlaying() const { return playing; } - bool IsLooping() const { return loop; } - float GetSpeed() const { return speed; } + // Texture UAID + uint64_t GetTextureUAID() const; + void SetTextureUAID(uint64_t uaid); - TextureAtlas *GetAtlas() { return &atlas; } - const TextureAtlas *GetAtlas() const { return &atlas; } + // Timing + float GetFrameDuration() const; + void SetFrameDuration(float duration); - int GetCurrentFrame() const { return currentFrame; } - - uint64_t GetTextureUAID() const { return textureUAID; } - float GetFrameDuration() const { return frameDuration; } + // Access atlas + TextureAtlas* GetAtlas(); + const TextureAtlas* GetAtlas() const; + // Update per tick void Update(float dt); + // Component overrides std::string GetName() const override; void Save(YAML::Emitter &out) const override; void Load(const YAML::Node &node) override; - - RenderType renderType; private: @@ -60,6 +84,7 @@ private: float frameDuration = 0.1f; float time = 0.0f; int currentFrame = 0; + bool playing = true; bool loop = true; float speed = 1.0f; diff --git a/src/src/Components/ScriptComponent.cpp b/src/src/Components/ScriptComponent.cpp index f89059a..a2db59a 100644 --- a/src/src/Components/ScriptComponent.cpp +++ b/src/src/Components/ScriptComponent.cpp @@ -9,15 +9,14 @@ #include "../Components/LightComponent.h" #include "../Components/TextComponent.h" #include "../Components/TilemapComponent.h" +#include "../Components/AnimationComponent.h" #include "../core/utils/Profiler.h" #include "../core/utils/utils.h" #include "../core/utils/keycode.h" #include "../core/utils/input.h" -#include "../core/types/vec2.h" - - +#include "../core/types/vec2.h" #include #include @@ -26,13 +25,10 @@ static bool luaDebugEnabled = false; static bool old_state = false; - - -#define SET_KC(name) \ +#define SET_KC(name) \ lua_pushinteger(L, static_cast(Keycode::name)); \ lua_setfield(L, -2, #name); - struct LuaObjectWrapper { Object *obj; @@ -45,6 +41,13 @@ struct LuaVector2 }; #define LUA_VECTOR2_MT "LuaVector2Meta" +#define LUA_ANIMATION_MT "LuaAnimationMeta" + +struct LuaAnimationWrapper +{ + AnimationComponent *comp; +}; + ScriptComponent::ScriptComponent(Object *owner) : Component(owner), L(nullptr) {} ScriptComponent::~ScriptComponent() { @@ -145,22 +148,25 @@ static Component *GetComponentByName(Object *obj, const std::string &type) return obj->GetComponent().get(); if (type == "ScriptComponent") return obj->GetComponent().get(); + if (type == "AnimationComponent") + return obj->GetComponent().get(); return nullptr; } + static int Lua_GetMousePos(lua_State *L) { PROFILE_DEEP_SCOPE("Engine::GetMousePos"); - + core::types::Vec2 m = Input::GetMousePosition(); - - LuaVector2* vec = (LuaVector2*)lua_newuserdata(L, sizeof(LuaVector2)); + + LuaVector2 *vec = (LuaVector2 *)lua_newuserdata(L, sizeof(LuaVector2)); vec->x = m.x; vec->y = m.y; - + luaL_getmetatable(L, LUA_VECTOR2_MT); lua_setmetatable(L, -2); - + return 1; } @@ -169,6 +175,21 @@ static int Lua_Object_GetComponent(lua_State *L) PROFILE_DEEP_SCOPE("Object::GetComponent"); auto *wrapper = (LuaObjectWrapper *)luaL_checkudata(L, 1, LUA_OBJECT_MT); const char *type = luaL_checkstring(L, 2); + if (strcmp(type, "AnimationComponent") == 0) + { + auto compPtr = wrapper->obj->GetComponent(); + if (compPtr) + { + LuaAnimationWrapper *aw = (LuaAnimationWrapper *)lua_newuserdata(L, sizeof(LuaAnimationWrapper)); + aw->comp = compPtr.get(); + luaL_getmetatable(L, LUA_ANIMATION_MT); + lua_setmetatable(L, -2); + return 1; + } + lua_pushnil(L); + return 1; + } + // fallback for other components Component *comp = GetComponentByName(wrapper->obj, type); lua_pushlightuserdata(L, comp ? comp : nullptr); return 1; @@ -247,9 +268,95 @@ static int Lua_GetObjectByTag(lua_State *L) return 1; } +// --- AnimationComponent Lua bindings --- +static AnimationComponent *CheckAnimationComponent(lua_State *L, int idx) +{ + void *ptr = lua_touserdata(L, idx); + return static_cast(ptr); +} + +static int Lua_Animation_GetCurrentFrame(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::GetCurrentFrame"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + lua_pushinteger(L, anim ? anim->GetCurrentFrame() : -1); + return 1; +} + +static int Lua_Animation_SetCurrentFrame(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::SetCurrentFrame"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + int frame = luaL_checkinteger(L, 2); + if (anim) + anim->SetFrame(frame); + return 0; +} + +static int Lua_Animation_IsPlaying(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::IsPlaying"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + lua_pushboolean(L, anim ? anim->IsPlaying() : false); + return 1; +} + +static int Lua_Animation_SetPlaying(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::SetPlaying"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + bool play = lua_toboolean(L, 2); + if (anim) + anim->SetPlaying(play); + return 0; +} + +static int Lua_Animation_GetStartFrame(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::GetStartFrame"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + lua_pushinteger(L, anim ? anim->GetStartFrame() : 0); + return 1; +} + +static int Lua_Animation_SetStartFrame(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::SetStartFrame"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + int start = luaL_checkinteger(L, 2); + if (anim) + anim->SetStartFrame(start); + return 0; +} + +static int Lua_Animation_GetEndFrame(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::GetEndFrame"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + lua_pushinteger(L, anim ? anim->GetEndFrame() : 0); + return 1; +} + +static int Lua_Animation_SetEndFrame(lua_State *L) +{ + PROFILE_DEEP_SCOPE("Animation::SetEndFrame"); + AnimationComponent *anim = CheckAnimationComponent(L, 1); + int end = luaL_checkinteger(L, 2); + if (anim) + anim->SetEndFrame(end); + return 0; +} +static int Lua_Animation_Index(lua_State *L) +{ + // stack: [1]=userdata, [2]=key + luaL_getmetatable(L, LUA_ANIMATION_MT); + lua_pushvalue(L, 2); + lua_rawget(L, -2); + return 1; +} static int keycode_loader(lua_State *L) { @@ -383,20 +490,13 @@ static int keycode_loader(lua_State *L) SET_KC(RightSuper) SET_KC(Menu) - #undef SET_KC +#undef SET_KC lua_setglobal(L, "Keycode"); - return 1; } - - - - - - static int Lua_KeyDown(lua_State *L) { // match your other deep‐profile scopes @@ -413,7 +513,6 @@ static int Lua_KeyDown(lua_State *L) return 1; } - static int Lua_Vector2_New(lua_State *L) { PROFILE_DEEP_SCOPE("Vector2()"); @@ -482,6 +581,35 @@ void RegisterVector2Type(lua_State *L) lua_setglobal(L, "Vector2"); } +// Register the AnimationComponent metatable +void RegisterAnimationType(lua_State *L) +{ + PROFILE_DEEP_SCOPE("RegisterAnimationType"); + luaL_newmetatable(L, LUA_ANIMATION_MT); + // methods + lua_pushcfunction(L, Lua_Animation_GetCurrentFrame); + lua_setfield(L, -2, "GetCurrentFrame"); + lua_pushcfunction(L, Lua_Animation_SetCurrentFrame); + lua_setfield(L, -2, "SetCurrentFrame"); + lua_pushcfunction(L, Lua_Animation_IsPlaying); + lua_setfield(L, -2, "IsPlaying"); + lua_pushcfunction(L, Lua_Animation_SetPlaying); + lua_setfield(L, -2, "SetPlaying"); + lua_pushcfunction(L, Lua_Animation_GetStartFrame); + lua_setfield(L, -2, "GetStartFrame"); + lua_pushcfunction(L, Lua_Animation_SetStartFrame); + lua_setfield(L, -2, "SetStartFrame"); + lua_pushcfunction(L, Lua_Animation_GetEndFrame); + lua_setfield(L, -2, "GetEndFrame"); + lua_pushcfunction(L, Lua_Animation_SetEndFrame); + lua_setfield(L, -2, "SetEndFrame"); + + // __index + lua_pushcfunction(L, Lua_Animation_Index); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +} + void ScriptComponent::RegisterEngineBindings() { PROFILE_DEEP_SCOPE("RegisterEngineBindings"); @@ -500,12 +628,12 @@ void ScriptComponent::RegisterEngineBindings() lua_pushcfunction(L, Lua_KeyDown); lua_setfield(L, -2, "KeyDown"); - lua_pushcfunction(L, Lua_GetMousePos); lua_setfield(L, -2, "GetMousePos"); lua_setglobal(L, "Engine"); + } void ScriptComponent::ReloadScript() @@ -523,9 +651,10 @@ void ScriptComponent::ReloadScript() RegisterObjectType(L); RegisterVector2Type(L); + RegisterAnimationType(L); RegisterEngineBindings(); - keycode_loader(L); + keycode_loader(L); Logger::LogVerbose("[Lua] Loading Script from file."); if (luaL_dofile(L, scriptPath.c_str())) diff --git a/src/src/Components/SpriteComponent.cpp b/src/src/Components/SpriteComponent.cpp index 6cac848..762df24 100644 --- a/src/src/Components/SpriteComponent.cpp +++ b/src/src/Components/SpriteComponent.cpp @@ -1,10 +1,10 @@ #include "SpriteComponent.h" #include "../core/utils/AssetManager.h" #include "../core/utils/Logging.h" - - #include + + SpriteComponent::SpriteComponent(Object *owner) : Component(owner) {} bool SpriteComponent::HasTexture() @@ -12,6 +12,8 @@ bool SpriteComponent::HasTexture() return texture_loaded; } + + void SpriteComponent::SetTexture(const std::string &path) { if (path.empty()) return; @@ -22,6 +24,8 @@ void SpriteComponent::SetTexture(const std::string &path) SetTexture(asset->uaid); } + + void SpriteComponent::SetNormalMap(const std::string &path) { if (path.empty()) return; @@ -32,6 +36,8 @@ void SpriteComponent::SetNormalMap(const std::string &path) SetNormalMap(asset->uaid); } + + void SpriteComponent::SetTexture(uint64_t uaid) { textureUAID = uaid; @@ -44,6 +50,8 @@ void SpriteComponent::SetTexture(uint64_t uaid) } } + + void SpriteComponent::SetNormalMap(uint64_t uaid) { normalMapUAID = uaid; @@ -54,26 +62,36 @@ void SpriteComponent::SetNormalMap(uint64_t uaid) } } + + unsigned int SpriteComponent::GetTextureID() const { return textureID; } + + unsigned int SpriteComponent::GetNormalMapID() const { return normalMapID; } + + uint64_t SpriteComponent::GetTextureUAID() const { return textureUAID; } + + uint64_t SpriteComponent::GetNormalMapUAID() const { return normalMapUAID; } + + void SpriteComponent::Save(YAML::Emitter &out) const { out << YAML::BeginMap; @@ -84,6 +102,8 @@ void SpriteComponent::Save(YAML::Emitter &out) const out << YAML::EndMap; } + + void SpriteComponent::Load(const YAML::Node& node) { try { diff --git a/src/src/core/utils/AssetManager.cpp b/src/src/core/utils/AssetManager.cpp index dd67072..3d6c2b5 100644 --- a/src/src/core/utils/AssetManager.cpp +++ b/src/src/core/utils/AssetManager.cpp @@ -1,85 +1,58 @@ +// AssetManager.cpp #include "AssetManager.h" #include "utils.h" -#include "../../Renderer.h" +#include #define STB_IMAGE_IMPLEMENTATION #include +#include -#include -#include -#include -#include // for std::hash - +// Static definitions std::unordered_map AssetManager::s_Assets; - +std::unordered_map AssetManager::s_PathToUAID; std::mutex AssetManager::s_Mutex; uint64_t AssetManager::s_NextUAID = 1; -inline static std::unordered_map s_PathToUAID; - -inline std::string GetFileExtension(const std::string &path) -{ - size_t dot = path.find_last_of('.'); - if (dot == std::string::npos) - return ""; - return path.substr(dot + 1); -} - -inline GLuint CreateOpenGLTexture(unsigned char *data, int width, int height) -{ - GLuint tex; - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glBindTexture(GL_TEXTURE_2D, 0); - return tex; -} - void AssetManager::Init() {} uint64_t AssetManager::GenerateUAID() { std::lock_guard lock(s_Mutex); - - static std::random_device rd; - static std::mt19937 gen(rd()); - static std::uniform_int_distribution dist(0, 9); - - std::string digits; - digits.reserve(32); - for (int i = 0; i < 32; ++i) - digits += static_cast('0' + dist(gen)); - - return std::hash{}(digits); + return s_NextUAID++; } void AssetManager::LoadAssetAsync(const std::string &path, AssetType type) { - uint64_t uaid = GenerateUAID(); - - AssetInfo info; - info.uaid = uaid; - info.path = path; - info.filename = GetFilenameFromPath(path); - info.filetype = GetFileExtension(path); - info.type = type; - { + std::lock_guard lock(s_Mutex); + auto itPath = s_PathToUAID.find(path); + if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded) + { + Logger::LogVerbose("[AssetManager] Skipping already-loaded image: %s (UAID: %llu)", path.c_str(), itPath->second); + return; + } + } + + uint64_t uaid = GenerateUAID(); + { + AssetInfo info; + info.uaid = uaid; + info.path = path; + info.filename = GetFilenameFromPath(path); + info.filetype = ::GetFileExtension(path); + info.type = type; std::lock_guard lock(s_Mutex); s_Assets[uaid] = info; + s_PathToUAID[path] = uaid; } if (type == AssetType::Image) { - Logger::LogVerbose("[AssetManager] Loading image: %s (UAID: %llu)", path.c_str(), uaid); - LoadImageInternal(path, uaid); + Logger::LogVerbose("[AssetManager] Scheduling load: %s (UAID: %llu)", path.c_str(), uaid); + AssetManager::LoadImageInternal(path, uaid); } else { - Logger::LogWarning("Unknown Asset Type: '%d'", type); + Logger::LogWarning("[AssetManager] Unknown Asset Type: '%d'", static_cast(type)); } } @@ -87,22 +60,16 @@ void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid) { { std::lock_guard lock(s_Mutex); - auto it = s_PathToUAID.find(path); - if (it != s_PathToUAID.end()) - { - const auto &asset = s_Assets[it->second]; - if (asset.loaded) - { - Logger::LogVerbose("[AssetManager] Skipping already loaded asset: %s (UAID: %llu)", path.c_str(), asset.uaid); - return; - } - } + auto it = s_Assets.find(uaid); + if (it != s_Assets.end() && it->second.loaded) + return; + auto itPath = s_PathToUAID.find(path); + if (itPath != s_PathToUAID.end() && s_Assets[itPath->second].loaded) + return; } Logger::LogVerbose("[AssetManager] Begin loading image: %s (UAID: %llu)", path.c_str(), uaid); - stbi_set_flip_vertically_on_load(false); - int w, h, channels; stbi_uc *pixels = stbi_load(path.c_str(), &w, &h, &channels, STBI_rgb_alpha); if (!pixels) @@ -111,50 +78,50 @@ void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid) return; } - GLuint texID = CreateOpenGLTexture(pixels, w, h); + GLuint texID; + glGenTextures(1, &texID); + glBindTexture(GL_TEXTURE_2D, texID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + glBindTexture(GL_TEXTURE_2D, 0); stbi_image_free(pixels); + if (texID == 0) + { + Logger::LogError("[AssetManager] Failed to Load asset."); + return; + } { std::lock_guard lock(s_Mutex); - auto &asset = s_Assets[uaid]; - asset.path = path; - asset.filename = GetFilenameFromPath(path); - asset.filetype = GetFileExtension(path); - asset.size = {(float)w, (float)h}; + asset.size = {static_cast(w), static_cast(h)}; asset.textureID = texID; - asset.type = AssetType::Image; asset.loaded = true; } - { - std::lock_guard lock(s_Mutex); - s_PathToUAID[path] = uaid; - } - - 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) { std::lock_guard lock(s_Mutex); 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) { std::lock_guard lock(s_Mutex); - for (const auto &[id, asset] : s_Assets) - if (asset.path == path) - return &asset; - return nullptr; + auto it = s_PathToUAID.find(path); + return it != s_PathToUAID.end() ? &s_Assets[it->second] : nullptr; } const std::unordered_map &AssetManager::GetAllAssets() { - return s_Assets; // Assume read-only external usage + return s_Assets; } void AssetManager::UnloadAsset(uint64_t uaid) @@ -165,43 +132,37 @@ void AssetManager::UnloadAsset(uint64_t uaid) { if (it->second.textureID) glDeleteTextures(1, &it->second.textureID); - s_Assets.erase(it); s_PathToUAID.erase(it->second.path); - + s_Assets.erase(it); } } void AssetManager::ClearAllAssets() { std::lock_guard lock(s_Mutex); - for (auto &[id, asset] : s_Assets) - { - if (asset.textureID) - glDeleteTextures(1, &asset.textureID); - } + for (auto &kv : s_Assets) + if (kv.second.textureID) + glDeleteTextures(1, &kv.second.textureID); s_Assets.clear(); s_PathToUAID.clear(); - } void AssetManager::Save(YAML::Emitter &out) { std::lock_guard lock(s_Mutex); - out << YAML::Key << "Assets"; - out << YAML::BeginSeq; - - for (const auto &[uaid, asset] : s_Assets) + out << YAML::Key << "Assets" << YAML::BeginSeq; + for (const auto &kv : s_Assets) { - out << YAML::BeginMap; - out << YAML::Key << "uaid" << YAML::Value << asset.uaid; - out << YAML::Key << "path" << YAML::Value << asset.path; - out << YAML::Key << "filename" << YAML::Value << asset.filename; - out << YAML::Key << "filetype" << YAML::Value << asset.filetype; - out << YAML::Key << "type" << YAML::Value << static_cast(asset.type); - out << YAML::Key << "size" << YAML::Value << YAML::Flow << YAML::BeginSeq << asset.size.x << asset.size.y << YAML::EndSeq; - out << YAML::EndMap; + const auto &a = kv.second; + out << YAML::BeginMap + << YAML::Key << "uaid" << YAML::Value << a.uaid + << YAML::Key << "path" << YAML::Value << a.path + << YAML::Key << "filename" << YAML::Value << a.filename + << YAML::Key << "filetype" << YAML::Value << a.filetype + << YAML::Key << "type" << YAML::Value << static_cast(a.type) + << YAML::Key << "size" << YAML::Value << YAML::Flow << YAML::BeginSeq << a.size.x << a.size.y << YAML::EndSeq + << YAML::EndMap; } - out << YAML::EndSeq; } @@ -209,35 +170,43 @@ void AssetManager::Load(const YAML::Node &node) { if (!node) return; - for (const auto &item : node) { - AssetInfo asset; - asset.uaid = item["uaid"].as(); - asset.path = item["path"].as(); - asset.filename = item["filename"].as(); - asset.filetype = item["filetype"].as(); - asset.type = static_cast(item["type"].as()); - - const auto &size = item["size"]; - asset.size = {size[0].as(), size[1].as()}; - asset.loaded = false; + uint64_t uaid = item["uaid"].as(); + std::string path = item["path"].as(); + AssetType type = static_cast(item["type"].as()); + float sx = item["size"][0].as(); + float sy = item["size"][1].as(); + bool already = false; { std::lock_guard lock(s_Mutex); - s_Assets[asset.uaid] = asset; - if (asset.uaid >= s_NextUAID) - s_NextUAID = asset.uaid + 1; + auto it = s_Assets.find(uaid); + if (it != s_Assets.end() && it->second.loaded) + { + already = true; + } + else + { + AssetInfo asset; + asset.uaid = uaid; + asset.path = path; + asset.filename = GetFilenameFromPath(path); + asset.filetype = ::GetFileExtension(path); + asset.type = type; + asset.size = {sx, sy}; + asset.loaded = false; + asset.textureID = 0; + s_Assets[uaid] = asset; + s_PathToUAID[path] = uaid; + if (uaid >= s_NextUAID) + s_NextUAID = uaid + 1; + } } - - if (asset.type == AssetType::Image) + if (!already && type == AssetType::Image) { - Logger::LogVerbose("[AssetManager] Reloading from file: %s (UAID: %llu)", asset.path.c_str(), asset.uaid); - LoadImageInternal(asset.path, asset.uaid); - } - else - { - Logger::LogWarning("Unknown Asset Type: '%d'", asset.type); + Logger::LogVerbose("[AssetManager] Reloading from file: %s (UAID: %llu)", path.c_str(), uaid); + LoadImageInternal(path, uaid); } } } diff --git a/src/src/core/utils/AssetManager.h b/src/src/core/utils/AssetManager.h index 4226b5b..5895b15 100644 --- a/src/src/core/utils/AssetManager.h +++ b/src/src/core/utils/AssetManager.h @@ -42,6 +42,7 @@ public: private: static std::unordered_map s_Assets; + static std::unordered_map s_PathToUAID; static std::mutex s_Mutex; static uint64_t s_NextUAID; diff --git a/src/src/core/utils/utils.h b/src/src/core/utils/utils.h index fc279ac..88d34d2 100644 --- a/src/src/core/utils/utils.h +++ b/src/src/core/utils/utils.h @@ -58,4 +58,12 @@ inline glm::vec3 HSVtoRGB(float h, float s, float v) } return glm::vec3(r, g, b); +} + +inline std::string GetFileExtension(const std::string &path) +{ + size_t dot = path.find_last_of('.'); + if (dot == std::string::npos) + return ""; + return path.substr(dot + 1); } \ No newline at end of file