Added Lua Bindings for Animations

This commit is contained in:
OusmBlueNinja 2025-04-23 11:42:08 -05:00
parent 3dd28fe3a6
commit 9ddfa06bd9
11 changed files with 446 additions and 233 deletions

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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]

View File

@ -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)
{

View File

@ -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;

View File

@ -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 <lua.hpp>
#include <memory>
@ -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<int>(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<TextComponent>().get();
if (type == "ScriptComponent")
return obj->GetComponent<ScriptComponent>().get();
if (type == "AnimationComponent")
return obj->GetComponent<AnimationComponent>().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<AnimationComponent>();
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<AnimationComponent *>(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 deepprofile 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()))

View File

@ -1,10 +1,10 @@
#include "SpriteComponent.h"
#include "../core/utils/AssetManager.h"
#include "../core/utils/Logging.h"
#include <GL/glew.h>
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 {

View File

@ -1,85 +1,58 @@
// AssetManager.cpp
#include "AssetManager.h"
#include "utils.h"
#include "../../Renderer.h"
#include <GL/glew.h>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include <future>
#include <string>
#include <random>
#include <mutex>
#include <functional> // for std::hash
// Static definitions
std::unordered_map<uint64_t, AssetInfo> AssetManager::s_Assets;
std::unordered_map<std::string, uint64_t> AssetManager::s_PathToUAID;
std::mutex AssetManager::s_Mutex;
uint64_t AssetManager::s_NextUAID = 1;
inline static std::unordered_map<std::string, uint64_t> 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<std::mutex> lock(s_Mutex);
static std::random_device rd;
static std::mt19937 gen(rd());
static std::uniform_int_distribution<int> dist(0, 9);
std::string digits;
digits.reserve(32);
for (int i = 0; i < 32; ++i)
digits += static_cast<char>('0' + dist(gen));
return std::hash<std::string>{}(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<std::mutex> 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<std::mutex> 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<int>(type));
}
}
@ -87,22 +60,16 @@ void AssetManager::LoadImageInternal(const std::string &path, uint64_t uaid)
{
{
std::lock_guard<std::mutex> 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<std::mutex> 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<float>(w), static_cast<float>(h)};
asset.textureID = texID;
asset.type = AssetType::Image;
asset.loaded = true;
}
{
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<uint64_t, AssetInfo> &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<std::mutex> 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<std::mutex> 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<int>(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<int>(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<uint64_t>();
asset.path = item["path"].as<std::string>();
asset.filename = item["filename"].as<std::string>();
asset.filetype = item["filetype"].as<std::string>();
asset.type = static_cast<AssetType>(item["type"].as<int>());
const auto &size = item["size"];
asset.size = {size[0].as<float>(), size[1].as<float>()};
asset.loaded = false;
uint64_t uaid = item["uaid"].as<uint64_t>();
std::string path = item["path"].as<std::string>();
AssetType type = static_cast<AssetType>(item["type"].as<int>());
float sx = item["size"][0].as<float>();
float sy = item["size"][1].as<float>();
bool already = false;
{
std::lock_guard<std::mutex> 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);
}
}
}

View File

@ -42,6 +42,7 @@ public:
private:
static std::unordered_map<uint64_t, AssetInfo> s_Assets;
static std::unordered_map<std::string, uint64_t> s_PathToUAID;
static std::mutex s_Mutex;
static uint64_t s_NextUAID;

View File

@ -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);
}