diff --git a/doc/en/scripting/ecs.md b/doc/en/scripting/ecs.md index 6c294f9b..1452efe3 100644 --- a/doc/en/scripting/ecs.md +++ b/doc/en/scripting/ecs.md @@ -118,6 +118,10 @@ local rig = entity.skeleton -- Returns the model name assigned to the bone at the specified index rig:get_model(index: int) -> str +-- Reassigns the bone model at the specified index +-- Resets to original if name is not specified +rig:set_model(index: int, name: str) + -- Returns the bone transformation matrix at the specified index rig:get_matrix(index: int) -> mat4 -- Sets the bone transformation matrix at the specified index diff --git a/doc/ru/scripting/ecs.md b/doc/ru/scripting/ecs.md index 6173e58e..40ef6d1f 100644 --- a/doc/ru/scripting/ecs.md +++ b/doc/ru/scripting/ecs.md @@ -119,6 +119,10 @@ local rig = entity.skeleton -- Возвращает имя модели, назначенной на кость с указанным индексом rig:get_model(index: int) -> str +-- Переназначает модель кости с указанным индексом +-- Сбрасывает до изначальной, если не указывать имя +rig:set_model(index: int, name: str) + -- Возвращает матрицу трансформации кости с указанным индексом rig:get_matrix(index: int) -> mat4 -- Устанавливает матрицу трансформации кости с указанным индексом diff --git a/res/modules/internal/stdcomp.lua b/res/modules/internal/stdcomp.lua index 0860caa9..a5fd21cb 100644 --- a/res/modules/internal/stdcomp.lua +++ b/res/modules/internal/stdcomp.lua @@ -39,6 +39,7 @@ end local Skeleton = {__index={ get_model=function(self, i) return __skeleton.get_model(self.eid, i) end, + set_model=function(self, i, s) return __skeleton.set_model(self.eid, i, s) end, get_matrix=function(self, i) return __skeleton.get_matrix(self.eid, i) end, set_matrix=function(self, i, m) return __skeleton.set_matrix(self.eid, i, m) end, get_texture=function(self, s) return __skeleton.get_texture(self.eid, s) end, diff --git a/src/logic/BlocksController.hpp b/src/logic/BlocksController.hpp index 4c989bc4..179302f5 100644 --- a/src/logic/BlocksController.hpp +++ b/src/logic/BlocksController.hpp @@ -20,6 +20,7 @@ enum class BlockInteraction { placing }; +/// @brief Player argument is nullable using on_block_interaction = std::function; @@ -76,6 +77,7 @@ public: BlockInteraction type ); + /// @brief Add block interaction callback void listenBlockInteraction(const on_block_interaction& callback); }; diff --git a/src/logic/scripting/lua/lib__skeleton.cpp b/src/logic/scripting/lua/lib__skeleton.cpp index 936963c5..227d895d 100644 --- a/src/logic/scripting/lua/lib__skeleton.cpp +++ b/src/logic/scripting/lua/lib__skeleton.cpp @@ -16,7 +16,25 @@ static int l_get_model(lua::State* L) { auto& skeleton = entity->getSkeleton(); auto* rigConfig = skeleton.config; auto index = index_range_check(skeleton, lua::tointeger(L, 2)); - return lua::pushstring(L, rigConfig->getNodes()[index]->getModelName()); + const auto& modelOverride = skeleton.modelOverrides[index]; + if (!modelOverride.model) { + return lua::pushstring(L, modelOverride.name); + } + return lua::pushstring(L, rigConfig->getNodes()[index]->model.name); + } + return 0; +} + +static int l_set_model(lua::State* L) { + if (auto entity = get_entity(L, 1)) { + auto& skeleton = entity->getSkeleton(); + auto index = index_range_check(skeleton, lua::tointeger(L, 2)); + auto& modelOverride = skeleton.modelOverrides[index]; + if (lua::isnoneornil(L, 3)) { + modelOverride = {"", nullptr, true}; + } else { + modelOverride = {lua::require_string(L, 3), nullptr, true}; + } } return 0; } @@ -96,6 +114,7 @@ static int l_set_visible(lua::State* L) { const luaL_Reg skeletonlib [] = { {"get_model", lua::wrap}, + {"set_model", lua::wrap}, {"get_matrix", lua::wrap}, {"set_matrix", lua::wrap}, {"get_texture", lua::wrap}, diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index 4c161a5f..82552464 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -7,6 +7,13 @@ using namespace rigging; +void ModelReference::refresh(const Assets* assets) { + if (updateFlag) { + model = assets->get(name); + updateFlag = false; + } +} + Bone::Bone( size_t index, std::string name, @@ -14,22 +21,27 @@ Bone::Bone( std::vector> bones) : index(index), name(std::move(name)), - modelName(std::move(model)), - bones(std::move(bones)) + bones(std::move(bones)), + model({model, nullptr, true}) {} void Bone::setModel(const std::string& name) { - if (modelName == name) { + if (model.name == name) { return; } - modelName = name; - modelUpdated = true; + model = {name, nullptr, true}; } -void Bone::refreshModel(const Assets* assets) { - if (modelUpdated) { - model = assets->get(modelName); - modelUpdated = false; +Skeleton::Skeleton(const SkeletonConfig* config) + : config(config), + pose(config->getNodes().size()), + calculated(config->getNodes().size()), + flags(config->getNodes().size()), + textures(), + modelOverrides(config->getNodes().size()), + visible(true) { + for (size_t i = 0; i < config->getNodes().size(); i++) { + flags[i].visible = true; } } @@ -76,11 +88,17 @@ void SkeletonConfig::render( } for (size_t i = 0; i < nodes.size(); i++) { auto* node = nodes[i]; - node->refreshModel(assets); if (!skeleton.flags[i].visible) { continue; } - if (auto model = node->getModel()) { + node->model.refresh(assets); + auto model = node->model.model; + auto& modelOverride = skeleton.modelOverrides.at(i); + if (!modelOverride.updateFlag) { + modelOverride.refresh(assets); + } + model = modelOverride.model ? modelOverride.model : model; + if (model) { batch.pushMatrix(skeleton.calculated.matrices[i]); batch.draw(model, &skeleton.textures); batch.popMatrix(); diff --git a/src/objects/rigging.hpp b/src/objects/rigging.hpp index 8bb241fd..01920b92 100644 --- a/src/objects/rigging.hpp +++ b/src/objects/rigging.hpp @@ -28,14 +28,20 @@ namespace rigging { } }; + struct ModelReference { + std::string name; + model::Model* model; + bool updateFlag; + + void refresh(const Assets* assets); + }; + class Bone { size_t index; std::string name; - std::string modelName; std::vector> bones; - model::Model* model = nullptr; - bool modelUpdated = true; public: + ModelReference model; Bone( size_t index, std::string name, @@ -44,20 +50,10 @@ namespace rigging { void setModel(const std::string& name); - void refreshModel(const Assets* assets); - const std::string& getName() const { return name; } - - const std::string& getModelName() const { - return modelName; - } - - model::Model* getModel() const { - return model; - } - + size_t getIndex() const { return index; } @@ -77,7 +73,10 @@ namespace rigging { Pose calculated; std::vector flags; std::unordered_map textures; + std::vector modelOverrides; bool visible; + + Skeleton(const SkeletonConfig* config); }; class SkeletonConfig { @@ -110,13 +109,7 @@ namespace rigging { const glm::mat4& matrix) const; Skeleton instance() const { - auto rig = Skeleton { - this, Pose(nodes.size()), Pose(nodes.size()), {}, {}, true - }; - for (size_t i = 0; i < nodes.size(); i++) { - rig.flags.push_back({true}); - } - return rig; + return Skeleton(this); } Bone* find(std::string_view str) const;