From 346dd89a8136f8919cded2e3b8d5f9c4f4a98744 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 01/19] add git submodules & add cmake script --- .gitmodules | 3 +++ LuaSTG/Core.cmake | 2 ++ external/CMakeLists.txt | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/.gitmodules b/.gitmodules index 2d582f48..1a8a54f9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "external/beautiful-win32-api"] path = external/beautiful-win32-api url = https://github.com/Demonese/beautiful-win32-api +[submodule "external/spine-runtimes"] + path = external/spine-runtimes + url = https://github.com/EsotericSoftware/spine-runtimes.git diff --git a/LuaSTG/Core.cmake b/LuaSTG/Core.cmake index 2167d58c..30548ffc 100644 --- a/LuaSTG/Core.cmake +++ b/LuaSTG/Core.cmake @@ -111,6 +111,8 @@ target_link_libraries(Core PUBLIC Freetype::Freetype # model tinygltf + # spine + spine-cpp # audio dr_libs Ogg::ogg diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index bcbdb632..6aac3dcc 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -140,6 +140,24 @@ target_sources(libqoi PRIVATE set_target_properties(libqoi PROPERTIES FOLDER external) +# ==================== spine-cpp ==================== + +add_library(spine-cpp STATIC) +target_compile_definitions(spine-cpp PRIVATE + _CRT_SECURE_NO_WARNINGS +) +target_include_directories(spine-cpp PUBLIC + spine-runtimes/spine-cpp/spine-cpp/include +) + +file(GLOB SPINE_INCLUDES "spine-runtimes/spine-cpp/spine-cpp/include/**/*.h") +file(GLOB SPINE_SOURCES "spine-runtimes/spine-cpp/spine-cpp/src/**/*.cpp") + +target_sources(spine-cpp PRIVATE +# ${SPINE_INCLUDES} + ${SPINE_SOURCES} +) + # ==================== steam api ==================== add_subdirectory(steam_api) From 4c5ae4d2456dd1a0d5290671c0a549d3b756bf45 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 02/19] add missing files --- external/spine-runtimes | 1 + 1 file changed, 1 insertion(+) create mode 160000 external/spine-runtimes diff --git a/external/spine-runtimes b/external/spine-runtimes new file mode 160000 index 00000000..36535405 --- /dev/null +++ b/external/spine-runtimes @@ -0,0 +1 @@ +Subproject commit 3653540558ba09104065addc56178dc2bceafc24 From 8ef1f5c7f5db06c69dbf0fde2e78bb44aa64c913 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 03/19] modify cmake script --- external/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 6aac3dcc..b632ce31 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -154,10 +154,12 @@ file(GLOB SPINE_INCLUDES "spine-runtimes/spine-cpp/spine-cpp/include/**/*.h") file(GLOB SPINE_SOURCES "spine-runtimes/spine-cpp/spine-cpp/src/**/*.cpp") target_sources(spine-cpp PRIVATE -# ${SPINE_INCLUDES} + ${SPINE_INCLUDES} ${SPINE_SOURCES} ) +set_target_properties(spine-cpp PROPERTIES FOLDER external) + # ==================== steam api ==================== add_subdirectory(steam_api) From 0d16cda0b6b2e93a6e521761dd4e085e11bbe277 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 04/19] add placeholders --- .../Implement/ResourceSpineImpl.cpp | 7 +++++++ .../Implement/ResourceSpineImpl.hpp | 11 +++++++++++ LuaSTG/LuaSTG/GameResource/ResourceBase.hpp | 1 + LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp | 18 ++++++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp create mode 100644 LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp create mode 100644 LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp new file mode 100644 index 00000000..a72cecb1 --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp @@ -0,0 +1,7 @@ +#include "GameResource/Implement/ResourceSpineImpl.hpp" +#include "AppFrame.h" + +namespace luastg +{ + +} diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp new file mode 100644 index 00000000..e4a89d9b --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "GameResource/ResourceSpine.hpp" +#include "GameResource/Implement/ResourceBaseImpl.hpp" + +namespace luastg +{ + class ResourceSpineImpl : public ResourceBaseImpl + { + + }; +} diff --git a/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp b/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp index 24922e86..0cdd8f93 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp @@ -14,6 +14,7 @@ namespace luastg { TrueTypeFont, FX, Model, + Spine, }; // 混合模式 diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp new file mode 100644 index 00000000..450dd963 --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp @@ -0,0 +1,18 @@ +#pragma once +#include "GameResource/ResourceBase.hpp" +#include "spine/Extension.h" + +namespace luastg +{ + struct IResourceSpine : public IResourceBase + { + + }; +} + +namespace core { + // UUID v5 + // ns:URL + // https://www.luastg-sub.com/luastg.IResourceSpine + template<> constexpr InterfaceId getInterfaceId() { return UUID::parse("8f0a4281-6b0e-5db5-8cf4-2315eedf0c0f"); } +} From 42ad7fb7cf2d2a5b3ba079ac557f8f483106694a Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 05/19] basic connectors --- LuaSTG/CMakeLists.txt | 3 + .../Implement/ResourceSpineImpl.cpp | 55 ++++++++++++++++- .../Implement/ResourceSpineImpl.hpp | 34 +++++++++++ LuaSTG/LuaSTG/GameResource/ResourceManager.h | 7 ++- LuaSTG/LuaSTG/GameResource/ResourcePool.cpp | 61 +++++++++++++++++-- LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp | 1 - 6 files changed, 152 insertions(+), 9 deletions(-) diff --git a/LuaSTG/CMakeLists.txt b/LuaSTG/CMakeLists.txt index d8af4518..b4b0cb53 100644 --- a/LuaSTG/CMakeLists.txt +++ b/LuaSTG/CMakeLists.txt @@ -45,6 +45,7 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/GameResource/ResourceBase.hpp LuaSTG/GameResource/ResourceTexture.hpp LuaSTG/GameResource/ResourceSprite.hpp + LuaSTG/GameResource/ResourceSpine.hpp LuaSTG/GameResource/ResourceAnimation.hpp LuaSTG/GameResource/ResourceMusic.hpp LuaSTG/GameResource/ResourceSoundEffect.hpp @@ -66,6 +67,8 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/GameResource/Implement/ResourceTextureImpl.cpp LuaSTG/GameResource/Implement/ResourceSpriteImpl.hpp LuaSTG/GameResource/Implement/ResourceSpriteImpl.cpp + LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp + LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp LuaSTG/GameResource/Implement/ResourceAnimationImpl.hpp LuaSTG/GameResource/Implement/ResourceAnimationImpl.cpp LuaSTG/GameResource/Implement/ResourceMusicImpl.hpp diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp index a72cecb1..404a83d4 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp @@ -1,7 +1,60 @@ #include "GameResource/Implement/ResourceSpineImpl.hpp" #include "AppFrame.h" +#include "Core/FileSystem.hpp" namespace luastg { - + ResourceSpineImpl::ResourceSpineImpl(const char* name, const char* path) + : ResourceBaseImpl(ResourceType::Spine, name) + { + + } } + +namespace spine +{ + LuaSTGAtlasAttachmentLoader::LuaSTGAtlasAttachmentLoader(Atlas* atlas) : AtlasAttachmentLoader(atlas) {} + LuaSTGAtlasAttachmentLoader::~LuaSTGAtlasAttachmentLoader() {} + void LuaSTGAtlasAttachmentLoader::configureAttachment(Attachment* attachment) {} + + LuaSTGTextureLoader::LuaSTGTextureLoader() : TextureLoader() {} + LuaSTGTextureLoader::~LuaSTGTextureLoader() {} + void LuaSTGTextureLoader::load(AtlasPage& page, const spine::String& path) + { + core::Graphics::ITexture2D* p_texture; + if (!LAPP.GetAppModel()->getDevice()->createTextureFromFile(path.buffer(), true, &p_texture)) + { + spdlog::error("[luastg] 从 '{}' 创建Spine纹理失败", path.buffer()); + return; + } + + p_texture->retain(); + auto [w, h] = p_texture->getSize(); + + page.texture = p_texture; + page.width = w; + page.height = h; + } + void LuaSTGTextureLoader::unload(void* texture) + { + if (!texture) return; + core::Graphics::ITexture2D* p_texture = (core::Graphics::ITexture2D*)texture; + p_texture->release(); + } + + LuaSTGExtension::LuaSTGExtension() : DefaultSpineExtension() {} + + LuaSTGExtension::~LuaSTGExtension() {} + + char* LuaSTGExtension::_readFile(const spine::String& path, int* length) { + core::IData* data; + if(!core::FileSystemManager::readFile(path.buffer(), &data)) return nullptr; + + *length = static_cast(data->size()); + char* bytes = SpineExtension::alloc(*length, __FILE__, __LINE__); + std::memcpy(bytes, data->data(), *length); + return bytes; + } + + SpineExtension* spine::getDefaultExtension() { return new LuaSTGExtension(); } +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp index e4a89d9b..71650f71 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp @@ -1,11 +1,45 @@ #pragma once #include "GameResource/ResourceSpine.hpp" #include "GameResource/Implement/ResourceBaseImpl.hpp" +#include namespace luastg { class ResourceSpineImpl : public ResourceBaseImpl { + private: + public: + ResourceSpineImpl(const char* name, const char* path); }; } + +namespace spine +{ + class LuaSTGAtlasAttachmentLoader : public AtlasAttachmentLoader + { + public: + LuaSTGAtlasAttachmentLoader(Atlas *atlas); + virtual ~LuaSTGAtlasAttachmentLoader(); + virtual void configureAttachment(Attachment *attachment); + }; + + class LuaSTGTextureLoader : public TextureLoader + { + public: + LuaSTGTextureLoader(); + virtual ~LuaSTGTextureLoader(); + virtual void load(AtlasPage &page, const String &path); + virtual void unload(void *texture); + }; + + class LuaSTGExtension : public DefaultSpineExtension + { + public: + LuaSTGExtension(); + virtual ~LuaSTGExtension(); + + protected: + virtual char *_readFile(const String &path, int *length); + }; +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.h b/LuaSTG/LuaSTG/GameResource/ResourceManager.h index 431926cd..56b29526 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.h +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.h @@ -9,6 +9,7 @@ #include "GameResource/ResourceFont.hpp" #include "GameResource/ResourcePostEffectShader.hpp" #include "GameResource/ResourceModel.hpp" +#include "GameResource/ResourceSpine.hpp" #include "lua.hpp" #include "xxhash.h" @@ -87,6 +88,7 @@ namespace luastg dictionary_t> m_TTFFontPool; dictionary_t> m_FXPool; dictionary_t> m_ModelPool; + dictionary_t> m_SpinePool; private: const char* getResourcePoolTypeName(); public: @@ -132,7 +134,9 @@ namespace luastg bool LoadFX(const char* name, const char* path) noexcept; // 模型 bool LoadModel(const char* name, const char* path) noexcept; - + // Spine + bool LoadSpine(const char* name, const char* path) noexcept; + core::SmartReference GetTexture(std::string_view name) noexcept; core::SmartReference GetSprite(std::string_view name) noexcept; core::SmartReference GetAnimation(std::string_view name) noexcept; @@ -143,6 +147,7 @@ namespace luastg core::SmartReference GetTTFFont(std::string_view name) noexcept; core::SmartReference GetFX(std::string_view name) noexcept; core::SmartReference GetModel(std::string_view name) noexcept; + core::SmartReference GetSpine(std::string_view name) noexcept; public: ResourcePool(ResourceMgr* mgr, ResourcePoolType t); ResourcePool& operator=(const ResourcePool&) = delete; diff --git a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp index 76fa8666..3eb446e1 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp @@ -11,6 +11,7 @@ #include "core/FileSystem.hpp" #include "AppFrame.h" #include "lua/plus.hpp" +#include "GameResource/Implement/ResourceSpineImpl.hpp" namespace luastg { @@ -28,6 +29,7 @@ namespace luastg m_TTFFontPool.clear(); m_FXPool.clear(); m_ModelPool.clear(); + m_SpinePool.clear(); spdlog::info("[luastg] 已清空资源池 '{}'", getResourcePoolTypeName()); } @@ -93,6 +95,9 @@ namespace luastg case ResourceType::Model: removeResource(m_ModelPool, name); break; + case ResourceType::Spine: + removeResource(m_SpinePool, name); + break; default: spdlog::warn("[luastg] RemoveResource: 试图移除一个不存在的资源类型 ({})", (int)t); return; @@ -123,6 +128,8 @@ namespace luastg return m_FXPool.find(name) != m_FXPool.end(); case ResourceType::Model: return m_ModelPool.find(name) != m_ModelPool.end(); + case ResourceType::Spine: + return m_SpinePool.find(name) != m_SpinePool.end(); default: spdlog::warn("[luastg] CheckRes: 试图检索一个不存在的资源类型({})", (int)t); break; @@ -179,6 +186,9 @@ namespace luastg case ResourceType::Model: listResourceName(L, m_ModelPool); break; + case ResourceType::Spine: + listResourceName(L, m_SpinePool); + break; default: spdlog::warn("[luastg] EnumRes: 试图枚举一个不存在的资源类型({})", (int)t); S.create_array(0); @@ -868,7 +878,7 @@ namespace luastg } return true; } - + try { core::SmartReference tRes; @@ -880,12 +890,45 @@ namespace luastg spdlog::error("[luastg] LoadModel: 无法加载模型 '{}' ({})", name, e.what()); return false; } - + if (ResourceMgr::GetResourceLoadingLog()) { spdlog::info("[luastg] LoadModel: 已从 '{}' 加载模型 '{}' ({})", path, name, getResourcePoolTypeName()); } - + + return true; + } + + // 加载Spine + + bool ResourcePool::LoadSpine(const char* name, const char* path) noexcept + { + if (m_SpinePool.find(std::string_view(name)) != m_SpinePool.end()) + { + if (ResourceMgr::GetResourceLoadingLog()) + { + spdlog::warn("[luastg] LoadModel: Spine '{}' 已存在,加载操作已取消", name); + } + return true; + } + + try + { + core::SmartReference tRes; + tRes.attach(new ResourceSpineImpl(name, path)); + m_SpinePool.emplace(name, tRes); + } + catch (std::exception const& e) + { + spdlog::error("[luastg] LoadModel: 无法加载Spine '{}' ({})", name, e.what()); + return false; + } + + if (ResourceMgr::GetResourceLoadingLog()) + { + spdlog::info("[luastg] LoadModel: 已从 '{}' 加载Spine '{}' ({})", path, name, getResourcePoolTypeName()); + } + return true; } @@ -946,10 +989,15 @@ namespace luastg return findResource(m_FXPool, name); } - core::SmartReference ResourcePool::GetModel(std::string_view name) noexcept - { + core::SmartReference ResourcePool::GetModel(std::string_view name) noexcept + { return findResource(m_ModelPool, name); - } + } + + core::SmartReference ResourcePool::GetSpine(std::string_view name) noexcept + { + return findResource(m_SpinePool, name); + } ResourcePool::ResourcePool(ResourceMgr* mgr, ResourcePoolType t) : m_pMgr(mgr) @@ -964,6 +1012,7 @@ namespace luastg , m_TTFFontPool(&m_memory_resource) , m_FXPool(&m_memory_resource) , m_ModelPool(&m_memory_resource) + , m_SpinePool(&m_memory_resource) { } diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp index 450dd963..9b7f9b65 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp @@ -1,6 +1,5 @@ #pragma once #include "GameResource/ResourceBase.hpp" -#include "spine/Extension.h" namespace luastg { From 03e9737b78c7f21610ac34c9715aca963b466706 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 06/19] handle texSampler && basic LoadSpine --- .../Implement/ResourceSpineImpl.cpp | 47 +++++++++++++++++-- .../Implement/ResourceSpineImpl.hpp | 25 +++++----- LuaSTG/LuaSTG/GameResource/ResourceManager.h | 2 +- LuaSTG/LuaSTG/GameResource/ResourcePool.cpp | 10 ++-- 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp index 404a83d4..0b230a04 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp @@ -4,15 +4,49 @@ namespace luastg { - ResourceSpineImpl::ResourceSpineImpl(const char* name, const char* path) + ResourceSpineImpl::ResourceSpineImpl(const char* name, const char* atlas_path, const char* skel_path) : ResourceBaseImpl(ResourceType::Spine, name) { + atlas = new spine::Atlas(atlas_path, &textureLoader); + if (std::string_view(skel_path).ends_with(".json")) + skeldata = (new spine::SkeletonJson(atlas))->readSkeletonDataFile(skel_path); + else + skeldata = (new spine::SkeletonBinary(atlas))->readSkeletonDataFile(skel_path); } } namespace spine { + using SamplerStateEnum = core::Graphics::IRenderer::SamplerState; + // 沟槽的采样模式映射 + static SamplerStateEnum mapSpineToD3D11( + TextureFilter minFilter, TextureFilter magFilter, + TextureWrap uWrap, TextureWrap vWrap, + bool& enableMipmap) + { + bool isLinear = false; + if (minFilter == TextureFilter_Linear || minFilter == TextureFilter_MipMapLinearNearest || + minFilter == TextureFilter_MipMap || magFilter == TextureFilter_Linear) + isLinear = true; + + if (minFilter == TextureFilter_MipMapNearestNearest || magFilter == TextureFilter_MipMapNearestNearest || + minFilter == TextureFilter_MipMapLinearNearest || magFilter == TextureFilter_MipMapLinearNearest || + minFilter == TextureFilter_MipMapNearestLinear || magFilter == TextureFilter_MipMapNearestLinear || + minFilter == TextureFilter_MipMapLinearLinear || magFilter == TextureFilter_MipMapLinearLinear) + enableMipmap = true; + + SamplerStateEnum mode; + if (uWrap == TextureWrap_Repeat) + mode = isLinear ? SamplerStateEnum::LinearWrap : SamplerStateEnum::PointWrap; + else if (uWrap == TextureWrap_ClampToEdge) + mode = isLinear ? SamplerStateEnum::LinearClamp : SamplerStateEnum::PointClamp; + else + mode = SamplerStateEnum::LinearWrap; + + return mode; + } + LuaSTGAtlasAttachmentLoader::LuaSTGAtlasAttachmentLoader(Atlas* atlas) : AtlasAttachmentLoader(atlas) {} LuaSTGAtlasAttachmentLoader::~LuaSTGAtlasAttachmentLoader() {} void LuaSTGAtlasAttachmentLoader::configureAttachment(Attachment* attachment) {} @@ -21,13 +55,18 @@ namespace spine LuaSTGTextureLoader::~LuaSTGTextureLoader() {} void LuaSTGTextureLoader::load(AtlasPage& page, const spine::String& path) { + bool enableMipmap = false; + SamplerStateEnum state = mapSpineToD3D11(page.minFilter, page.magFilter, page.uWrap, page.uWrap, enableMipmap); + core::Graphics::ITexture2D* p_texture; - if (!LAPP.GetAppModel()->getDevice()->createTextureFromFile(path.buffer(), true, &p_texture)) + if (!LAPP.GetAppModel()->getDevice()->createTextureFromFile(path.buffer(), enableMipmap, &p_texture)) { spdlog::error("[luastg] 从 '{}' 创建Spine纹理失败", path.buffer()); return; } - + core::Graphics::ISamplerState* p_sampler = LAPP.GetRenderer2D()->getKnownSamplerState(state); + p_texture->setSamplerState(p_sampler); + p_texture->retain(); auto [w, h] = p_texture->getSize(); @@ -43,9 +82,7 @@ namespace spine } LuaSTGExtension::LuaSTGExtension() : DefaultSpineExtension() {} - LuaSTGExtension::~LuaSTGExtension() {} - char* LuaSTGExtension::_readFile(const spine::String& path, int* length) { core::IData* data; if(!core::FileSystemManager::readFile(path.buffer(), &data)) return nullptr; diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp index 71650f71..802a5a0c 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp @@ -3,17 +3,6 @@ #include "GameResource/Implement/ResourceBaseImpl.hpp" #include -namespace luastg -{ - class ResourceSpineImpl : public ResourceBaseImpl - { - private: - - public: - ResourceSpineImpl(const char* name, const char* path); - }; -} - namespace spine { class LuaSTGAtlasAttachmentLoader : public AtlasAttachmentLoader @@ -42,4 +31,18 @@ namespace spine protected: virtual char *_readFile(const String &path, int *length); }; +} + +namespace luastg +{ + class ResourceSpineImpl : public ResourceBaseImpl + { + private: + inline static spine::LuaSTGTextureLoader textureLoader{}; + spine::Atlas* atlas; + spine::SkeletonData* skeldata; + + public: + ResourceSpineImpl(const char* name, const char* atlasPath, const char* skelPath); + }; } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.h b/LuaSTG/LuaSTG/GameResource/ResourceManager.h index 56b29526..909bdf6b 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.h +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.h @@ -135,7 +135,7 @@ namespace luastg // 模型 bool LoadModel(const char* name, const char* path) noexcept; // Spine - bool LoadSpine(const char* name, const char* path) noexcept; + bool LoadSpine(const char* name, const char* atlas_path, const char* skel_path) noexcept; core::SmartReference GetTexture(std::string_view name) noexcept; core::SmartReference GetSprite(std::string_view name) noexcept; diff --git a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp index 3eb446e1..547b79fb 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp @@ -901,13 +901,13 @@ namespace luastg // 加载Spine - bool ResourcePool::LoadSpine(const char* name, const char* path) noexcept + bool ResourcePool::LoadSpine(const char* name, const char* atlas_path, const char* skel_path) noexcept { if (m_SpinePool.find(std::string_view(name)) != m_SpinePool.end()) { if (ResourceMgr::GetResourceLoadingLog()) { - spdlog::warn("[luastg] LoadModel: Spine '{}' 已存在,加载操作已取消", name); + spdlog::warn("[luastg] LoadSpine: Spine '{}' 已存在,加载操作已取消", name); } return true; } @@ -915,18 +915,18 @@ namespace luastg try { core::SmartReference tRes; - tRes.attach(new ResourceSpineImpl(name, path)); + tRes.attach(new ResourceSpineImpl(name, atlas_path, skel_path)); m_SpinePool.emplace(name, tRes); } catch (std::exception const& e) { - spdlog::error("[luastg] LoadModel: 无法加载Spine '{}' ({})", name, e.what()); + spdlog::error("[luastg] LoadSpine: 无法加载Spine '{}' ({})", name, e.what()); return false; } if (ResourceMgr::GetResourceLoadingLog()) { - spdlog::info("[luastg] LoadModel: 已从 '{}' 加载Spine '{}' ({})", path, name, getResourcePoolTypeName()); + spdlog::info("[luastg] LoadSpine: 已从 '{}', '{}' 加载Spine '{}' ({})", atlas_path, skel_path, name, getResourcePoolTypeName()); } return true; From a9d9492cf6b29e7bb86cd593c48135781690ddb0 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 07/19] split spine to spineAtlas & spineSkeleton --- LuaSTG/CMakeLists.txt | 8 ++-- LuaSTG/LuaSTG/AppFrame.cpp | 2 + .../Implement/ResourceSpineAtlasImpl.cpp | 16 ++++++++ .../Implement/ResourceSpineAtlasImpl.hpp | 17 +++++++++ LuaSTG/LuaSTG/GameResource/ResourceBase.hpp | 2 +- LuaSTG/LuaSTG/GameResource/ResourceManager.h | 10 +++-- LuaSTG/LuaSTG/GameResource/ResourcePool.cpp | 37 ++++++++++--------- ...SpineImpl.cpp => ResourceSpineAdaptor.cpp} | 28 +++++--------- ...SpineImpl.hpp => ResourceSpineAdaptor.hpp} | 18 +-------- ...sourceSpine.hpp => ResourceSpineAtlas.hpp} | 6 +-- 10 files changed, 80 insertions(+), 64 deletions(-) create mode 100644 LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp create mode 100644 LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp rename LuaSTG/LuaSTG/GameResource/{Implement/ResourceSpineImpl.cpp => ResourceSpineAdaptor.cpp} (82%) rename LuaSTG/LuaSTG/GameResource/{Implement/ResourceSpineImpl.hpp => ResourceSpineAdaptor.hpp} (63%) rename LuaSTG/LuaSTG/GameResource/{ResourceSpine.hpp => ResourceSpineAtlas.hpp} (51%) diff --git a/LuaSTG/CMakeLists.txt b/LuaSTG/CMakeLists.txt index b4b0cb53..cf8e4e24 100644 --- a/LuaSTG/CMakeLists.txt +++ b/LuaSTG/CMakeLists.txt @@ -45,7 +45,9 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/GameResource/ResourceBase.hpp LuaSTG/GameResource/ResourceTexture.hpp LuaSTG/GameResource/ResourceSprite.hpp - LuaSTG/GameResource/ResourceSpine.hpp + LuaSTG/GameResource/ResourceSpineAtlas.hpp + LuaSTG/GameResource/ResourceSpineAdaptor.hpp + LuaSTG/GameResource/ResourceSpineAdaptor.cpp LuaSTG/GameResource/ResourceAnimation.hpp LuaSTG/GameResource/ResourceMusic.hpp LuaSTG/GameResource/ResourceSoundEffect.hpp @@ -67,8 +69,8 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/GameResource/Implement/ResourceTextureImpl.cpp LuaSTG/GameResource/Implement/ResourceSpriteImpl.hpp LuaSTG/GameResource/Implement/ResourceSpriteImpl.cpp - LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp - LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp + LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp + LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp LuaSTG/GameResource/Implement/ResourceAnimationImpl.hpp LuaSTG/GameResource/Implement/ResourceAnimationImpl.cpp LuaSTG/GameResource/Implement/ResourceMusicImpl.hpp diff --git a/LuaSTG/LuaSTG/AppFrame.cpp b/LuaSTG/LuaSTG/AppFrame.cpp index 18760389..9b7636fc 100644 --- a/LuaSTG/LuaSTG/AppFrame.cpp +++ b/LuaSTG/LuaSTG/AppFrame.cpp @@ -305,6 +305,8 @@ void AppFrame::Run()noexcept m_pAppModel->getSwapChain()->addEventListener(this); m_pAppModel->getFrameRateController()->setTargetFPS(m_target_fps); + LAPP.GetResourceMgr().GetActivedPool()->LoadSpineAtlas("test", "spineboy.atlas"); + LAPP.GetResourceMgr().GetActivedPool()->LoadSpineAtlas("test", "spineboy.atlas"); m_pAppModel->run(); m_pAppModel->getSwapChain()->removeEventListener(this); diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp new file mode 100644 index 00000000..c1763e52 --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp @@ -0,0 +1,16 @@ +#include "GameResource/Implement/ResourceSpineAtlasImpl.hpp" +#include "GameResource/Implement/ResourceTextureImpl.hpp" +#include "AppFrame.h" +#include "Core/FileSystem.hpp" +#include "Core/SmartReference.hpp" + +namespace luastg +{ + ResourceSpineAtlasImpl::ResourceSpineAtlasImpl(const char* name, const char* atlas_path, spine::TextureLoader* textureLoader) + : ResourceBaseImpl(ResourceType::SpineAtlas, name), + atlas(new spine::Atlas(atlas_path, textureLoader)) + { + + } + +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp new file mode 100644 index 00000000..2a4242b7 --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp @@ -0,0 +1,17 @@ +#pragma once +#include "GameResource/ResourceSpineAtlas.hpp" +#include "GameResource/Implement/ResourceBaseImpl.hpp" +#include + +namespace luastg +{ + class ResourceSpineAtlasImpl : public ResourceBaseImpl + { + private: + std::unique_ptr atlas; + std::unique_ptr skeldata; + + public: + ResourceSpineAtlasImpl(const char* name, const char* atlasPath, spine::TextureLoader* textureLoader); + }; +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp b/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp index 0cdd8f93..ac6fe5d1 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp @@ -14,7 +14,7 @@ namespace luastg { TrueTypeFont, FX, Model, - Spine, + SpineAtlas, }; // 混合模式 diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.h b/LuaSTG/LuaSTG/GameResource/ResourceManager.h index 909bdf6b..6ac3dba1 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.h +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.h @@ -9,7 +9,8 @@ #include "GameResource/ResourceFont.hpp" #include "GameResource/ResourcePostEffectShader.hpp" #include "GameResource/ResourceModel.hpp" -#include "GameResource/ResourceSpine.hpp" +#include "GameResource/ResourceSpineAtlas.hpp" +#include "GameResource/ResourceSpineAdaptor.hpp" #include "lua.hpp" #include "xxhash.h" @@ -77,6 +78,7 @@ namespace luastg private: ResourceMgr* m_pMgr; ResourcePoolType m_iType; + std::unique_ptr m_SpineTextureLoader; std::pmr::unsynchronized_pool_resource m_memory_resource; dictionary_t> m_TexturePool; dictionary_t> m_SpritePool; @@ -88,7 +90,7 @@ namespace luastg dictionary_t> m_TTFFontPool; dictionary_t> m_FXPool; dictionary_t> m_ModelPool; - dictionary_t> m_SpinePool; + dictionary_t> m_SpineAtlasPool; private: const char* getResourcePoolTypeName(); public: @@ -135,7 +137,7 @@ namespace luastg // 模型 bool LoadModel(const char* name, const char* path) noexcept; // Spine - bool LoadSpine(const char* name, const char* atlas_path, const char* skel_path) noexcept; + bool LoadSpineAtlas(const char* name, const char* atlas_path) noexcept; core::SmartReference GetTexture(std::string_view name) noexcept; core::SmartReference GetSprite(std::string_view name) noexcept; @@ -147,7 +149,7 @@ namespace luastg core::SmartReference GetTTFFont(std::string_view name) noexcept; core::SmartReference GetFX(std::string_view name) noexcept; core::SmartReference GetModel(std::string_view name) noexcept; - core::SmartReference GetSpine(std::string_view name) noexcept; + core::SmartReference GetSpine(std::string_view name) noexcept; public: ResourcePool(ResourceMgr* mgr, ResourcePoolType t); ResourcePool& operator=(const ResourcePool&) = delete; diff --git a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp index 547b79fb..d55cb286 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp @@ -8,10 +8,10 @@ #include "GameResource/Implement/ResourceFontImpl.hpp" #include "GameResource/Implement/ResourcePostEffectShaderImpl.hpp" #include "GameResource/Implement/ResourceModelImpl.hpp" +#include "GameResource/Implement/ResourceSpineAtlasImpl.hpp" #include "core/FileSystem.hpp" #include "AppFrame.h" #include "lua/plus.hpp" -#include "GameResource/Implement/ResourceSpineImpl.hpp" namespace luastg { @@ -29,7 +29,7 @@ namespace luastg m_TTFFontPool.clear(); m_FXPool.clear(); m_ModelPool.clear(); - m_SpinePool.clear(); + m_SpineAtlasPool.clear(); spdlog::info("[luastg] 已清空资源池 '{}'", getResourcePoolTypeName()); } @@ -95,8 +95,8 @@ namespace luastg case ResourceType::Model: removeResource(m_ModelPool, name); break; - case ResourceType::Spine: - removeResource(m_SpinePool, name); + case ResourceType::SpineAtlas: + removeResource(m_SpineAtlasPool, name); break; default: spdlog::warn("[luastg] RemoveResource: 试图移除一个不存在的资源类型 ({})", (int)t); @@ -128,8 +128,8 @@ namespace luastg return m_FXPool.find(name) != m_FXPool.end(); case ResourceType::Model: return m_ModelPool.find(name) != m_ModelPool.end(); - case ResourceType::Spine: - return m_SpinePool.find(name) != m_SpinePool.end(); + case ResourceType::SpineAtlas: + return m_SpineAtlasPool.find(name) != m_SpineAtlasPool.end(); default: spdlog::warn("[luastg] CheckRes: 试图检索一个不存在的资源类型({})", (int)t); break; @@ -186,8 +186,8 @@ namespace luastg case ResourceType::Model: listResourceName(L, m_ModelPool); break; - case ResourceType::Spine: - listResourceName(L, m_SpinePool); + case ResourceType::SpineAtlas: + listResourceName(L, m_SpineAtlasPool); break; default: spdlog::warn("[luastg] EnumRes: 试图枚举一个不存在的资源类型({})", (int)t); @@ -901,9 +901,9 @@ namespace luastg // 加载Spine - bool ResourcePool::LoadSpine(const char* name, const char* atlas_path, const char* skel_path) noexcept + bool ResourcePool::LoadSpineAtlas(const char* name, const char* atlas_path) noexcept { - if (m_SpinePool.find(std::string_view(name)) != m_SpinePool.end()) + if (m_SpineAtlasPool.find(std::string_view(name)) != m_SpineAtlasPool.end()) { if (ResourceMgr::GetResourceLoadingLog()) { @@ -914,19 +914,19 @@ namespace luastg try { - core::SmartReference tRes; - tRes.attach(new ResourceSpineImpl(name, atlas_path, skel_path)); - m_SpinePool.emplace(name, tRes); + core::SmartReference tRes; + tRes.attach(new ResourceSpineAtlasImpl(name, atlas_path, m_SpineTextureLoader.get())); + m_SpineAtlasPool.emplace(name, tRes); } catch (std::exception const& e) { - spdlog::error("[luastg] LoadSpine: 无法加载Spine '{}' ({})", name, e.what()); + spdlog::error("[luastg] LoadSpineAtlas: 无法加载SpineAtlas '{}' ({})", name, e.what()); return false; } if (ResourceMgr::GetResourceLoadingLog()) { - spdlog::info("[luastg] LoadSpine: 已从 '{}', '{}' 加载Spine '{}' ({})", atlas_path, skel_path, name, getResourcePoolTypeName()); + spdlog::info("[luastg] LoadSpineAtlas: 已从 '{}' 加载SpineAtlas '{}' ({})", atlas_path, name, getResourcePoolTypeName()); } return true; @@ -994,14 +994,15 @@ namespace luastg return findResource(m_ModelPool, name); } - core::SmartReference ResourcePool::GetSpine(std::string_view name) noexcept + core::SmartReference ResourcePool::GetSpine(std::string_view name) noexcept { - return findResource(m_SpinePool, name); + return findResource(m_SpineAtlasPool, name); } ResourcePool::ResourcePool(ResourceMgr* mgr, ResourcePoolType t) : m_pMgr(mgr) , m_iType(t) + , m_SpineTextureLoader(new spine::LuaSTGTextureLoader) , m_TexturePool(&m_memory_resource) , m_SpritePool(&m_memory_resource) , m_AnimationPool(&m_memory_resource) @@ -1012,7 +1013,7 @@ namespace luastg , m_TTFFontPool(&m_memory_resource) , m_FXPool(&m_memory_resource) , m_ModelPool(&m_memory_resource) - , m_SpinePool(&m_memory_resource) + , m_SpineAtlasPool(&m_memory_resource) { } diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp similarity index 82% rename from LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp rename to LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index 0b230a04..60c2befa 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -1,21 +1,7 @@ -#include "GameResource/Implement/ResourceSpineImpl.hpp" +#include "ResourceSpineAdaptor.hpp" #include "AppFrame.h" #include "Core/FileSystem.hpp" -namespace luastg -{ - ResourceSpineImpl::ResourceSpineImpl(const char* name, const char* atlas_path, const char* skel_path) - : ResourceBaseImpl(ResourceType::Spine, name) - { - atlas = new spine::Atlas(atlas_path, &textureLoader); - - if (std::string_view(skel_path).ends_with(".json")) - skeldata = (new spine::SkeletonJson(atlas))->readSkeletonDataFile(skel_path); - else - skeldata = (new spine::SkeletonBinary(atlas))->readSkeletonDataFile(skel_path); - } -} - namespace spine { using SamplerStateEnum = core::Graphics::IRenderer::SamplerState; @@ -58,7 +44,7 @@ namespace spine bool enableMipmap = false; SamplerStateEnum state = mapSpineToD3D11(page.minFilter, page.magFilter, page.uWrap, page.uWrap, enableMipmap); - core::Graphics::ITexture2D* p_texture; + core::Graphics::ITexture2D* p_texture; if (!LAPP.GetAppModel()->getDevice()->createTextureFromFile(path.buffer(), enableMipmap, &p_texture)) { spdlog::error("[luastg] 从 '{}' 创建Spine纹理失败", path.buffer()); @@ -67,9 +53,8 @@ namespace spine core::Graphics::ISamplerState* p_sampler = LAPP.GetRenderer2D()->getKnownSamplerState(state); p_texture->setSamplerState(p_sampler); - p_texture->retain(); auto [w, h] = p_texture->getSize(); - + page.texture = p_texture; page.width = w; page.height = h; @@ -90,8 +75,13 @@ namespace spine *length = static_cast(data->size()); char* bytes = SpineExtension::alloc(*length, __FILE__, __LINE__); std::memcpy(bytes, data->data(), *length); + data->release(); return bytes; } + LuaSTGExtension& LuaSTGExtension::Instance() { + static LuaSTGExtension _instance; + return _instance; + } - SpineExtension* spine::getDefaultExtension() { return new LuaSTGExtension(); } + SpineExtension* spine::getDefaultExtension() { return &LuaSTGExtension::Instance(); } } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp similarity index 63% rename from LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp rename to LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp index 802a5a0c..58506f3d 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp @@ -1,6 +1,4 @@ #pragma once -#include "GameResource/ResourceSpine.hpp" -#include "GameResource/Implement/ResourceBaseImpl.hpp" #include namespace spine @@ -24,7 +22,9 @@ namespace spine class LuaSTGExtension : public DefaultSpineExtension { + private: public: + static LuaSTGExtension& Instance(); LuaSTGExtension(); virtual ~LuaSTGExtension(); @@ -32,17 +32,3 @@ namespace spine virtual char *_readFile(const String &path, int *length); }; } - -namespace luastg -{ - class ResourceSpineImpl : public ResourceBaseImpl - { - private: - inline static spine::LuaSTGTextureLoader textureLoader{}; - spine::Atlas* atlas; - spine::SkeletonData* skeldata; - - public: - ResourceSpineImpl(const char* name, const char* atlasPath, const char* skelPath); - }; -} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp similarity index 51% rename from LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp rename to LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp index 9b7f9b65..e279d0ba 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpine.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp @@ -3,7 +3,7 @@ namespace luastg { - struct IResourceSpine : public IResourceBase + struct IResourceSpineAtlas : public IResourceBase { }; @@ -12,6 +12,6 @@ namespace luastg namespace core { // UUID v5 // ns:URL - // https://www.luastg-sub.com/luastg.IResourceSpine - template<> constexpr InterfaceId getInterfaceId() { return UUID::parse("8f0a4281-6b0e-5db5-8cf4-2315eedf0c0f"); } + // https://www.luastg-sub.com/luastg.IResourceSpineAtlas + template<> constexpr InterfaceId getInterfaceId() { return UUID::parse("a7995836-0ed4-57ee-a014-417162b8541d"); } } From 5877b9609f3635cee9e07e4d9ff215de541c742f Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 08/19] change spine::LuaSTGTextureLoader to a singleton --- LuaSTG/LuaSTG/GameResource/ResourceManager.h | 1 - LuaSTG/LuaSTG/GameResource/ResourcePool.cpp | 5 ++--- LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp | 5 +++++ LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp | 1 + 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.h b/LuaSTG/LuaSTG/GameResource/ResourceManager.h index 6ac3dba1..7b62305d 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.h +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.h @@ -78,7 +78,6 @@ namespace luastg private: ResourceMgr* m_pMgr; ResourcePoolType m_iType; - std::unique_ptr m_SpineTextureLoader; std::pmr::unsynchronized_pool_resource m_memory_resource; dictionary_t> m_TexturePool; dictionary_t> m_SpritePool; diff --git a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp index d55cb286..fb829006 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp @@ -907,7 +907,7 @@ namespace luastg { if (ResourceMgr::GetResourceLoadingLog()) { - spdlog::warn("[luastg] LoadSpine: Spine '{}' 已存在,加载操作已取消", name); + spdlog::warn("[luastg] LoadSpineAtlas: Spine '{}' 已存在,加载操作已取消", name); } return true; } @@ -915,7 +915,7 @@ namespace luastg try { core::SmartReference tRes; - tRes.attach(new ResourceSpineAtlasImpl(name, atlas_path, m_SpineTextureLoader.get())); + tRes.attach(new ResourceSpineAtlasImpl(name, atlas_path, &spine::LuaSTGTextureLoader::Instance())); m_SpineAtlasPool.emplace(name, tRes); } catch (std::exception const& e) @@ -1002,7 +1002,6 @@ namespace luastg ResourcePool::ResourcePool(ResourceMgr* mgr, ResourcePoolType t) : m_pMgr(mgr) , m_iType(t) - , m_SpineTextureLoader(new spine::LuaSTGTextureLoader) , m_TexturePool(&m_memory_resource) , m_SpritePool(&m_memory_resource) , m_AnimationPool(&m_memory_resource) diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index 60c2befa..3059ce09 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -65,6 +65,11 @@ namespace spine core::Graphics::ITexture2D* p_texture = (core::Graphics::ITexture2D*)texture; p_texture->release(); } + LuaSTGTextureLoader& LuaSTGTextureLoader::Instance() + { + static LuaSTGTextureLoader _instance; + return _instance; + } LuaSTGExtension::LuaSTGExtension() : DefaultSpineExtension() {} LuaSTGExtension::~LuaSTGExtension() {} diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp index 58506f3d..34567a33 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp @@ -18,6 +18,7 @@ namespace spine virtual ~LuaSTGTextureLoader(); virtual void load(AtlasPage &page, const String &path); virtual void unload(void *texture); + static LuaSTGTextureLoader& Instance(); }; class LuaSTGExtension : public DefaultSpineExtension From 2da727aa5137c5e59714c582893e7959751857b6 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 09/19] add spineskeleton --- LuaSTG/CMakeLists.txt | 3 + LuaSTG/LuaSTG/AppFrame.cpp | 2 - .../Implement/ResourceSpineAtlasImpl.cpp | 1 + .../Implement/ResourceSpineAtlasImpl.hpp | 5 +- .../Implement/ResourceSpineSkeletonImpl.cpp | 30 +++++++++ .../Implement/ResourceSpineSkeletonImpl.hpp | 17 +++++ LuaSTG/LuaSTG/GameResource/ResourceBase.hpp | 1 + .../LuaSTG/GameResource/ResourceManager.cpp | 16 +++++ LuaSTG/LuaSTG/GameResource/ResourceManager.h | 10 ++- LuaSTG/LuaSTG/GameResource/ResourcePool.cpp | 62 ++++++++++++++++++- .../GameResource/ResourceSpineAtlas.hpp | 3 +- .../GameResource/ResourceSpineSkeleton.hpp | 17 +++++ 12 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp create mode 100644 LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp create mode 100644 LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp diff --git a/LuaSTG/CMakeLists.txt b/LuaSTG/CMakeLists.txt index cf8e4e24..e3234d4c 100644 --- a/LuaSTG/CMakeLists.txt +++ b/LuaSTG/CMakeLists.txt @@ -46,6 +46,7 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/GameResource/ResourceTexture.hpp LuaSTG/GameResource/ResourceSprite.hpp LuaSTG/GameResource/ResourceSpineAtlas.hpp + LuaSTG/GameResource/ResourceSpineSkeleton.hpp LuaSTG/GameResource/ResourceSpineAdaptor.hpp LuaSTG/GameResource/ResourceSpineAdaptor.cpp LuaSTG/GameResource/ResourceAnimation.hpp @@ -71,6 +72,8 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/GameResource/Implement/ResourceSpriteImpl.cpp LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp + LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp + LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp LuaSTG/GameResource/Implement/ResourceAnimationImpl.hpp LuaSTG/GameResource/Implement/ResourceAnimationImpl.cpp LuaSTG/GameResource/Implement/ResourceMusicImpl.hpp diff --git a/LuaSTG/LuaSTG/AppFrame.cpp b/LuaSTG/LuaSTG/AppFrame.cpp index 9b7636fc..18760389 100644 --- a/LuaSTG/LuaSTG/AppFrame.cpp +++ b/LuaSTG/LuaSTG/AppFrame.cpp @@ -305,8 +305,6 @@ void AppFrame::Run()noexcept m_pAppModel->getSwapChain()->addEventListener(this); m_pAppModel->getFrameRateController()->setTargetFPS(m_target_fps); - LAPP.GetResourceMgr().GetActivedPool()->LoadSpineAtlas("test", "spineboy.atlas"); - LAPP.GetResourceMgr().GetActivedPool()->LoadSpineAtlas("test", "spineboy.atlas"); m_pAppModel->run(); m_pAppModel->getSwapChain()->removeEventListener(this); diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp index c1763e52..8e27d0f7 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp @@ -6,6 +6,7 @@ namespace luastg { + const std::shared_ptr& ResourceSpineAtlasImpl::getAtlas() { return atlas; } ResourceSpineAtlasImpl::ResourceSpineAtlasImpl(const char* name, const char* atlas_path, spine::TextureLoader* textureLoader) : ResourceBaseImpl(ResourceType::SpineAtlas, name), atlas(new spine::Atlas(atlas_path, textureLoader)) diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp index 2a4242b7..25000812 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp @@ -8,9 +8,10 @@ namespace luastg class ResourceSpineAtlasImpl : public ResourceBaseImpl { private: - std::unique_ptr atlas; - std::unique_ptr skeldata; + std::shared_ptr atlas; + public: + const std::shared_ptr& getAtlas(); public: ResourceSpineAtlasImpl(const char* name, const char* atlasPath, spine::TextureLoader* textureLoader); }; diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp new file mode 100644 index 00000000..0c40de9b --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp @@ -0,0 +1,30 @@ +#include "GameResource/Implement/ResourceSpineSkeletonImpl.hpp" +#include "AppFrame.h" + + +namespace luastg +{ + ResourceSpineSkeletonImpl::ResourceSpineSkeletonImpl(const char* name, const char* skel_path, const std::shared_ptr& atlas) + : ResourceBaseImpl(ResourceType::SpineSkeleton, name) + //, atlas_holder(atlas) + { + std::string_view skeleton_path = skel_path; + if (skeleton_path.ends_with(".json")) + { + auto skelJson = new spine::SkeletonJson(atlas.get()); + skeleton.reset(skelJson->readSkeletonDataFile(skel_path)); + delete skelJson; + } + else if (skeleton_path.ends_with(".skel")) + { + auto skelBin = new spine::SkeletonBinary(atlas.get()); + skeleton.reset(skelBin->readSkeletonDataFile(skel_path)); + delete skelBin; + } + else + { + spdlog::error("'{}' 不是可识别的SpineSkeleton文件"); + } + } + +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp new file mode 100644 index 00000000..1f552959 --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp @@ -0,0 +1,17 @@ +#pragma once +#include "GameResource/ResourceSpineSkeleton.hpp" +#include "GameResource/Implement/ResourceBaseImpl.hpp" +#include + +namespace luastg +{ + class ResourceSpineSkeletonImpl : public ResourceBaseImpl + { + private: + std::shared_ptr atlas_holder; + std::shared_ptr skeleton; + + public: + ResourceSpineSkeletonImpl(const char* name, const char* skelPath, const std::shared_ptr& atlas); + }; +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp b/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp index ac6fe5d1..7ee33132 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceBase.hpp @@ -15,6 +15,7 @@ namespace luastg { FX, Model, SpineAtlas, + SpineSkeleton, }; // 混合模式 diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp b/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp index 42bf7340..ecd87c8b 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp @@ -114,6 +114,22 @@ namespace luastg return tRet; } + core::SmartReference ResourceMgr::FindSpineAtlas(const char* name) noexcept + { + core::SmartReference tRet; + if (!(tRet = m_StageResourcePool.GetSpineAtlas(name))) + tRet = m_GlobalResourcePool.GetSpineAtlas(name); + return tRet; + } + + core::SmartReference ResourceMgr::FindSpineSkeleton(const char* name) noexcept + { + core::SmartReference tRet; + if (!(tRet = m_StageResourcePool.GetSpineSkeleton(name))) + tRet = m_GlobalResourcePool.GetSpineSkeleton(name); + return tRet; + } + // 其他资源操作 bool ResourceMgr::GetTextureSize(const char* name, core::Vector2U& out) noexcept { diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.h b/LuaSTG/LuaSTG/GameResource/ResourceManager.h index 7b62305d..bd818887 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.h +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.h @@ -9,8 +9,9 @@ #include "GameResource/ResourceFont.hpp" #include "GameResource/ResourcePostEffectShader.hpp" #include "GameResource/ResourceModel.hpp" -#include "GameResource/ResourceSpineAtlas.hpp" #include "GameResource/ResourceSpineAdaptor.hpp" +#include "GameResource/ResourceSpineAtlas.hpp" +#include "GameResource/ResourceSpineSkeleton.hpp" #include "lua.hpp" #include "xxhash.h" @@ -90,6 +91,7 @@ namespace luastg dictionary_t> m_FXPool; dictionary_t> m_ModelPool; dictionary_t> m_SpineAtlasPool; + dictionary_t> m_SpineSkeletonPool; private: const char* getResourcePoolTypeName(); public: @@ -137,6 +139,7 @@ namespace luastg bool LoadModel(const char* name, const char* path) noexcept; // Spine bool LoadSpineAtlas(const char* name, const char* atlas_path) noexcept; + bool LoadSpineSkeleton(const char* atlas_name, const char* name, const char* skeleton_path) noexcept; core::SmartReference GetTexture(std::string_view name) noexcept; core::SmartReference GetSprite(std::string_view name) noexcept; @@ -148,7 +151,8 @@ namespace luastg core::SmartReference GetTTFFont(std::string_view name) noexcept; core::SmartReference GetFX(std::string_view name) noexcept; core::SmartReference GetModel(std::string_view name) noexcept; - core::SmartReference GetSpine(std::string_view name) noexcept; + core::SmartReference GetSpineAtlas(std::string_view name) noexcept; + core::SmartReference GetSpineSkeleton(std::string_view name) noexcept; public: ResourcePool(ResourceMgr* mgr, ResourcePoolType t); ResourcePool& operator=(const ResourcePool&) = delete; @@ -179,6 +183,8 @@ namespace luastg core::SmartReference FindTTFFont(const char* name) noexcept; core::SmartReference FindFX(const char* name) noexcept; core::SmartReference FindModel(const char* name) noexcept; + core::SmartReference FindSpineAtlas(const char* name) noexcept; + core::SmartReference FindSpineSkeleton(const char* name) noexcept; bool GetTextureSize(const char* name, core::Vector2U& out) noexcept; void CacheTTFFontString(const char* name, const char* text, size_t len) noexcept; diff --git a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp index fb829006..6b9a99b7 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp @@ -9,6 +9,7 @@ #include "GameResource/Implement/ResourcePostEffectShaderImpl.hpp" #include "GameResource/Implement/ResourceModelImpl.hpp" #include "GameResource/Implement/ResourceSpineAtlasImpl.hpp" +#include "GameResource/Implement/ResourceSpineSkeletonImpl.hpp" #include "core/FileSystem.hpp" #include "AppFrame.h" #include "lua/plus.hpp" @@ -30,6 +31,7 @@ namespace luastg m_FXPool.clear(); m_ModelPool.clear(); m_SpineAtlasPool.clear(); + m_SpineSkeletonPool.clear(); spdlog::info("[luastg] 已清空资源池 '{}'", getResourcePoolTypeName()); } @@ -98,6 +100,9 @@ namespace luastg case ResourceType::SpineAtlas: removeResource(m_SpineAtlasPool, name); break; + case ResourceType::SpineSkeleton: + removeResource(m_SpineSkeletonPool, name); + break; default: spdlog::warn("[luastg] RemoveResource: 试图移除一个不存在的资源类型 ({})", (int)t); return; @@ -130,6 +135,8 @@ namespace luastg return m_ModelPool.find(name) != m_ModelPool.end(); case ResourceType::SpineAtlas: return m_SpineAtlasPool.find(name) != m_SpineAtlasPool.end(); + case ResourceType::SpineSkeleton: + return m_SpineSkeletonPool.find(name) != m_SpineSkeletonPool.end(); default: spdlog::warn("[luastg] CheckRes: 试图检索一个不存在的资源类型({})", (int)t); break; @@ -189,6 +196,9 @@ namespace luastg case ResourceType::SpineAtlas: listResourceName(L, m_SpineAtlasPool); break; + case ResourceType::SpineSkeleton: + listResourceName(L, m_SpineSkeletonPool); + break; default: spdlog::warn("[luastg] EnumRes: 试图枚举一个不存在的资源类型({})", (int)t); S.create_array(0); @@ -899,7 +909,7 @@ namespace luastg return true; } - // 加载Spine + // 加载SpineAtlas bool ResourcePool::LoadSpineAtlas(const char* name, const char* atlas_path) noexcept { @@ -907,7 +917,7 @@ namespace luastg { if (ResourceMgr::GetResourceLoadingLog()) { - spdlog::warn("[luastg] LoadSpineAtlas: Spine '{}' 已存在,加载操作已取消", name); + spdlog::warn("[luastg] LoadSpineAtlas: SpineAtlas '{}' 已存在,加载操作已取消", name); } return true; } @@ -932,6 +942,46 @@ namespace luastg return true; } + // 加载SpineSkeleton + + bool ResourcePool::LoadSpineSkeleton(const char* atlas_name, const char* name, const char* skeleton_path) noexcept + { + if (m_SpineSkeletonPool.find(std::string_view(name)) != m_SpineSkeletonPool.end()) + { + if (ResourceMgr::GetResourceLoadingLog()) + { + spdlog::warn("[luastg] LoadSpineSkeleton: SpineSkeleton '{}' 已存在,加载操作已取消", name); + } + return true; + } + + core::SmartReference pAtlas = m_pMgr->FindSpineAtlas(atlas_name); + if (!pAtlas) + { + spdlog::error("[luastg] LoadSpineSkeleton: 无法创建SpineSkeleton '{}',因为无法找到SpineAtlas '{}'", name, atlas_name); + return false; + } + + try + { + core::SmartReference tRes; + tRes.attach(new ResourceSpineSkeletonImpl(name, skeleton_path, pAtlas->getAtlas())); + m_SpineSkeletonPool.emplace(name, tRes); + } + catch (std::exception const& e) + { + spdlog::error("[luastg] LoadSpineSkeleton: 无法加载SpineSkeleton '{}' ({})", name, e.what()); + return false; + } + + if (ResourceMgr::GetResourceLoadingLog()) + { + spdlog::info("[luastg] LoadSpineSkeleton: 已从 '{}' 加载SpineSkeleton '{}' ({})", skeleton_path, name, getResourcePoolTypeName()); + } + + return true; + } + // 查找并获取 template @@ -994,11 +1044,16 @@ namespace luastg return findResource(m_ModelPool, name); } - core::SmartReference ResourcePool::GetSpine(std::string_view name) noexcept + core::SmartReference ResourcePool::GetSpineAtlas(std::string_view name) noexcept { return findResource(m_SpineAtlasPool, name); } + core::SmartReference ResourcePool::GetSpineSkeleton(std::string_view name) noexcept + { + return findResource(m_SpineSkeletonPool, name); + } + ResourcePool::ResourcePool(ResourceMgr* mgr, ResourcePoolType t) : m_pMgr(mgr) , m_iType(t) @@ -1013,6 +1068,7 @@ namespace luastg , m_FXPool(&m_memory_resource) , m_ModelPool(&m_memory_resource) , m_SpineAtlasPool(&m_memory_resource) + , m_SpineSkeletonPool(&m_memory_resource) { } diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp index e279d0ba..8262c4b9 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp @@ -1,11 +1,12 @@ #pragma once #include "GameResource/ResourceBase.hpp" +#include namespace luastg { struct IResourceSpineAtlas : public IResourceBase { - + virtual const std::shared_ptr& getAtlas() = 0; }; } diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp new file mode 100644 index 00000000..c931c2d7 --- /dev/null +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp @@ -0,0 +1,17 @@ +#pragma once +#include "GameResource/ResourceBase.hpp" + +namespace luastg +{ + struct IResourceSpineSkeleton : public IResourceBase + { + + }; +} + +namespace core { + // UUID v5 + // ns:URL + // https://www.luastg-sub.com/luastg.IResourceSpineSkeleton + template<> constexpr InterfaceId getInterfaceId() { return UUID::parse("7ff21330-a4cc-580b-bd25-adb5bbb09c90"); } +} From cc4eb9d1f6238ce62a89082645edb71336842103 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 10/19] basic lua binding --- .../Implement/ResourceSpineSkeletonImpl.cpp | 12 +++--- LuaSTG/LuaSTG/GameResource/ResourceManager.h | 2 +- LuaSTG/LuaSTG/GameResource/ResourcePool.cpp | 2 +- .../GameResource/ResourceSpineSkeleton.hpp | 4 +- LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp | 38 ++++++++++++++++++- 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp index 0c40de9b..9f037aad 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp @@ -6,20 +6,18 @@ namespace luastg { ResourceSpineSkeletonImpl::ResourceSpineSkeletonImpl(const char* name, const char* skel_path, const std::shared_ptr& atlas) : ResourceBaseImpl(ResourceType::SpineSkeleton, name) - //, atlas_holder(atlas) + , atlas_holder(atlas) { std::string_view skeleton_path = skel_path; if (skeleton_path.ends_with(".json")) { - auto skelJson = new spine::SkeletonJson(atlas.get()); - skeleton.reset(skelJson->readSkeletonDataFile(skel_path)); - delete skelJson; + auto skelJson = spine::SkeletonJson(atlas.get()); + skeleton.reset(skelJson.readSkeletonDataFile(skel_path)); } else if (skeleton_path.ends_with(".skel")) { - auto skelBin = new spine::SkeletonBinary(atlas.get()); - skeleton.reset(skelBin->readSkeletonDataFile(skel_path)); - delete skelBin; + auto skelBin = spine::SkeletonBinary(atlas.get()); + skeleton.reset(skelBin.readSkeletonDataFile(skel_path)); } else { diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.h b/LuaSTG/LuaSTG/GameResource/ResourceManager.h index bd818887..133e9209 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.h +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.h @@ -139,7 +139,7 @@ namespace luastg bool LoadModel(const char* name, const char* path) noexcept; // Spine bool LoadSpineAtlas(const char* name, const char* atlas_path) noexcept; - bool LoadSpineSkeleton(const char* atlas_name, const char* name, const char* skeleton_path) noexcept; + bool LoadSpineSkeleton(const char* name, const char* atlas_name, const char* skeleton_path) noexcept; core::SmartReference GetTexture(std::string_view name) noexcept; core::SmartReference GetSprite(std::string_view name) noexcept; diff --git a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp index 6b9a99b7..08a2f689 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp @@ -944,7 +944,7 @@ namespace luastg // 加载SpineSkeleton - bool ResourcePool::LoadSpineSkeleton(const char* atlas_name, const char* name, const char* skeleton_path) noexcept + bool ResourcePool::LoadSpineSkeleton(const char* name, const char* atlas_name, const char* skeleton_path) noexcept { if (m_SpineSkeletonPool.find(std::string_view(name)) != m_SpineSkeletonPool.end()) { diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp index c931c2d7..6bf7bbae 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp @@ -1,11 +1,13 @@ #pragma once #include "GameResource/ResourceBase.hpp" +#include namespace luastg { struct IResourceSpineSkeleton : public IResourceBase { - + //virtual std::unique_ptr CreateInstance() = 0; + }; } diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp index 3557daf9..1b124f48 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp @@ -351,7 +351,7 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept { const char* name = luaL_checkstring(L, 1); const char* model_path = luaL_checkstring(L, 2); - + ResourcePool* pActivedPool = LRES.GetActivedPool(); if (!pActivedPool) return luaL_error(L, "can't load resource at this time."); @@ -363,6 +363,40 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept } return 0; } + static int LoadSpineAtlas(lua_State* L) noexcept + { + const char* name = luaL_checkstring(L, 1); + const char* atlas_path = luaL_checkstring(L, 2); + + ResourcePool* pActivedPool = LRES.GetActivedPool(); + if (!pActivedPool) + return luaL_error(L, "can't load resource at this time."); + if (!pActivedPool->LoadSpineAtlas( + name, + atlas_path)) + { + return luaL_error(L, "load spineAtlas failed (name='%s', atlas='%s').", name, atlas_path); + } + return 0; + } + static int LoadSpineSkeleton(lua_State* L) noexcept + { + const char* name = luaL_checkstring(L, 1); + const char* atlas_name = luaL_checkstring(L, 2); + const char* skel_path = luaL_checkstring(L, 3); + + ResourcePool* pActivedPool = LRES.GetActivedPool(); + if (!pActivedPool) + return luaL_error(L, "can't load resource at this time."); + if (!pActivedPool->LoadSpineSkeleton( + name, + atlas_name, + skel_path)) + { + return luaL_error(L, "load spineSkeleton failed (name='%s', atlas='%s', skeleton='%s').", name, atlas_name, skel_path); + } + return 0; + } static int CreateRenderTarget(lua_State* L) noexcept { const char* name = luaL_checkstring(L, 1); @@ -688,6 +722,8 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept { "LoadTrueTypeFont", &Wrapper::LoadTrueTypeFont }, { "LoadFX", &Wrapper::LoadFX }, { "LoadModel", &Wrapper::LoadModel }, + { "LoadSpineAtlas", &Wrapper::LoadSpineAtlas }, + { "LoadSpineSkeleton", &Wrapper::LoadSpineSkeleton }, { "CreateRenderTarget", &Wrapper::CreateRenderTarget }, { "IsRenderTarget", &Wrapper::IsRenderTarget }, { "SetTexturePreMulAlphaState", &Wrapper::SetTexturePreMulAlphaState }, From b39a0e900791707a9a1846db827c1ff80cf11b7b Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 11/19] start writing warppers --- LuaSTG/CMakeLists.txt | 1 + .../Implement/ResourceSpineSkeletonImpl.cpp | 2 +- .../Implement/ResourceSpineSkeletonImpl.hpp | 6 ++- .../GameResource/ResourceSpineSkeleton.hpp | 3 +- LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp | 53 +++++++++++++++++++ LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp | 6 +++ LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp | 8 +++ 7 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp diff --git a/LuaSTG/CMakeLists.txt b/LuaSTG/CMakeLists.txt index e3234d4c..08ad58ba 100644 --- a/LuaSTG/CMakeLists.txt +++ b/LuaSTG/CMakeLists.txt @@ -106,6 +106,7 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/LuaBinding/LW_ParticleSystem.cpp LuaSTG/LuaBinding/LW_Render.cpp LuaSTG/LuaBinding/LW_Renderer.cpp + LuaSTG/LuaBinding/LW_Spine.cpp LuaSTG/LuaBinding/LW_StopWatch.cpp LuaSTG/LuaBinding/LW_ResourceMgr.cpp LuaSTG/LuaBinding/LW_Platform.cpp diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp index 9f037aad..26eb804a 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp @@ -24,5 +24,5 @@ namespace luastg spdlog::error("'{}' 不是可识别的SpineSkeleton文件"); } } - + spine::SkeletonData* ResourceSpineSkeletonImpl::getSkeletonData() { return skeleton.get(); } } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp index 1f552959..5eed47e0 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp @@ -9,8 +9,10 @@ namespace luastg { private: std::shared_ptr atlas_holder; - std::shared_ptr skeleton; - + std::unique_ptr skeleton; + + public: + spine::SkeletonData* getSkeletonData(); public: ResourceSpineSkeletonImpl(const char* name, const char* skelPath, const std::shared_ptr& atlas); }; diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp index 6bf7bbae..9710d7af 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp @@ -6,8 +6,7 @@ namespace luastg { struct IResourceSpineSkeleton : public IResourceBase { - //virtual std::unique_ptr CreateInstance() = 0; - + virtual spine::SkeletonData* getSkeletonData() = 0; }; } diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp new file mode 100644 index 00000000..215aadca --- /dev/null +++ b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp @@ -0,0 +1,53 @@ +#include "LuaBinding/LuaWrapper.hpp" + +void luastg::binding::Spine::Register(lua_State* L) noexcept +{ +#define GETUDATA(p, i) spine::Skeleton* (p) = static_cast(luaL_checkudata(L, (i), LUASTG_LUA_TYPENAME_SPINE)); + struct Wrapper + { + static int CreateSpineInstance(lua_State* L) noexcept + { + const char* name = luaL_checkstring(L, 1); + + core::SmartReference pRes; + if (!pRes) return luaL_error(L, "could not find spineSkeleton '%s'.", name); + + luastg::binding::Spine::CreateAndPush(L, pRes->getSkeletonData()); + return 1; + } + static int __gc(lua_State* L) noexcept + { + GETUDATA(data, 1); + data->~Skeleton(); + return 0; + } + + + }; +#undef GETUDATA + luaL_Reg const lib[] = { + { NULL, NULL }, + }; + + luaL_Reg const mt[] = { + { "__gc", &Wrapper::__gc }, + { NULL, NULL }, + }; + + luaL_Reg const ins[] = { + { "CreateSpineInstance", Wrapper::CreateSpineInstance }, + { NULL, NULL } + }; + + luaL_register(L, "lstg", ins); // ??? lstg + RegisterClassIntoTable(L, ".Spine", lib, LUASTG_LUA_TYPENAME_SPINE, mt); + lua_pop(L, 1); +} + +void luastg::binding::Spine::CreateAndPush(lua_State* L, spine::SkeletonData* data) +{ + spine::Skeleton* p = static_cast(lua_newuserdata(L, sizeof(spine::Skeleton))); // udata + new(p) spine::Skeleton(data); + luaL_getmetatable(L, LUASTG_LUA_TYPENAME_SPINE); // udata mt + lua_setmetatable(L, -2); // udata +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp index a617bc17..a4e1ae37 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp @@ -20,6 +20,11 @@ namespace luastg::binding { + static int lib_CreateSpineInstance(lua_State* L) noexcept + { + Spine::CreateAndPush(L); + return 1; + } static int lib_StopWatch(lua_State* L) noexcept { StopWatch::CreateAndPush(L); @@ -42,6 +47,7 @@ namespace luastg::binding luaL_register(L, LUASTG_LUA_LIBNAME, constructors); // ? t Color::Register(L); ParticleSystem::Register(L); + Spine::Register(L); StopWatch::Register(L); BentLaser::Register(L); DirectInput::Register(L); diff --git a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp index 01b1e5dd..ee57e1f4 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp +++ b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp @@ -7,6 +7,7 @@ #define LUASTG_LUA_LIBNAME "lstg" +#define LUASTG_LUA_TYPENAME_SPINE "lstg.Spine" #define LUASTG_LUA_TYPENAME_STOPWATCH "lstg.StopWatch" #define LUASTG_LUA_TYPENAME_BENTLASER "lstg.CurveLaser" @@ -91,6 +92,13 @@ namespace luastg::binding static void CreateAndPush(lua_State* L, core::Color4B const& color); }; + class Spine + { + public: + static void Register(lua_State* L) noexcept; + static void CreateAndPush(lua_State* L, spine::SkeletonData* data); + }; + class StopWatch { public: From 715d7e1a6f56408e258d69c548f6f6b4c7e48014 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 12/19] some warpper --- .../Implement/ResourceSpineSkeletonImpl.cpp | 17 ++ .../Implement/ResourceSpineSkeletonImpl.hpp | 4 + .../GameResource/ResourceSpineAdaptor.cpp | 16 ++ .../GameResource/ResourceSpineAdaptor.hpp | 17 ++ .../GameResource/ResourceSpineSkeleton.hpp | 3 + LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp | 21 +++ LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp | 163 +++++++++++++++++- LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp | 5 - LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp | 2 +- LuaSTG/LuaSTG/LuaBinding/LuaWrapperMisc.hpp | 2 +- 10 files changed, 234 insertions(+), 16 deletions(-) diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp index 26eb804a..3c04280d 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp @@ -23,6 +23,23 @@ namespace luastg { spdlog::error("'{}' 不是可识别的SpineSkeleton文件"); } + + anistate.reset(new spine::AnimationStateData(skeleton.get())); } spine::SkeletonData* ResourceSpineSkeletonImpl::getSkeletonData() { return skeleton.get(); } + spine::AnimationStateData* ResourceSpineSkeletonImpl::getAnimationStateData() { return anistate.get(); } + void ResourceSpineSkeletonImpl::setAnimationMix(const char* ani1, const char* ani2, float mix_time) + { + auto from = skeleton->findAnimation(ani1); + auto to = skeleton->findAnimation(ani2); + + if (!from || !to) + { + spdlog::error("SetSpineAnimationMix: 指定的骨骼 '{}' 上不存在动画 '{}' 和/或 '{}', 已取消", GetResName(), ani1, ani2); + return; + } + + anistate->setMix(ani1, ani2, mix_time); + } + void ResourceSpineSkeletonImpl::setAnimationMix(float mix_time) { anistate->setDefaultMix(mix_time); }; } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp index 5eed47e0..c5b729d6 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp @@ -10,9 +10,13 @@ namespace luastg private: std::shared_ptr atlas_holder; std::unique_ptr skeleton; + std::unique_ptr anistate; public: spine::SkeletonData* getSkeletonData(); + spine::AnimationStateData* getAnimationStateData(); + void setAnimationMix(const char* ani1, const char* ani2, float mix_time); + void setAnimationMix(float mix_time); public: ResourceSpineSkeletonImpl(const char* name, const char* skelPath, const std::shared_ptr& atlas); }; diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index 3059ce09..97184370 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -88,5 +88,21 @@ namespace spine return _instance; } + LuaSTGSpineInstance::LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata) + : resname(name) + , skeleton(new spine::Skeleton(skeldata)) + , anistate(new spine::AnimationState(anidata)) + { + // name -> bone mapping + auto bones = skeleton->getBones(); + auto bone_size = bones.size(); + for (int i = 0; i < bone_size; i++) bonecache[bones[i]->getData().getName().buffer()] = bones[i]; + }; + const std::string_view& LuaSTGSpineInstance::getName() { return resname; } + const std::unordered_map& LuaSTGSpineInstance::getAllBones() { return bonecache; } + Skeleton* LuaSTGSpineInstance::getSkeleton() { return skeleton.get(); } + AnimationState* LuaSTGSpineInstance::getAnimationState() { return anistate.get(); } + Bone* LuaSTGSpineInstance::findBone(const char* name) { return bonecache.contains(name) ? bonecache[name] : nullptr; } + SpineExtension* spine::getDefaultExtension() { return &LuaSTGExtension::Instance(); } } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp index 34567a33..42a5f653 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp @@ -32,4 +32,21 @@ namespace spine protected: virtual char *_readFile(const String &path, int *length); }; + + class LuaSTGSpineInstance + { + private: + std::string_view resname; + std::unique_ptr skeleton; + std::unique_ptr anistate; + std::unordered_map bonecache; + public: + const std::string_view& getName(); + const std::unordered_map& getAllBones(); + Skeleton* getSkeleton(); + AnimationState* getAnimationState(); + Bone* findBone(const char* name); + public: + LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata); + }; } diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp index 9710d7af..d3bca15d 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp @@ -7,6 +7,9 @@ namespace luastg struct IResourceSpineSkeleton : public IResourceBase { virtual spine::SkeletonData* getSkeletonData() = 0; + virtual spine::AnimationStateData* getAnimationStateData() = 0; + virtual void setAnimationMix(const char* ani1, const char* ani2, float mix_time) = 0; + virtual void setAnimationMix(float mix_time) = 0; }; } diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp index 1b124f48..2f1c0996 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp @@ -699,6 +699,25 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept return 0; } + static int SetSpineAnimationMix(lua_State* L) + { + const char* name = luaL_checkstring(L, 1); + core::SmartReference p = LRES.FindSpineSkeleton(name); + if (!p) return luaL_error(L, "spine skeleton '%s' not found.", name); + + if (lua_gettop(L) == 2) + { + p->setAnimationMix(luaL_checknumber(L, 2)); + return 0; + } + + const char* ani1 = luaL_checkstring(L, 2); + const char* ani2 = luaL_checkstring(L, 3); + p->setAnimationMix(ani1, ani2, luaL_checknumber(L, 4)); + + return 0; + } + static int CacheTTFString(lua_State* L) { size_t len = 0; const char* str = luaL_checklstring(L, 2, &len); @@ -745,6 +764,8 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept { "SetFontState", &Wrapper::SetFontState }, + { "SetSpineAnimationMix", &Wrapper::SetSpineAnimationMix }, + { "CacheTTFString", &Wrapper::CacheTTFString }, { NULL, NULL }, }; diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp index 215aadca..901b2ffe 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp @@ -1,36 +1,181 @@ #include "LuaBinding/LuaWrapper.hpp" +using SpineInstance = spine::LuaSTGSpineInstance; + +namespace +{ + enum class Mapper + { + x, y, + vscale, hscale, + getExistBones, + getBoneInfo, + }; + + const std::unordered_map KeyMapper + { + { "x", Mapper::x }, + { "y", Mapper::y }, + { "vscale", Mapper::vscale }, + { "hscale", Mapper::hscale }, + { "getExistBones", Mapper::getExistBones }, + { "getBoneInfo", Mapper::getBoneInfo }, + + }; +} + void luastg::binding::Spine::Register(lua_State* L) noexcept { -#define GETUDATA(p, i) spine::Skeleton* (p) = static_cast(luaL_checkudata(L, (i), LUASTG_LUA_TYPENAME_SPINE)); +#define GETUDATA(p, i) SpineInstance* (p) = static_cast(luaL_checkudata(L, (i), LUASTG_LUA_TYPENAME_SPINE)); struct Wrapper { static int CreateSpineInstance(lua_State* L) noexcept { const char* name = luaL_checkstring(L, 1); - core::SmartReference pRes; - if (!pRes) return luaL_error(L, "could not find spineSkeleton '%s'.", name); + core::SmartReference pRes = LRES.FindSpineSkeleton(name); + if (!pRes) return luaL_error(L, "could not find spine skeleton '%s'.", name); - luastg::binding::Spine::CreateAndPush(L, pRes->getSkeletonData()); + luastg::binding::Spine::CreateAndPush(L, pRes.get()); return 1; } static int __gc(lua_State* L) noexcept { GETUDATA(data, 1); - data->~Skeleton(); + data->~SpineInstance(); + + return 0; + } + static int __index(lua_State* L) + { + GETUDATA(data, 1); + const char* key = luaL_checkstring(L, 2); + + if (!KeyMapper.contains(key)) { lua_pushnil(L); return 1; } + + switch (KeyMapper.at(key)) + { + case Mapper::x : + lua_pushnumber(L, data->getSkeleton()->getX()); break; + case Mapper::y : + lua_pushnumber(L, data->getSkeleton()->getY()); break; + case Mapper::vscale : + lua_pushnumber(L, data->getSkeleton()->getScaleX()); break; + case Mapper::hscale : + lua_pushnumber(L, data->getSkeleton()->getScaleY()); break; + case Mapper::getExistBones : + lua_pushcfunction(L, Wrapper::getExistBones); break; + case Mapper::getBoneInfo : + lua_pushcfunction(L, Wrapper::getBoneInfo); break; + + default : + ; + }; + + return 1; + } + static int __newindex(lua_State* L) + { + GETUDATA(data, 1); + const char* key = luaL_checkstring(L, 2); + + if (!KeyMapper.contains(key)) { lua_pushnil(L); return 1; } + + switch (KeyMapper.at(key)) + { + case Mapper::x: + data->getSkeleton()->setX(luaL_checknumber(L, 3)); + case Mapper::y: + data->getSkeleton()->setY(luaL_checknumber(L, 3)); + case Mapper::vscale: + data->getSkeleton()->setScaleX(luaL_checknumber(L, 3)); + case Mapper::hscale: + data->getSkeleton()->setScaleY(luaL_checknumber(L, 3)); + + default: + ; + }; return 0; } + static int getExistBones(lua_State* L) + { + GETUDATA(data, 1); + auto& bones = data->getAllBones(); + + lua_createtable(L, bones.size(), 0); // ..args t + + int count = 1; + for (const auto& [k, _] : bones) + { + lua_pushlstring(L, k.data(), k.length()); // ..args t v + lua_rawseti(L, -2, count++); // ..args t + } + + return 1; + } + static int getBoneInfo(lua_State* L) + { + GETUDATA(data, 1); + const char* bone_name = luaL_checkstring(L, 2); + + spine::Bone* bone = data->findBone(bone_name); + if (!bone) return luaL_error(L, "could not find bone '%s' from spine skeleton '%s'.", bone_name, std::string(data->getName()).c_str()); + + // 不知道这些信息哪些有用 总之全给了.jpg + lua_createtable(L, 0, 13); // ..args t + lua_pushnumber(L, bone->getX()); // ..args t val + lua_setfield(L, -2, "x"); // ..args t + lua_pushnumber(L, bone->getY()); // ..args t val + lua_setfield(L, -2, "y"); // ..args t + lua_pushnumber(L, bone->getWorldX()); // ..args t val + lua_setfield(L, -2, "world_x"); // ..args t + lua_pushnumber(L, bone->getWorldY()); // ..args t val + lua_setfield(L, -2, "world_y"); // ..args t + lua_pushnumber(L, bone->getRotation()); // ..args t val + lua_setfield(L, -2, "rot"); // ..args t + lua_pushnumber(L, bone->getWorldRotationX()); // ..args t val + lua_setfield(L, -2, "world_rot_x"); // ..args t + lua_pushnumber(L, bone->getWorldRotationY()); // ..args t val + lua_setfield(L, -2, "world_rot_y"); // ..args t + lua_pushnumber(L, bone->getScaleX()); // ..args t val + lua_setfield(L, -2, "vscale"); // ..args t + lua_pushnumber(L, bone->getScaleY()); // ..args t val + lua_setfield(L, -2, "hscale"); // ..args t + lua_pushnumber(L, bone->getWorldScaleX()); // ..args t val + lua_setfield(L, -2, "world_vscale"); // ..args t + lua_pushnumber(L, bone->getWorldScaleY()); // ..args t val + lua_setfield(L, -2, "world_hscale"); // ..args t + lua_pushnumber(L, bone->getShearX()); // ..args t val + lua_setfield(L, -2, "shear_x"); // ..args t + lua_pushnumber(L, bone->getShearY()); // ..args t val + lua_setfield(L, -2, "shear_y"); // ..args t + + return 1; + } + static int GetEvent() + { + + } + static int SetEventListener() + { + + } + }; #undef GETUDATA + luaL_Reg const lib[] = { + { "getExistBones", &Wrapper::getExistBones }, + { "getBoneInfo", &Wrapper::getBoneInfo }, { NULL, NULL }, }; luaL_Reg const mt[] = { { "__gc", &Wrapper::__gc }, + { "__index", &Wrapper::__index }, + { "__newindex", &Wrapper::__newindex }, { NULL, NULL }, }; @@ -40,14 +185,14 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept }; luaL_register(L, "lstg", ins); // ??? lstg - RegisterClassIntoTable(L, ".Spine", lib, LUASTG_LUA_TYPENAME_SPINE, mt); + RegisterClassIntoTable2(L, ".Spine", lib, LUASTG_LUA_TYPENAME_SPINE, mt); lua_pop(L, 1); } -void luastg::binding::Spine::CreateAndPush(lua_State* L, spine::SkeletonData* data) +void luastg::binding::Spine::CreateAndPush(lua_State* L, IResourceSpineSkeleton* data) { - spine::Skeleton* p = static_cast(lua_newuserdata(L, sizeof(spine::Skeleton))); // udata - new(p) spine::Skeleton(data); + SpineInstance* p = static_cast(lua_newuserdata(L, sizeof(SpineInstance))); // udata + new(p) SpineInstance(data->GetResName(), data->getSkeletonData(), data->getAnimationStateData()); luaL_getmetatable(L, LUASTG_LUA_TYPENAME_SPINE); // udata mt lua_setmetatable(L, -2); // udata } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp index a4e1ae37..9e197d82 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.cpp @@ -20,11 +20,6 @@ namespace luastg::binding { - static int lib_CreateSpineInstance(lua_State* L) noexcept - { - Spine::CreateAndPush(L); - return 1; - } static int lib_StopWatch(lua_State* L) noexcept { StopWatch::CreateAndPush(L); diff --git a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp index ee57e1f4..aa00f4f5 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp +++ b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp @@ -96,7 +96,7 @@ namespace luastg::binding { public: static void Register(lua_State* L) noexcept; - static void CreateAndPush(lua_State* L, spine::SkeletonData* data); + static void CreateAndPush(lua_State* L, IResourceSpineSkeleton* data); }; class StopWatch diff --git a/LuaSTG/LuaSTG/LuaBinding/LuaWrapperMisc.hpp b/LuaSTG/LuaSTG/LuaBinding/LuaWrapperMisc.hpp index f1fc4faa..8c9c9c5e 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LuaWrapperMisc.hpp +++ b/LuaSTG/LuaSTG/LuaBinding/LuaWrapperMisc.hpp @@ -56,7 +56,7 @@ namespace luastg //在栈顶的table创建一个名为name的新表,然后注册静态方法到该表中 //注册元方法到注册表中名为metaname的元表中,并保护元表不被修改 //不注册index元方法 - inline void RegisterClassIntoTable2(lua_State* L, const char* name, luaL_Reg* method, const char* metaname, luaL_Reg* metamethod) + inline void RegisterClassIntoTable2(lua_State* L, const char* name, luaL_Reg const* method, const char* metaname, luaL_Reg const* metamethod) { // ... t lua_pushstring(L, name); // ... t s //key From 6f83e3bef747341eadfd2e08b038ae81425d7573 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:04 +0800 Subject: [PATCH 13/19] render & update --- .../GameResource/ResourceSpineAdaptor.cpp | 13 ++ .../GameResource/ResourceSpineAdaptor.hpp | 8 + LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp | 137 ++++++++++++++++-- 3 files changed, 149 insertions(+), 9 deletions(-) diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index 97184370..98876ab7 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -33,6 +33,13 @@ namespace spine return mode; } + void LuaSTGdummyOnAnimationEventFunc(AnimationState* state, spine::EventType type, TrackEntry* entry, Event* event) { + SP_UNUSED(state); + SP_UNUSED(type); + SP_UNUSED(entry); + SP_UNUSED(event); + } + LuaSTGAtlasAttachmentLoader::LuaSTGAtlasAttachmentLoader(Atlas* atlas) : AtlasAttachmentLoader(atlas) {} LuaSTGAtlasAttachmentLoader::~LuaSTGAtlasAttachmentLoader() {} void LuaSTGAtlasAttachmentLoader::configureAttachment(Attachment* attachment) {} @@ -88,6 +95,12 @@ namespace spine return _instance; } + SkeletonRenderer& LuaSTGSkeletonRenderer::Instance() + { + static SkeletonRenderer _instance; + return _instance; + }; + LuaSTGSpineInstance::LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata) : resname(name) , skeleton(new spine::Skeleton(skeldata)) diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp index 42a5f653..12a359c2 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp @@ -3,6 +3,8 @@ namespace spine { + void LuaSTGdummyOnAnimationEventFunc(AnimationState* state, spine::EventType type, TrackEntry* entry, Event* event); + class LuaSTGAtlasAttachmentLoader : public AtlasAttachmentLoader { public: @@ -33,6 +35,12 @@ namespace spine virtual char *_readFile(const String &path, int *length); }; + class LuaSTGSkeletonRenderer + { + public: + static SkeletonRenderer& Instance(); + }; + class LuaSTGSpineInstance { private: diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp index 901b2ffe..7e8dcfdb 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp @@ -1,4 +1,5 @@ #include "LuaBinding/LuaWrapper.hpp" +#include using SpineInstance = spine::LuaSTGSpineInstance; @@ -10,6 +11,8 @@ namespace vscale, hscale, getExistBones, getBoneInfo, + update, reset, + render, }; const std::unordered_map KeyMapper @@ -20,7 +23,9 @@ namespace { "hscale", Mapper::hscale }, { "getExistBones", Mapper::getExistBones }, { "getBoneInfo", Mapper::getBoneInfo }, - + { "update", Mapper::update }, + { "reset", Mapper::reset }, + { "render", Mapper::render }, }; } @@ -67,9 +72,14 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept lua_pushcfunction(L, Wrapper::getExistBones); break; case Mapper::getBoneInfo : lua_pushcfunction(L, Wrapper::getBoneInfo); break; - + case Mapper::update : + lua_pushcfunction(L, Wrapper::update); break; + case Mapper::reset : + lua_pushcfunction(L, Wrapper::reset); break; + case Mapper::render : + lua_pushcfunction(L, Wrapper::render); break; default : - ; + lua_pushnil(L); break; }; return 1; @@ -84,20 +94,126 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept switch (KeyMapper.at(key)) { case Mapper::x: - data->getSkeleton()->setX(luaL_checknumber(L, 3)); + data->getSkeleton()->setX(luaL_checknumber(L, 3)); break; case Mapper::y: - data->getSkeleton()->setY(luaL_checknumber(L, 3)); + data->getSkeleton()->setY(luaL_checknumber(L, 3)); break; case Mapper::vscale: - data->getSkeleton()->setScaleX(luaL_checknumber(L, 3)); + data->getSkeleton()->setScaleX(luaL_checknumber(L, 3)); break; case Mapper::hscale: - data->getSkeleton()->setScaleY(luaL_checknumber(L, 3)); + data->getSkeleton()->setScaleY(luaL_checknumber(L, 3)); break; default: - ; - }; + break; + } + return 0; + } + + static int update(lua_State* L) + { + GETUDATA(data, 1); + auto delta_t = luaL_checknumber(L, 2); + +#if SPINE_MAJOR_VERSION >= 4 + int physic_state = 0; + if (lua_gettop(L) >= 3) physic_state = luaL_checkint(L, 3); + + spine::Physics physics; + switch (physic_state) + { + case 0: physics = spine::Physics_Update; break; + case 1: physics = spine::Physics_None; break; + case 2: physics = spine::Physics_Pose; break; + case 3: physics = spine::Physics_Reset; break; + default: physics = spine::Physics_Update; break; + } +#endif + + auto animation_state = data->getAnimationState(); + auto skeleton = data->getSkeleton(); + animation_state->update(delta_t); + animation_state->apply(*skeleton); +#if SPINE_MAJOR_VERSION >= 4 + skeleton->updateWorldTransform(physics); +#else + skeleton->updateWorldTramsform(); +#endif + return 0; + } + static int reset(lua_State* L) + { + GETUDATA(data, 1); + auto animationState = data->getAnimationState(); + auto skeleton = data->getSkeleton(); + + skeleton->setToSetupPose(); + skeleton->setSlotsToSetupPose(); + + animationState->clearTracks(); + animationState->setTimeScale(1.0f); + animationState->setListener(spine::LuaSTGdummyOnAnimationEventFunc); + animationState->update(0); + animationState->apply(*skeleton); +#if SPINE_MAJOR_VERSION >= 4 + skeleton->updateWorldTransform(spine::Physics_Reset); +#else + skeleton->updateWorldTransform(); +#endif + return 0; } + static int render(lua_State* L) + { + GETUDATA(data, 1); + + auto* ctx = LAPP.GetAppModel()->getRenderer(); + core::Graphics::IRenderer::DrawVertex vertex[3]; + vertex[0].z = 0.5f; vertex[1].z = 0.5f; vertex[2].z = 0.5f; + + auto skeleton = data->getSkeleton(); + auto& skeletonRenderer = spine::LuaSTGSkeletonRenderer::Instance(); + spine::RenderCommand* command = skeletonRenderer.render(*skeleton); + while (command) { + float* positions = command->positions; + float* uvs = command->uvs; + uint32_t* colors = command->colors; + uint16_t* indices = command->indices; + int32_t n_indices = command->numIndices; + int32_t n_vertices = command->numVertices; + + core::Graphics::ITexture2D* texture = (core::Graphics::ITexture2D*)command->texture; + ctx->setTexture(texture); + luastg::BlendMode mode; + switch (command->blendMode) + { + case spine::BlendMode_Additive: + mode = luastg::BlendMode::AddAdd; break; + case spine::BlendMode_Multiply: + mode = luastg::BlendMode::AddMutiply; break; + case spine::BlendMode_Screen: + mode = luastg::BlendMode::AddScreen; break; + case spine::BlendMode_Normal: // fall through + default: mode = luastg::BlendMode::MulAlpha; break; + } + LAPP.updateGraph2DBlendMode(mode); + + auto vertices = new core::Graphics::IRenderer::DrawVertex[n_vertices]; + for (int i = 0, n = command->numVertices; i < n; i++) + { + vertices[i].x = positions[i << 1]; + vertices[i].y = positions[(i << 1) + 1]; + vertices[i].z = 0.5f; + vertices[i].u = uvs[i << 1]; + vertices[i].v = uvs[(i << 1) + 1]; + vertices[i].color = colors[i]; + } + ctx->drawRaw(vertices, n_vertices, indices, n_indices); + delete[] vertices; + command = command->next; + } + + return 0; + } static int getExistBones(lua_State* L) { GETUDATA(data, 1); @@ -167,6 +283,9 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept #undef GETUDATA luaL_Reg const lib[] = { + { "update", &Wrapper::update }, + { "reset", &Wrapper::reset }, + { "render", &Wrapper::render }, { "getExistBones", &Wrapper::getExistBones }, { "getBoneInfo", &Wrapper::getBoneInfo }, { NULL, NULL }, From 0648700ffb21a8b3f7da79a599ffeae290ccffa6 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:05 +0800 Subject: [PATCH 14/19] basic animation wrapper --- .../GameResource/ResourceSpineAdaptor.cpp | 9 ++- .../GameResource/ResourceSpineAdaptor.hpp | 3 + LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp | 63 +++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index 98876ab7..e75ffcc8 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -107,15 +107,20 @@ namespace spine , anistate(new spine::AnimationState(anidata)) { // name -> bone mapping - auto bones = skeleton->getBones(); - auto bone_size = bones.size(); + const auto& bones = skeleton->getBones(); + const auto bone_size = bones.size(); for (int i = 0; i < bone_size; i++) bonecache[bones[i]->getData().getName().buffer()] = bones[i]; + const auto& animations = skeldata->getAnimations(); + const auto ani_size = animations.size(); + for (int i = 0; i < ani_size; i++) animationcache[animations[i]->getName().buffer()] = animations[i]; }; const std::string_view& LuaSTGSpineInstance::getName() { return resname; } const std::unordered_map& LuaSTGSpineInstance::getAllBones() { return bonecache; } + const std::unordered_map& LuaSTGSpineInstance::getAllAnimations() { return animationcache; } Skeleton* LuaSTGSpineInstance::getSkeleton() { return skeleton.get(); } AnimationState* LuaSTGSpineInstance::getAnimationState() { return anistate.get(); } Bone* LuaSTGSpineInstance::findBone(const char* name) { return bonecache.contains(name) ? bonecache[name] : nullptr; } + Animation* LuaSTGSpineInstance::findAnimation(const char* name) { return animationcache.contains(name) ? animationcache[name] : nullptr; } SpineExtension* spine::getDefaultExtension() { return &LuaSTGExtension::Instance(); } } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp index 12a359c2..0d8e1d84 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp @@ -48,12 +48,15 @@ namespace spine std::unique_ptr skeleton; std::unique_ptr anistate; std::unordered_map bonecache; + std::unordered_map animationcache; public: const std::string_view& getName(); const std::unordered_map& getAllBones(); + const std::unordered_map& getAllAnimations(); Skeleton* getSkeleton(); AnimationState* getAnimationState(); Bone* findBone(const char* name); + Animation* findAnimation(const char* name); public: LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata); }; diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp index 7e8dcfdb..f352659f 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp @@ -13,6 +13,8 @@ namespace getBoneInfo, update, reset, render, + getExistAnimations, + addAnimation, setAnimation, }; const std::unordered_map KeyMapper @@ -26,6 +28,9 @@ namespace { "update", Mapper::update }, { "reset", Mapper::reset }, { "render", Mapper::render }, + { "getExistAnimations", Mapper::getExistAnimations }, + { "addAnimation", Mapper::addAnimation }, + { "setAnimation", Mapper::setAnimation }, }; } @@ -78,6 +83,12 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept lua_pushcfunction(L, Wrapper::reset); break; case Mapper::render : lua_pushcfunction(L, Wrapper::render); break; + case Mapper::getExistAnimations : + lua_pushcfunction(L, Wrapper::getExistAnimations); break; + case Mapper::addAnimation : + lua_pushcfunction(L, Wrapper::addAnimation); break; + case Mapper::setAnimation : + lua_pushcfunction(L, Wrapper::setAnimation); break; default : lua_pushnil(L); break; }; @@ -269,6 +280,58 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept return 1; } + static int getExistAnimations(lua_State* L) + { + GETUDATA(data, 1); + auto& animations = data->getAllAnimations(); + + lua_createtable(L, animations.size(), 0); // ..args t + + int count = 1; + for (const auto& [k, _] : animations) + { + lua_pushlstring(L, k.data(), k.length()); // ..args t v + lua_rawseti(L, -2, count++); // ..args t + } + + return 1; + } + static int addAnimation(lua_State* L) + { + GETUDATA(data, 1); + const char* ani_name = luaL_checkstring(L, 2); + const size_t track_index = luaL_checkinteger(L, 3); + const float delay = luaL_checknumber(L, 4); + const bool loop = lua_toboolean(L, 5); + + + spine::Animation* ani = data->findAnimation(ani_name); + if (!ani) return luaL_error(L, "could not find animation '%s' from spine skeleton '%s'.", ani_name, std::string(data->getName()).c_str()); + + auto animationState = data->getAnimationState(); + animationState->addAnimation(track_index, ani, loop, delay); + + return 0; + } + static int setAnimation(lua_State* L) + { + GETUDATA(data, 1); + const char* ani_name = luaL_checkstring(L, 2); + const size_t track_index = luaL_checkinteger(L, 3); + const float delay = luaL_checknumber(L, 4); + const bool loop = lua_toboolean(L, 5); + + + spine::Animation* ani = data->findAnimation(ani_name); + if (!ani) return luaL_error(L, "could not find animation '%s' from spine skeleton '%s'.", ani_name, std::string(data->getName()).c_str()); + + auto animationState = data->getAnimationState(); + animationState->setAnimation(track_index, ani, loop); + + return 0; + } + + static int GetEvent() { From d7e7f680db8ec432b7eab1cbe123289c18871530 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:05 +0800 Subject: [PATCH 15/19] event wrapper --- .../GameResource/ResourceSpineAdaptor.cpp | 21 -- .../GameResource/ResourceSpineAdaptor.hpp | 20 -- LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp | 229 +++++++++++++++++- external/CMakeLists.txt | 3 +- 4 files changed, 226 insertions(+), 47 deletions(-) diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index e75ffcc8..3d313821 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -101,26 +101,5 @@ namespace spine return _instance; }; - LuaSTGSpineInstance::LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata) - : resname(name) - , skeleton(new spine::Skeleton(skeldata)) - , anistate(new spine::AnimationState(anidata)) - { - // name -> bone mapping - const auto& bones = skeleton->getBones(); - const auto bone_size = bones.size(); - for (int i = 0; i < bone_size; i++) bonecache[bones[i]->getData().getName().buffer()] = bones[i]; - const auto& animations = skeldata->getAnimations(); - const auto ani_size = animations.size(); - for (int i = 0; i < ani_size; i++) animationcache[animations[i]->getName().buffer()] = animations[i]; - }; - const std::string_view& LuaSTGSpineInstance::getName() { return resname; } - const std::unordered_map& LuaSTGSpineInstance::getAllBones() { return bonecache; } - const std::unordered_map& LuaSTGSpineInstance::getAllAnimations() { return animationcache; } - Skeleton* LuaSTGSpineInstance::getSkeleton() { return skeleton.get(); } - AnimationState* LuaSTGSpineInstance::getAnimationState() { return anistate.get(); } - Bone* LuaSTGSpineInstance::findBone(const char* name) { return bonecache.contains(name) ? bonecache[name] : nullptr; } - Animation* LuaSTGSpineInstance::findAnimation(const char* name) { return animationcache.contains(name) ? animationcache[name] : nullptr; } - SpineExtension* spine::getDefaultExtension() { return &LuaSTGExtension::Instance(); } } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp index 0d8e1d84..a703713e 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp @@ -40,24 +40,4 @@ namespace spine public: static SkeletonRenderer& Instance(); }; - - class LuaSTGSpineInstance - { - private: - std::string_view resname; - std::unique_ptr skeleton; - std::unique_ptr anistate; - std::unordered_map bonecache; - std::unordered_map animationcache; - public: - const std::string_view& getName(); - const std::unordered_map& getAllBones(); - const std::unordered_map& getAllAnimations(); - Skeleton* getSkeleton(); - AnimationState* getAnimationState(); - Bone* findBone(const char* name); - Animation* findAnimation(const char* name); - public: - LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata); - }; } diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp index f352659f..b64895f0 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp @@ -1,6 +1,115 @@ #include "LuaBinding/LuaWrapper.hpp" #include +namespace spine +{ + class LuaSTGSpineInstance + { + private: + std::string_view resname; + std::unique_ptr skeleton; + std::unique_ptr anistate; + std::unordered_map bonecache; + std::unordered_map animationcache; + int animation_callback = LUA_NOREF; + int event_callback = LUA_NOREF; + int self_weak_table = LUA_NOREF; + public: + const std::string_view& getName(); + const std::unordered_map& getAllBones(); + const std::unordered_map& getAllAnimations(); + Skeleton* getSkeleton(); + AnimationState* getAnimationState(); + Bone* findBone(const char* name); + Animation* findAnimation(const char* name); + void setAnimationCallback(lua_State* L, int position); + void setEventCallback(lua_State* L, int position); + bool pushAnimationCallback(lua_State* L); + bool pushEventCallback(lua_State* L); + void makeSelfWeakTable(lua_State* L, int self_position); + bool pushSelf(lua_State* L); + public: + LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata); + ~LuaSTGSpineInstance(); + }; + + LuaSTGSpineInstance::LuaSTGSpineInstance(const std::string_view& name, spine::SkeletonData* skeldata, spine::AnimationStateData* anidata) + : resname(name) + , skeleton(new spine::Skeleton(skeldata)) + , anistate(new spine::AnimationState(anidata)) + { + // name -> bone mapping + const auto& bones = skeleton->getBones(); + const auto bone_size = bones.size(); + for (int i = 0; i < bone_size; i++) bonecache[bones[i]->getData().getName().buffer()] = bones[i]; + // name -> ani mapping + const auto& animations = skeldata->getAnimations(); + const auto ani_size = animations.size(); + for (int i = 0; i < ani_size; i++) animationcache[animations[i]->getName().buffer()] = animations[i]; + }; + const std::string_view& LuaSTGSpineInstance::getName() { return resname; } + const std::unordered_map& LuaSTGSpineInstance::getAllBones() { return bonecache; } + const std::unordered_map& LuaSTGSpineInstance::getAllAnimations() { return animationcache; } + Skeleton* LuaSTGSpineInstance::getSkeleton() { return skeleton.get(); } + AnimationState* LuaSTGSpineInstance::getAnimationState() { return anistate.get(); } + Bone* LuaSTGSpineInstance::findBone(const char* name) { return bonecache.contains(name) ? bonecache[name] : nullptr; } + Animation* LuaSTGSpineInstance::findAnimation(const char* name) { return animationcache.contains(name) ? animationcache[name] : nullptr; } + void LuaSTGSpineInstance::setAnimationCallback(lua_State* L, int position) + { + if (animation_callback != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, animation_callback); + lua_pushvalue(L, position); + animation_callback = luaL_ref(L, LUA_REGISTRYINDEX); + }; + void LuaSTGSpineInstance::setEventCallback(lua_State* L, int position) + { + if (event_callback != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, event_callback); + lua_pushvalue(L, position); + event_callback = luaL_ref(L, LUA_REGISTRYINDEX); + }; + bool LuaSTGSpineInstance::pushAnimationCallback(lua_State* L) + { + if (animation_callback == LUA_NOREF) return false; + lua_rawgeti(L, LUA_REGISTRYINDEX, animation_callback); + return true; + } + bool LuaSTGSpineInstance::pushEventCallback(lua_State* L) + { + if (event_callback == LUA_NOREF) return false; + lua_rawgeti(L, LUA_REGISTRYINDEX, event_callback); + return true; + } + LuaSTGSpineInstance::~LuaSTGSpineInstance() + { + lua_State* L = LAPP.GetLuaEngine(); + if (animation_callback != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, animation_callback); + if (event_callback != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, event_callback); + if (self_weak_table != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, self_weak_table); + } + void LuaSTGSpineInstance::makeSelfWeakTable(lua_State* L, int self_position) + { + if (self_weak_table != LUA_NOREF) return; + + lua_newtable(L); // ..arg t + lua_newtable(L); // ..arg t mt + lua_pushstring(L, "v"); // ..arg t mt "v" + lua_setfield(L, -2, "__mode"); // ..arg t mt + lua_setmetatable(L, -2); // ..arg t + lua_pushvalue(L, self_position); // ..arg t self + lua_setfield(L, -2, "self"); // ..arg t + self_weak_table = luaL_ref(L, LUA_REGISTRYINDEX); // ..arg + } + bool LuaSTGSpineInstance::pushSelf(lua_State* L) + { + if (self_weak_table == LUA_NOREF) return false; + + lua_rawgeti(L, LUA_REGISTRYINDEX, self_weak_table); // ..arg t + lua_getfield(L, -1, "self"); // ..arg t self + lua_remove(L, -2); // ..arg self + + return true; + } +} + using SpineInstance = spine::LuaSTGSpineInstance; namespace @@ -14,7 +123,8 @@ namespace update, reset, render, getExistAnimations, - addAnimation, setAnimation, + addAnimation, setAnimation, getCurrentAnimation, + getExistEvents, setEventListener, }; const std::unordered_map KeyMapper @@ -31,6 +141,9 @@ namespace { "getExistAnimations", Mapper::getExistAnimations }, { "addAnimation", Mapper::addAnimation }, { "setAnimation", Mapper::setAnimation }, + { "getCurrentAnimation", Mapper::getCurrentAnimation }, + { "getExistEvents", Mapper::getExistEvents }, + { "setEventListener", Mapper::setEventListener }, }; } @@ -87,8 +200,14 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept lua_pushcfunction(L, Wrapper::getExistAnimations); break; case Mapper::addAnimation : lua_pushcfunction(L, Wrapper::addAnimation); break; - case Mapper::setAnimation : + case Mapper::setAnimation: lua_pushcfunction(L, Wrapper::setAnimation); break; + case Mapper::getCurrentAnimation: + lua_pushcfunction(L, Wrapper::getCurrentAnimation); break; + case Mapper::getExistEvents: + lua_pushcfunction(L, Wrapper::getExistEvents); break; + case Mapper::setEventListener: + lua_pushcfunction(L, Wrapper::setEventListener); break; default : lua_pushnil(L); break; }; @@ -330,15 +449,106 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept return 0; } + static int getCurrentAnimation(lua_State* L) + { + GETUDATA(data, 1); + const size_t track_index = luaL_checkinteger(L, 2); + + auto animationState = data->getAnimationState(); + auto current = animationState->getCurrent(track_index); + + if (!current) + { + lua_pushnil(L); + return 1; + } + const auto& ani_name = current->getAnimation()->getName(); + lua_pushlstring(L, ani_name.buffer(), ani_name.length()); - static int GetEvent() + return 1; + } + static int getExistEvents(lua_State* L) { + GETUDATA(data, 1); + const auto& events = data->getSkeleton()->getData()->getEvents(); + + const auto size = events.size(); + lua_createtable(L, size, 0); // ..args t + + int count = 1; + for (int i = 0; i < size; i++) + { + const auto& event = events[i]->getName(); + lua_pushlstring(L, event.buffer(), event.length()); // ..args t v + lua_rawseti(L, -2, count++); // ..args t + } + return 1; } - static int SetEventListener() + static int setEventListener(lua_State* L) { + GETUDATA(data, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); // animation callback + luaL_checktype(L, 3, LUA_TFUNCTION); // event callback + + data->makeSelfWeakTable(L, 1); + data->setAnimationCallback(L, 2); + data->setEventCallback(L, 3); + + auto listener = [data](spine::AnimationState* state, spine::EventType type, spine::TrackEntry* entry, spine::Event* event) + { + lua_State* L = LAPP.GetLuaEngine(); + int stack_top = lua_gettop(L); + + if (type == spine::EventType_Event) + { + // spine name time fval ival sval ba vol + data->pushEventCallback(L); + data->pushSelf(L); + const auto& name = event->getData().getName(); + lua_pushlstring(L, name.buffer(), name.length()); + lua_pushinteger(L, event->getTime()); + lua_pushinteger(L, event->getFloatValue()); + lua_pushinteger(L, event->getIntValue()); + const auto& str = event->getStringValue(); + lua_pushlstring(L, str.buffer(), str.length()); + lua_pushnumber(L, event->getBalance()); + lua_pushnumber(L, event->getVolume()); + + lua_call(L, 8, 0); + lua_settop(L, stack_top); + return; + } + + data->pushAnimationCallback(L); + data->pushSelf(L); + const auto& name = entry->getAnimation()->getName(); + lua_pushlstring(L, name.buffer(), name.length()); + switch (type) { + case spine::EventType_Start: + lua_pushstring(L, "start"); break; + case spine::EventType_Interrupt: + lua_pushstring(L, "interrupt"); break; + case spine::EventType_End: + lua_pushstring(L, "end"); break; + case spine::EventType_Complete: + lua_pushstring(L, "complete"); break; + case spine::EventType_Dispose: + lua_pushstring(L, "dispose"); break; + default: + break; + }; + lua_call(L, 3, 0); + lua_settop(L, stack_top); + + return; + }; + + data->getAnimationState()->setListener(listener); + + return 1; } @@ -351,6 +561,15 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept { "render", &Wrapper::render }, { "getExistBones", &Wrapper::getExistBones }, { "getBoneInfo", &Wrapper::getBoneInfo }, + { "update", &Wrapper::update }, + { "reset", &Wrapper::reset }, + { "render", &Wrapper::render }, + { "getExistAnimations", &Wrapper::getExistAnimations }, + { "addAnimation", &Wrapper::addAnimation }, + { "setAnimation", &Wrapper::setAnimation }, + { "getCurrentAnimation", &Wrapper::getCurrentAnimation }, + { "getExistEvents", &Wrapper::getExistEvents }, + { "setEventListener", &Wrapper::setEventListener }, { NULL, NULL }, }; @@ -377,4 +596,4 @@ void luastg::binding::Spine::CreateAndPush(lua_State* L, IResourceSpineSkeleton* new(p) SpineInstance(data->GetResName(), data->getSkeletonData(), data->getAnimationStateData()); luaL_getmetatable(L, LUASTG_LUA_TYPENAME_SPINE); // udata mt lua_setmetatable(L, -2); // udata -} \ No newline at end of file +} diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index b632ce31..f5a1e782 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -143,8 +143,9 @@ set_target_properties(libqoi PROPERTIES FOLDER external) # ==================== spine-cpp ==================== add_library(spine-cpp STATIC) -target_compile_definitions(spine-cpp PRIVATE +target_compile_definitions(spine-cpp PUBLIC _CRT_SECURE_NO_WARNINGS + SPINE_USE_STD_FUNCTION ) target_include_directories(spine-cpp PUBLIC spine-runtimes/spine-cpp/spine-cpp/include From 92f5dce9b3c0fe31f0aae1c40e2cf83e0708c8c5 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:05 +0800 Subject: [PATCH 16/19] final wrapper --- LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp | 232 +++++++++++++++++++++++--- 1 file changed, 211 insertions(+), 21 deletions(-) diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp index b64895f0..1a48405b 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp @@ -3,6 +3,12 @@ namespace spine { + struct LuaSTGSlotCacheHelper + { + Slot* slot; + int index; + }; + class LuaSTGSpineInstance { private: @@ -11,6 +17,8 @@ namespace spine std::unique_ptr anistate; std::unordered_map bonecache; std::unordered_map animationcache; + std::unordered_map skincache; + std::unordered_map slotcache; int animation_callback = LUA_NOREF; int event_callback = LUA_NOREF; int self_weak_table = LUA_NOREF; @@ -18,10 +26,14 @@ namespace spine const std::string_view& getName(); const std::unordered_map& getAllBones(); const std::unordered_map& getAllAnimations(); + const std::unordered_map& getAllSkins(); + const std::unordered_map & getAllSlots(); Skeleton* getSkeleton(); AnimationState* getAnimationState(); Bone* findBone(const char* name); Animation* findAnimation(const char* name); + Skin* findSkin(const char* name); + const LuaSTGSlotCacheHelper& findSlot(const char* name); void setAnimationCallback(lua_State* L, int position); void setEventCallback(lua_State* L, int position); bool pushAnimationCallback(lua_State* L); @@ -46,14 +58,26 @@ namespace spine const auto& animations = skeldata->getAnimations(); const auto ani_size = animations.size(); for (int i = 0; i < ani_size; i++) animationcache[animations[i]->getName().buffer()] = animations[i]; + // name -> skin mapping + const auto& skins = skeldata->getSkins(); + const auto ski_size = skins.size(); + for (int i = 0; i < ski_size; i++) skincache[skins[i]->getName().buffer()] = skins[i]; + // name -> slot mapping + const auto& slots = skeleton->getSlots(); + const auto slt_size = slots.size(); + for (int i = 0; i < slt_size; i++) slotcache[slots[i]->getData().getName().buffer()] = {.slot = slots[i], .index = i }; }; const std::string_view& LuaSTGSpineInstance::getName() { return resname; } const std::unordered_map& LuaSTGSpineInstance::getAllBones() { return bonecache; } const std::unordered_map& LuaSTGSpineInstance::getAllAnimations() { return animationcache; } + const std::unordered_map& LuaSTGSpineInstance::getAllSkins() { return skincache; } + const std::unordered_map & LuaSTGSpineInstance::getAllSlots() { return slotcache; } Skeleton* LuaSTGSpineInstance::getSkeleton() { return skeleton.get(); } AnimationState* LuaSTGSpineInstance::getAnimationState() { return anistate.get(); } Bone* LuaSTGSpineInstance::findBone(const char* name) { return bonecache.contains(name) ? bonecache[name] : nullptr; } Animation* LuaSTGSpineInstance::findAnimation(const char* name) { return animationcache.contains(name) ? animationcache[name] : nullptr; } + Skin* LuaSTGSpineInstance::findSkin(const char* name) { return skincache.contains(name) ? skincache[name] : nullptr; } + const LuaSTGSlotCacheHelper& LuaSTGSpineInstance::findSlot(const char* name) { return slotcache.contains(name) ? slotcache[name] : LuaSTGSlotCacheHelper{ .slot = nullptr, .index = -1 }; } void LuaSTGSpineInstance::setAnimationCallback(lua_State* L, int position) { if (animation_callback != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, animation_callback); @@ -119,12 +143,14 @@ namespace x, y, vscale, hscale, getExistBones, - getBoneInfo, - update, reset, - render, + getBoneInfo, setBoneState, + update, reset, render, getExistAnimations, - addAnimation, setAnimation, getCurrentAnimation, + addAnimation, setAnimation, + setAnimationTimeScale, getCurrentAnimation, getExistEvents, setEventListener, + getExistSkins, setSkin, getCurrentSkin, + getExistSlots, setSlotAttachment, getCurrentAttachmentOnSlot, }; const std::unordered_map KeyMapper @@ -135,15 +161,24 @@ namespace { "hscale", Mapper::hscale }, { "getExistBones", Mapper::getExistBones }, { "getBoneInfo", Mapper::getBoneInfo }, + { "setBoneState", Mapper::setBoneState }, { "update", Mapper::update }, { "reset", Mapper::reset }, { "render", Mapper::render }, { "getExistAnimations", Mapper::getExistAnimations }, { "addAnimation", Mapper::addAnimation }, { "setAnimation", Mapper::setAnimation }, + { "setAnimationTimeScale", Mapper::setAnimationTimeScale }, { "getCurrentAnimation", Mapper::getCurrentAnimation }, { "getExistEvents", Mapper::getExistEvents }, { "setEventListener", Mapper::setEventListener }, + { "getExistSkins", Mapper::getExistSkins }, + { "setSkin", Mapper::setSkin }, + { "getCurrentSkin", Mapper::getCurrentSkin }, + { "getExistSlots", Mapper::getExistSlots }, + { "setSlotAttachment", Mapper::setSlotAttachment }, + { "getCurrentAttachmentOnSlot", Mapper::getCurrentAttachmentOnSlot }, + }; } @@ -179,37 +214,52 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept switch (KeyMapper.at(key)) { case Mapper::x : - lua_pushnumber(L, data->getSkeleton()->getX()); break; + lua_pushnumber(L, data->getSkeleton()->getX()); break; case Mapper::y : - lua_pushnumber(L, data->getSkeleton()->getY()); break; + lua_pushnumber(L, data->getSkeleton()->getY()); break; case Mapper::vscale : - lua_pushnumber(L, data->getSkeleton()->getScaleX()); break; + lua_pushnumber(L, data->getSkeleton()->getScaleX()); break; case Mapper::hscale : - lua_pushnumber(L, data->getSkeleton()->getScaleY()); break; + lua_pushnumber(L, data->getSkeleton()->getScaleY()); break; case Mapper::getExistBones : - lua_pushcfunction(L, Wrapper::getExistBones); break; - case Mapper::getBoneInfo : - lua_pushcfunction(L, Wrapper::getBoneInfo); break; + lua_pushcfunction(L, Wrapper::getExistBones); break; + case Mapper::getBoneInfo: + lua_pushcfunction(L, Wrapper::getBoneInfo); break; + case Mapper::setBoneState: + lua_pushcfunction(L, Wrapper::setBoneState); break; case Mapper::update : - lua_pushcfunction(L, Wrapper::update); break; + lua_pushcfunction(L, Wrapper::update); break; case Mapper::reset : - lua_pushcfunction(L, Wrapper::reset); break; + lua_pushcfunction(L, Wrapper::reset); break; case Mapper::render : - lua_pushcfunction(L, Wrapper::render); break; + lua_pushcfunction(L, Wrapper::render); break; case Mapper::getExistAnimations : - lua_pushcfunction(L, Wrapper::getExistAnimations); break; + lua_pushcfunction(L, Wrapper::getExistAnimations); break; case Mapper::addAnimation : - lua_pushcfunction(L, Wrapper::addAnimation); break; + lua_pushcfunction(L, Wrapper::addAnimation); break; case Mapper::setAnimation: - lua_pushcfunction(L, Wrapper::setAnimation); break; + lua_pushcfunction(L, Wrapper::setAnimation); break; case Mapper::getCurrentAnimation: - lua_pushcfunction(L, Wrapper::getCurrentAnimation); break; + lua_pushcfunction(L, Wrapper::getCurrentAnimation); break; case Mapper::getExistEvents: - lua_pushcfunction(L, Wrapper::getExistEvents); break; + lua_pushcfunction(L, Wrapper::getExistEvents); break; case Mapper::setEventListener: - lua_pushcfunction(L, Wrapper::setEventListener); break; + lua_pushcfunction(L, Wrapper::setEventListener); break; + case Mapper::getExistSkins: + lua_pushcfunction(L, Wrapper::getExistSkins); break; + case Mapper::setSkin: + lua_pushcfunction(L, Wrapper::setSkin); break; + case Mapper::getCurrentSkin: + lua_pushcfunction(L, Wrapper::getCurrentSkin); break; + case Mapper::getExistSlots: + lua_pushcfunction(L, Wrapper::getExistSlots); break; + case Mapper::setSlotAttachment: + lua_pushcfunction(L, Wrapper::setSlotAttachment); break; + case Mapper::getCurrentAttachmentOnSlot: + lua_pushcfunction(L, Wrapper::getCurrentAttachmentOnSlot); break; + default : - lua_pushnil(L); break; + lua_pushnil(L); break; }; return 1; @@ -398,6 +448,37 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept lua_setfield(L, -2, "shear_y"); // ..args t return 1; + } + static int setBoneState(lua_State* L) + { + GETUDATA(data, 1); + const char* name = luaL_checkstring(L, 2); + + auto bone = data->findBone(name); + if (!bone) return luaL_error(L, "spine skeleton '%s' does not have bone '%s'.", std::string(data->getName()).c_str(), name); + + const float x = luaL_checknumber(L, 3); + const float y = luaL_checknumber(L, 4); + const float rot = luaL_checknumber(L, 5); + + float vscale = 1, hscale = 1, shear_x = 0, shear_y = 0; + const int stack_top = lua_gettop(L); + switch (stack_top) { + // using fallthrogh here + default: + case 9: + shear_y = luaL_checknumber(L, 9); + case 8: + shear_x = luaL_checknumber(L, 8); + case 7: + hscale = luaL_checknumber(L, 7); + case 6: + vscale = luaL_checknumber(L, 6); + } + + bone->updateWorldTransform(x, y, rot, vscale, hscale, shear_x, shear_y); + + return 0; } static int getExistAnimations(lua_State* L) { @@ -449,6 +530,19 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept return 0; } + static int setAnimationTimeScale(lua_State* L) + { + GETUDATA(data, 1); + const float time_scale = luaL_checknumber(L, 2); + + auto animationState = data->getAnimationState(); + const float old_time_scale = animationState->getTimeScale(); + animationState->setTimeScale(time_scale); + + lua_pushnumber(L, old_time_scale); + + return 1; + } static int getCurrentAnimation(lua_State* L) { GETUDATA(data, 1); @@ -550,7 +644,97 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept return 1; } + static int getExistSkins(lua_State* L) + { + GETUDATA(data, 1); + auto& skins = data->getAllSkins(); + + lua_createtable(L, skins.size(), 0); // ..args t + + int count = 1; + for (const auto& [k, _] : skins) + { + lua_pushlstring(L, k.data(), k.length()); // ..args t v + lua_rawseti(L, -2, count++); // ..args t + } + + return 1; + } + static int setSkin(lua_State* L) + { + GETUDATA(data, 1); + const char* name = luaL_checkstring(L, 2); + + spine::Skin* skin = data->findSkin(name); + if (!skin) return luaL_error(L, "could not find skin '%s' from spine skeleton '%s'.", name, std::string(data->getName()).c_str()); + + const auto skeleton = data->getSkeleton(); + skeleton->setSkin(skin); + skeleton->setSlotsToSetupPose(); + data->getAnimationState()->apply(*skeleton); + + return 0; + } + static int getCurrentSkin(lua_State* L) + { + GETUDATA(data, 1); + + const auto& name = data->getSkeleton()->getSkin()->getName(); + lua_pushlstring(L, name.buffer(), name.length()); + + return 1; + } + static int getExistSlots(lua_State* L) + { + GETUDATA(data, 1); + const auto& slots = data->getAllSlots(); + + const auto size = slots.size(); + lua_createtable(L, size, 0); // ..args t + + int count = 1; + for (const auto& [_, slot] : slots) + { + const auto& name = slot.slot->getData().getName(); + lua_pushlstring(L, name.buffer(), name.length()); // ..args t v + lua_rawseti(L, -2, count++); // ..args t + } + return 1; + } + static int setSlotAttachment(lua_State* L) + { + GETUDATA(data, 1); + const char* slot_name = luaL_checkstring(L, 2); + const char* attachment_name = luaL_checkstring(L, 3); + + const auto& slot_info = data->findSlot(slot_name); + auto slot = slot_info.slot; + if (!slot) return luaL_error(L, "could not find slot '%s' from spine skeleton '%s'.", slot_name, std::string(data->getName()).c_str()); + slot->setAttachment(data->getSkeleton()->getAttachment(slot_info.index, attachment_name)); + + return 0; + } + static int getCurrentAttachmentOnSlot(lua_State* L) + { + GETUDATA(data, 1); + const char* slot_name = luaL_checkstring(L, 2); + + const auto& slot_info = data->findSlot(slot_name); + auto slot = slot_info.slot; + if (!slot) return luaL_error(L, "could not find slot '%s' from spine skeleton '%s'.", slot_name, std::string(data->getName()).c_str()); + + auto attachment = slot->getAttachment(); + if (attachment) + { + const auto& name = attachment->getName(); + lua_pushlstring(L, name.buffer(), name.length()); + return 1; + } + + lua_pushnil(L); + return 1; + } }; #undef GETUDATA @@ -570,6 +754,12 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept { "getCurrentAnimation", &Wrapper::getCurrentAnimation }, { "getExistEvents", &Wrapper::getExistEvents }, { "setEventListener", &Wrapper::setEventListener }, + { "getExistSkins", &Wrapper::getExistSkins }, + { "setSkin", &Wrapper::setSkin }, + { "getCurrentSkin", &Wrapper::getCurrentSkin }, + { "getExistSlots", &Wrapper::getExistSlots }, + { "setSlotAttachment", &Wrapper::setSlotAttachment }, + { "getCurrentAttachmentOnSlot", &Wrapper::getCurrentAttachmentOnSlot }, { NULL, NULL }, }; From 9f7b80f8d54e7400f649e536187ef4141c4e0c75 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:05 +0800 Subject: [PATCH 17/19] throw exceptions when load failed --- .../GameResource/Implement/ResourceSpineSkeletonImpl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp index 3c04280d..29507dd7 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp @@ -21,9 +21,12 @@ namespace luastg } else { - spdlog::error("'{}' 不是可识别的SpineSkeleton文件"); + spdlog::error("'{}' 不是可识别的SpineSkeleton文件.", skel_path); + throw std::exception("spine skeleton only support .json and .skel format, check your skeleton file!"); } + if (skeleton.get() == nullptr) throw std::exception("load spine skeleton failed! check your spine export version and make sure it's 4.2.xx!"); + anistate.reset(new spine::AnimationStateData(skeleton.get())); } spine::SkeletonData* ResourceSpineSkeletonImpl::getSkeletonData() { return skeleton.get(); } From 34d67fe69a8e9cd64d659de967a368390993617e Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Thu, 30 Oct 2025 23:07:05 +0800 Subject: [PATCH 18/19] throw another exception --- LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index 3d313821..376964f3 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -55,6 +55,7 @@ namespace spine if (!LAPP.GetAppModel()->getDevice()->createTextureFromFile(path.buffer(), enableMipmap, &p_texture)) { spdlog::error("[luastg] 从 '{}' 创建Spine纹理失败", path.buffer()); + throw std::exception("failed loading spine atlas's texture, please make sure file structure is as same as it was exported!"); return; } core::Graphics::ISamplerState* p_sampler = LAPP.GetRenderer2D()->getKnownSamplerState(state); From 4cde4320f07c1414aab64681b93ab496063fc853 Mon Sep 17 00:00:00 2001 From: ChensenCHX <2087826155@qq.com> Date: Fri, 31 Oct 2025 13:58:27 +0800 Subject: [PATCH 19/19] add compile options and marco --- CMakeLists.txt | 6 +++ LuaSTG/Core.cmake | 8 +++- .../Implement/ResourceSpineAtlasImpl.cpp | 4 +- .../Implement/ResourceSpineAtlasImpl.hpp | 4 +- .../Implement/ResourceSpineSkeletonImpl.cpp | 4 +- .../Implement/ResourceSpineSkeletonImpl.hpp | 4 +- .../LuaSTG/GameResource/ResourceManager.cpp | 2 + LuaSTG/LuaSTG/GameResource/ResourceManager.h | 10 ++++- LuaSTG/LuaSTG/GameResource/ResourcePool.cpp | 16 +++++++- .../GameResource/ResourceSpineAdaptor.cpp | 4 +- .../GameResource/ResourceSpineAdaptor.hpp | 3 ++ .../GameResource/ResourceSpineAtlas.hpp | 4 ++ .../GameResource/ResourceSpineSkeleton.hpp | 4 ++ LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp | 13 +++++++ LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp | 37 ++++++++++++++++-- LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp | 4 +- external/CMakeLists.txt | 38 ++++++++++--------- 17 files changed, 132 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 017347be..200ec7db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,12 +8,18 @@ option(LUASTG_LINK_YY_THUNKS "Link to YY_Thunks for older Windows version (not r option(LUASTG_LINK_LUASOCKET "Link to luasocket" OFF) option(LUASTG_LINK_TRACY_CLIENT "Link to Tracy client" OFF) option(LUASTG_LINK_STEAM_API "Link to Steam API" OFF) +option(LUASTG_LINK_SPINE_RUNTIME "Link to Spine Runtime" OFF) if(LUASTG_SUPPORTS_WINDOWS_7) message(STATUS "[LuaSTG] Windows compatibility: Windows 7") add_compile_definitions(LUASTG_SUPPORTS_WINDOWS_7) endif() +if(LUASTG_LINK_SPINE_RUNTIME) + message(STATUS "[LuaSTG] Spine support: ON") + add_compile_definitions(LUASTG_SUPPORTS_SPINE) +endif() + set_property(GLOBAL PROPERTY USE_FOLDERS ON) include(cmake/TargetCommonOptions.cmake) include(cmake/options.cmake) diff --git a/LuaSTG/Core.cmake b/LuaSTG/Core.cmake index 30548ffc..1751eebf 100644 --- a/LuaSTG/Core.cmake +++ b/LuaSTG/Core.cmake @@ -111,8 +111,6 @@ target_link_libraries(Core PUBLIC Freetype::Freetype # model tinygltf - # spine - spine-cpp # audio dr_libs Ogg::ogg @@ -128,3 +126,9 @@ target_link_libraries(Core PUBLIC Core.FileSystem win32 ) + +if (LUASTG_LINK_SPINE_RUNTIME) + target_link_libraries(Core PUBLIC spine-cpp) + #target_compile_definitions(Core PUBLIC LUASTG_SUPPORTS_SPINE) + message(STATUS "[Core] Link: spine-runtime") +endif () \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp index 8e27d0f7..56359328 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.cpp @@ -1,3 +1,4 @@ +#ifdef LUASTG_SUPPORTS_SPINE #include "GameResource/Implement/ResourceSpineAtlasImpl.hpp" #include "GameResource/Implement/ResourceTextureImpl.hpp" #include "AppFrame.h" @@ -14,4 +15,5 @@ namespace luastg } -} \ No newline at end of file +} +#endif // LUASTG_SUPPORTS_SPINE \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp index 25000812..01680e81 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineAtlasImpl.hpp @@ -1,4 +1,5 @@ #pragma once +#ifdef LUASTG_SUPPORTS_SPINE #include "GameResource/ResourceSpineAtlas.hpp" #include "GameResource/Implement/ResourceBaseImpl.hpp" #include @@ -15,4 +16,5 @@ namespace luastg public: ResourceSpineAtlasImpl(const char* name, const char* atlasPath, spine::TextureLoader* textureLoader); }; -} \ No newline at end of file +} +#endif // LUASTG_SUPPORTS_SPINE \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp index 29507dd7..32971bc4 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.cpp @@ -1,3 +1,4 @@ +#ifdef LUASTG_SUPPORTS_SPINE #include "GameResource/Implement/ResourceSpineSkeletonImpl.hpp" #include "AppFrame.h" @@ -45,4 +46,5 @@ namespace luastg anistate->setMix(ani1, ani2, mix_time); } void ResourceSpineSkeletonImpl::setAnimationMix(float mix_time) { anistate->setDefaultMix(mix_time); }; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp index c5b729d6..40ebed7e 100644 --- a/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp +++ b/LuaSTG/LuaSTG/GameResource/Implement/ResourceSpineSkeletonImpl.hpp @@ -1,4 +1,5 @@ #pragma once +#ifdef LUASTG_SUPPORTS_SPINE #include "GameResource/ResourceSpineSkeleton.hpp" #include "GameResource/Implement/ResourceBaseImpl.hpp" #include @@ -20,4 +21,5 @@ namespace luastg public: ResourceSpineSkeletonImpl(const char* name, const char* skelPath, const std::shared_ptr& atlas); }; -} \ No newline at end of file +} +#endif // LUASTG_SUPPORTS_SPINE \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp b/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp index ecd87c8b..587cbb47 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.cpp @@ -114,6 +114,7 @@ namespace luastg return tRet; } +#ifdef LUASTG_SUPPORTS_SPINE core::SmartReference ResourceMgr::FindSpineAtlas(const char* name) noexcept { core::SmartReference tRet; @@ -129,6 +130,7 @@ namespace luastg tRet = m_GlobalResourcePool.GetSpineSkeleton(name); return tRet; } +#endif // LUASTG_SUPPORTS_SPINE // 其他资源操作 diff --git a/LuaSTG/LuaSTG/GameResource/ResourceManager.h b/LuaSTG/LuaSTG/GameResource/ResourceManager.h index 133e9209..82129195 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceManager.h +++ b/LuaSTG/LuaSTG/GameResource/ResourceManager.h @@ -90,8 +90,10 @@ namespace luastg dictionary_t> m_TTFFontPool; dictionary_t> m_FXPool; dictionary_t> m_ModelPool; +#ifdef LUASTG_SUPPORTS_SPINE dictionary_t> m_SpineAtlasPool; dictionary_t> m_SpineSkeletonPool; +#endif // LUASTG_SUPPORTS_SPINE private: const char* getResourcePoolTypeName(); public: @@ -138,8 +140,10 @@ namespace luastg // 模型 bool LoadModel(const char* name, const char* path) noexcept; // Spine +#ifdef LUASTG_SUPPORTS_SPINE bool LoadSpineAtlas(const char* name, const char* atlas_path) noexcept; bool LoadSpineSkeleton(const char* name, const char* atlas_name, const char* skeleton_path) noexcept; +#endif // LUASTG_SUPPORTS_SPINE core::SmartReference GetTexture(std::string_view name) noexcept; core::SmartReference GetSprite(std::string_view name) noexcept; @@ -151,8 +155,10 @@ namespace luastg core::SmartReference GetTTFFont(std::string_view name) noexcept; core::SmartReference GetFX(std::string_view name) noexcept; core::SmartReference GetModel(std::string_view name) noexcept; +#ifdef LUASTG_SUPPORTS_SPINE core::SmartReference GetSpineAtlas(std::string_view name) noexcept; core::SmartReference GetSpineSkeleton(std::string_view name) noexcept; +#endif // LUASTG_SUPPORTS_SPINE public: ResourcePool(ResourceMgr* mgr, ResourcePoolType t); ResourcePool& operator=(const ResourcePool&) = delete; @@ -183,9 +189,11 @@ namespace luastg core::SmartReference FindTTFFont(const char* name) noexcept; core::SmartReference FindFX(const char* name) noexcept; core::SmartReference FindModel(const char* name) noexcept; +#ifdef LUASTG_SUPPORTS_SPINE core::SmartReference FindSpineAtlas(const char* name) noexcept; core::SmartReference FindSpineSkeleton(const char* name) noexcept; - +#endif + bool GetTextureSize(const char* name, core::Vector2U& out) noexcept; void CacheTTFFontString(const char* name, const char* text, size_t len) noexcept; void UpdateSound(); diff --git a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp index 08a2f689..cafc1654 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourcePool.cpp @@ -30,8 +30,10 @@ namespace luastg m_TTFFontPool.clear(); m_FXPool.clear(); m_ModelPool.clear(); +#ifdef LUASTG_SUPPORTS_SPINE m_SpineAtlasPool.clear(); m_SpineSkeletonPool.clear(); +#endif // LUASTG_SUPPORTS_SPINE spdlog::info("[luastg] 已清空资源池 '{}'", getResourcePoolTypeName()); } @@ -97,12 +99,14 @@ namespace luastg case ResourceType::Model: removeResource(m_ModelPool, name); break; +#ifdef LUASTG_SUPPORTS_SPINE case ResourceType::SpineAtlas: removeResource(m_SpineAtlasPool, name); break; case ResourceType::SpineSkeleton: removeResource(m_SpineSkeletonPool, name); break; +#endif default: spdlog::warn("[luastg] RemoveResource: 试图移除一个不存在的资源类型 ({})", (int)t); return; @@ -133,10 +137,12 @@ namespace luastg return m_FXPool.find(name) != m_FXPool.end(); case ResourceType::Model: return m_ModelPool.find(name) != m_ModelPool.end(); +#ifdef LUASTG_SUPPORTS_SPINE case ResourceType::SpineAtlas: return m_SpineAtlasPool.find(name) != m_SpineAtlasPool.end(); case ResourceType::SpineSkeleton: return m_SpineSkeletonPool.find(name) != m_SpineSkeletonPool.end(); +#endif default: spdlog::warn("[luastg] CheckRes: 试图检索一个不存在的资源类型({})", (int)t); break; @@ -193,12 +199,14 @@ namespace luastg case ResourceType::Model: listResourceName(L, m_ModelPool); break; +#ifdef LUASTG_SUPPORTS_SPINE case ResourceType::SpineAtlas: listResourceName(L, m_SpineAtlasPool); break; case ResourceType::SpineSkeleton: listResourceName(L, m_SpineSkeletonPool); break; +#endif default: spdlog::warn("[luastg] EnumRes: 试图枚举一个不存在的资源类型({})", (int)t); S.create_array(0); @@ -909,6 +917,7 @@ namespace luastg return true; } +#ifdef LUASTG_SUPPORTS_SPINE // 加载SpineAtlas bool ResourcePool::LoadSpineAtlas(const char* name, const char* atlas_path) noexcept @@ -981,7 +990,8 @@ namespace luastg return true; } - +#endif + // 查找并获取 template @@ -1044,6 +1054,7 @@ namespace luastg return findResource(m_ModelPool, name); } +#ifdef LUASTG_SUPPORTS_SPINE core::SmartReference ResourcePool::GetSpineAtlas(std::string_view name) noexcept { return findResource(m_SpineAtlasPool, name); @@ -1053,6 +1064,7 @@ namespace luastg { return findResource(m_SpineSkeletonPool, name); } +#endif // LUASTG_SUPPORTS_SPINE ResourcePool::ResourcePool(ResourceMgr* mgr, ResourcePoolType t) : m_pMgr(mgr) @@ -1067,8 +1079,10 @@ namespace luastg , m_TTFFontPool(&m_memory_resource) , m_FXPool(&m_memory_resource) , m_ModelPool(&m_memory_resource) +#ifdef LUASTG_SUPPORTS_SPINE , m_SpineAtlasPool(&m_memory_resource) , m_SpineSkeletonPool(&m_memory_resource) +#endif // LUASTG_SUPPORTS_SPINE { } diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp index 376964f3..d7a7c283 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.cpp @@ -1,3 +1,4 @@ +#ifdef LUASTG_SUPPORTS_SPINE #include "ResourceSpineAdaptor.hpp" #include "AppFrame.h" #include "Core/FileSystem.hpp" @@ -103,4 +104,5 @@ namespace spine }; SpineExtension* spine::getDefaultExtension() { return &LuaSTGExtension::Instance(); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp index a703713e..151e7b1b 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAdaptor.hpp @@ -1,4 +1,5 @@ #pragma once +#ifdef LUASTG_SUPPORTS_SPINE #include namespace spine @@ -41,3 +42,5 @@ namespace spine static SkeletonRenderer& Instance(); }; } + +#endif \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp index 8262c4b9..31e04608 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineAtlas.hpp @@ -1,4 +1,6 @@ #pragma once +#ifdef LUASTG_SUPPORTS_SPINE + #include "GameResource/ResourceBase.hpp" #include @@ -16,3 +18,5 @@ namespace core { // https://www.luastg-sub.com/luastg.IResourceSpineAtlas template<> constexpr InterfaceId getInterfaceId() { return UUID::parse("a7995836-0ed4-57ee-a014-417162b8541d"); } } + +#endif // LUASTG_SUPPORTS_SPINE \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp index d3bca15d..789a9901 100644 --- a/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp +++ b/LuaSTG/LuaSTG/GameResource/ResourceSpineSkeleton.hpp @@ -1,4 +1,6 @@ #pragma once +#ifdef LUASTG_SUPPORTS_SPINE + #include "GameResource/ResourceBase.hpp" #include @@ -19,3 +21,5 @@ namespace core { // https://www.luastg-sub.com/luastg.IResourceSpineSkeleton template<> constexpr InterfaceId getInterfaceId() { return UUID::parse("7ff21330-a4cc-580b-bd25-adb5bbb09c90"); } } + +#endif // LUASTG_SUPPORTS_SPINE \ No newline at end of file diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp index 2f1c0996..35964033 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_ResourceMgr.cpp @@ -365,6 +365,7 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept } static int LoadSpineAtlas(lua_State* L) noexcept { +#ifdef LUASTG_SUPPORTS_SPINE const char* name = luaL_checkstring(L, 1); const char* atlas_path = luaL_checkstring(L, 2); @@ -378,9 +379,13 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept return luaL_error(L, "load spineAtlas failed (name='%s', atlas='%s').", name, atlas_path); } return 0; +#else + return luaL_error(L, "spine is not supported in this version!"); +#endif } static int LoadSpineSkeleton(lua_State* L) noexcept { +#ifdef LUASTG_SUPPORTS_SPINE const char* name = luaL_checkstring(L, 1); const char* atlas_name = luaL_checkstring(L, 2); const char* skel_path = luaL_checkstring(L, 3); @@ -396,6 +401,9 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept return luaL_error(L, "load spineSkeleton failed (name='%s', atlas='%s', skeleton='%s').", name, atlas_name, skel_path); } return 0; +#else + return luaL_error(L, "spine is not supported in this version!"); +#endif } static int CreateRenderTarget(lua_State* L) noexcept { @@ -701,6 +709,8 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept static int SetSpineAnimationMix(lua_State* L) { +#ifdef LUASTG_SUPPORTS_SPINE + const char* name = luaL_checkstring(L, 1); core::SmartReference p = LRES.FindSpineSkeleton(name); if (!p) return luaL_error(L, "spine skeleton '%s' not found.", name); @@ -716,6 +726,9 @@ void luastg::binding::ResourceManager::Register(lua_State* L) noexcept p->setAnimationMix(ani1, ani2, luaL_checknumber(L, 4)); return 0; +#else + return luaL_error(L, "spine is not supported in this version!"); +#endif } static int CacheTTFString(lua_State* L) { diff --git a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp index 1a48405b..2dffc207 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LW_Spine.cpp @@ -1,4 +1,5 @@ #include "LuaBinding/LuaWrapper.hpp" +#ifdef LUASTG_SUPPORTS_SPINE #include namespace spine @@ -197,6 +198,11 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept luastg::binding::Spine::CreateAndPush(L, pRes.get()); return 1; } + static int CheckSpineSupport(lua_State* L) + { + lua_pushstring(L, "4.2"); + return 1; + } static int __gc(lua_State* L) noexcept { GETUDATA(data, 1); @@ -740,9 +746,6 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept #undef GETUDATA luaL_Reg const lib[] = { - { "update", &Wrapper::update }, - { "reset", &Wrapper::reset }, - { "render", &Wrapper::render }, { "getExistBones", &Wrapper::getExistBones }, { "getBoneInfo", &Wrapper::getBoneInfo }, { "update", &Wrapper::update }, @@ -771,7 +774,8 @@ void luastg::binding::Spine::Register(lua_State* L) noexcept }; luaL_Reg const ins[] = { - { "CreateSpineInstance", Wrapper::CreateSpineInstance }, + { "CreateSpineInstance", &Wrapper::CreateSpineInstance }, + { "CheckSpineSupport", &Wrapper::CheckSpineSupport }, { NULL, NULL } }; @@ -787,3 +791,28 @@ void luastg::binding::Spine::CreateAndPush(lua_State* L, IResourceSpineSkeleton* luaL_getmetatable(L, LUASTG_LUA_TYPENAME_SPINE); // udata mt lua_setmetatable(L, -2); // udata } +#else +void luastg::binding::Spine::Register(lua_State* L) noexcept +{ + struct Wrapper { + static int CreateSpineInstance(lua_State* L) + { + return luaL_error(L, "spine is not supported in this version!"); + } + static int CheckSpineSupport(lua_State* L) + { + lua_pushstring(L, "unsupport"); + return 1; + } + }; + + luaL_Reg const ins[] = { + { "CreateSpineInstance", &Wrapper::CreateSpineInstance }, + { "CheckSpineSupport", &Wrapper::CheckSpineSupport }, + { NULL, NULL } + }; + + luaL_register(L, "lstg", ins); // ??? lstg + lua_pop(L, 1); // ??? +} +#endif \ No newline at end of file diff --git a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp index aa00f4f5..3acfba15 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp +++ b/LuaSTG/LuaSTG/LuaBinding/LuaWrapper.hpp @@ -91,14 +91,14 @@ namespace luastg::binding static void Register(lua_State* L) noexcept; static void CreateAndPush(lua_State* L, core::Color4B const& color); }; - class Spine { public: static void Register(lua_State* L) noexcept; +#ifdef LUASTG_SUPPORTS_SPINE static void CreateAndPush(lua_State* L, IResourceSpineSkeleton* data); +#endif }; - class StopWatch { public: diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index f5a1e782..3a6651c1 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -142,24 +142,26 @@ set_target_properties(libqoi PROPERTIES FOLDER external) # ==================== spine-cpp ==================== -add_library(spine-cpp STATIC) -target_compile_definitions(spine-cpp PUBLIC - _CRT_SECURE_NO_WARNINGS - SPINE_USE_STD_FUNCTION -) -target_include_directories(spine-cpp PUBLIC - spine-runtimes/spine-cpp/spine-cpp/include -) - -file(GLOB SPINE_INCLUDES "spine-runtimes/spine-cpp/spine-cpp/include/**/*.h") -file(GLOB SPINE_SOURCES "spine-runtimes/spine-cpp/spine-cpp/src/**/*.cpp") - -target_sources(spine-cpp PRIVATE - ${SPINE_INCLUDES} - ${SPINE_SOURCES} -) - -set_target_properties(spine-cpp PROPERTIES FOLDER external) +if(LUASTG_LINK_SPINE_RUNTIME) + add_library(spine-cpp STATIC) + target_compile_definitions(spine-cpp PUBLIC + _CRT_SECURE_NO_WARNINGS + SPINE_USE_STD_FUNCTION + ) + target_include_directories(spine-cpp PUBLIC + spine-runtimes/spine-cpp/spine-cpp/include + ) + + file(GLOB SPINE_INCLUDES "spine-runtimes/spine-cpp/spine-cpp/include/**/*.h") + file(GLOB SPINE_SOURCES "spine-runtimes/spine-cpp/spine-cpp/src/**/*.cpp") + + target_sources(spine-cpp PRIVATE + ${SPINE_INCLUDES} + ${SPINE_SOURCES} + ) + + set_target_properties(spine-cpp PROPERTIES FOLDER external) +endif() # ==================== steam api ====================