From bf403b923ab4a1e11447b3f81d54d5d0c1124f65 Mon Sep 17 00:00:00 2001 From: sapier Date: Fri, 1 Sep 2017 11:15:12 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20animation=20frame=5Fspeed=20and=20blend?= =?UTF-8?q?=20loosing=20precision=20due=20to=20incorrec=E2=80=A6=20(#6357)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix animation frame_speed and blend loosing precision due to incorrect data type Add lua function set_animation_frame_speed to update the frame speed without resetting the animation to start --- doc/lua_api.txt | 3 ++- src/content_cao.cpp | 13 ++++++++++++- src/content_cao.h | 6 ++++-- src/content_sao.cpp | 14 ++++++++++++++ src/content_sao.h | 2 ++ src/genericobject.cpp | 10 ++++++++++ src/genericobject.h | 5 ++++- src/script/lua_api/l_object.cpp | 21 +++++++++++++++++++++ src/script/lua_api/l_object.h | 3 +++ src/serverobject.h | 2 ++ 10 files changed, 74 insertions(+), 5 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index b815d7ee3..4c0b3db2a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3304,8 +3304,9 @@ This is basically a reference to a C++ `ServerActiveObject` * `set_wielded_item(item)`: replaces the wielded item, returns `true` if successful * `set_armor_groups({group1=rating, group2=rating, ...})` * `get_armor_groups()`: returns a table with the armor group ratings -* `set_animation({x=1,y=1}, frame_speed=15, frame_blend=0, frame_loop=true)` +* `set_animation({x=1,y=1}, frame_speed=15.0, frame_blend=0, frame_loop=true)` * `get_animation()`: returns `range`, `frame_speed`, `frame_blend` and `frame_loop` +* `set_animation_frame_speed(frame_speed=15.0)` * `set_attach(parent, bone, position, rotation)` * `bone`: string * `position`: `{x=num, y=num, z=num}` (relative) diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 42f4e22a6..7659871b6 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1150,9 +1150,17 @@ void GenericCAO::updateAnimation() #endif } +void GenericCAO::updateAnimationSpeed() +{ + if (!m_animated_meshnode) + return; + + m_animated_meshnode->setAnimationSpeed(m_animation_speed); +} + void GenericCAO::updateBonePosition() { - if(m_bone_position.empty() || !m_animated_meshnode) + if (m_bone_position.empty() || !m_animated_meshnode) return; m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render @@ -1351,6 +1359,9 @@ void GenericCAO::processMessage(const std::string &data) updateAnimation(); } } + } else if (cmd == GENERIC_CMD_SET_ANIMATION_SPEED) { + m_animation_speed = readF1000(is); + updateAnimationSpeed(); } else if (cmd == GENERIC_CMD_SET_BONE_POSITION) { std::string bone = deSerializeString(is); v3f position = readV3F1000(is); diff --git a/src/content_cao.h b/src/content_cao.h index 0b0e907c5..93b532aad 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -83,8 +83,8 @@ private: bool m_initial_tx_basepos_set = false; bool m_tx_select_horiz_by_yawpitch = false; v2s32 m_animation_range; - int m_animation_speed = 15; - int m_animation_blend = 0; + float m_animation_speed = 15.0f; + float m_animation_blend = 0.0f; bool m_animation_loop = true; // stores position and rotation for each bone name std::unordered_map> m_bone_position; @@ -197,6 +197,8 @@ public: void updateAnimation(); + void updateAnimationSpeed(); + void updateBonePosition(); void updateAttachments(); diff --git a/src/content_sao.cpp b/src/content_sao.cpp index c264473af..ece921472 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -155,6 +155,12 @@ void UnitSAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_bl *frame_loop = m_animation_loop; } +void UnitSAO::setAnimationSpeed(float frame_speed) +{ + m_animation_speed = frame_speed; + m_animation_speed_sent = false; +} + void UnitSAO::setBonePosition(const std::string &bone, v3f position, v3f rotation) { // store these so they can be updated to clients @@ -440,6 +446,14 @@ void LuaEntitySAO::step(float dtime, bool send_recommended) m_messages_out.push(aom); } + if (!m_animation_speed_sent) { + m_animation_speed_sent = true; + std::string str = gob_cmd_update_animation_speed(m_animation_speed); + // create message and add to list + ActiveObjectMessage aom(getId(), true, str); + m_messages_out.push(aom); + } + if (!m_bone_position_sent) { m_bone_position_sent = true; for (std::unordered_map>::const_iterator diff --git a/src/content_sao.h b/src/content_sao.h index 160ac7f43..019397d83 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -46,6 +46,7 @@ public: const ItemGroupList &getArmorGroups(); void setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop); void getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop); + void setAnimationSpeed(float frame_speed); void setBonePosition(const std::string &bone, v3f position, v3f rotation); void getBonePosition(const std::string &bone, v3f *position, v3f *rotation); void setAttachment(int parent_id, const std::string &bone, v3f position, v3f rotation); @@ -70,6 +71,7 @@ protected: float m_animation_blend = 0.0f; bool m_animation_loop = true; bool m_animation_sent = false; + bool m_animation_speed_sent = false; // Stores position and rotation for each bone name std::unordered_map> m_bone_position; diff --git a/src/genericobject.cpp b/src/genericobject.cpp index 15977b0e0..d86c47eb9 100644 --- a/src/genericobject.cpp +++ b/src/genericobject.cpp @@ -147,6 +147,16 @@ std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_ return os.str(); } +std::string gob_cmd_update_animation_speed(float frame_speed) +{ + std::ostringstream os(std::ios::binary); + // command + writeU8(os, GENERIC_CMD_SET_ANIMATION_SPEED); + // parameters + writeF1000(os, frame_speed); + return os.str(); +} + std::string gob_cmd_update_bone_position(const std::string &bone, v3f position, v3f rotation) { diff --git a/src/genericobject.h b/src/genericobject.h index 3ebc85fa3..878300fbf 100644 --- a/src/genericobject.h +++ b/src/genericobject.h @@ -36,7 +36,8 @@ enum GenericCMD { GENERIC_CMD_ATTACH_TO, GENERIC_CMD_SET_PHYSICS_OVERRIDE, GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES, - GENERIC_CMD_SPAWN_INFANT + GENERIC_CMD_SPAWN_INFANT, + GENERIC_CMD_SET_ANIMATION_SPEED }; #include "object_properties.h" @@ -72,6 +73,8 @@ std::string gob_cmd_update_physics_override(float physics_override_speed, std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend, bool frame_loop); +std::string gob_cmd_update_animation_speed(float frame_speed); + std::string gob_cmd_update_bone_position(const std::string &bone, v3f position, v3f rotation); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 24fdeca4b..9b312b3ee 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -604,6 +604,26 @@ int ObjectRef::l_get_eye_offset(lua_State *L) return 2; } +// set_animation_frame_speed(self, frame_speed) +int ObjectRef::l_set_animation_frame_speed(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + ObjectRef *ref = checkobject(L, 1); + ServerActiveObject *co = getobject(ref); + if (co == NULL) + return 0; + + // Do it + if (!lua_isnil(L, 2)) { + float frame_speed = lua_tonumber(L, 2); + co->setAnimationSpeed(frame_speed); + lua_pushboolean(L, true); + } else { + lua_pushboolean(L, false); + } + return 1; +} + // set_bone_position(self, std::string bone, v3f position, v3f rotation) int ObjectRef::l_set_bone_position(lua_State *L) { @@ -1937,6 +1957,7 @@ const luaL_Reg ObjectRef::methods[] = { luamethod(ObjectRef, get_armor_groups), luamethod(ObjectRef, set_animation), luamethod(ObjectRef, get_animation), + luamethod(ObjectRef, set_animation_frame_speed), luamethod(ObjectRef, set_bone_position), luamethod(ObjectRef, get_bone_position), luamethod(ObjectRef, set_attach), diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index 19cc890c7..2a76d8a70 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -126,6 +126,9 @@ private: // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop) static int l_set_animation(lua_State *L); + // set_animation_frame_speed(self, frame_speed) + static int l_set_animation_frame_speed(lua_State *L); + // get_animation(self) static int l_get_animation(lua_State *L); diff --git a/src/serverobject.h b/src/serverobject.h index 7d87a0f59..33fc3e4a8 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -154,6 +154,8 @@ public: {} virtual void getAnimation(v2f *frames, float *frame_speed, float *frame_blend, bool *frame_loop) {} + virtual void setAnimationSpeed(float frame_speed) + {} virtual void setBonePosition(const std::string &bone, v3f position, v3f rotation) {} virtual void getBonePosition(const std::string &bone, v3f *position, v3f *lotation)