Fix some issues with animations, and allow non-looped animations to be defined
authorMirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Sat, 21 Feb 2015 21:38:53 +0000 (23:38 +0200)
committerest31 <MTest31@outlook.com>
Sun, 21 Jun 2015 23:53:38 +0000 (01:53 +0200)
doc/lua_api.txt
src/content_cao.cpp
src/content_cao.h
src/content_sao.cpp
src/content_sao.h
src/genericobject.cpp
src/genericobject.h
src/script/lua_api/l_object.cpp
src/script/lua_api/l_object.h
src/serverobject.h

index a65c53c1a3266c93dfef20c43266ecace6317dca..d2505284aaa1a6ff9a6dc551eef7ccd96f46a0b2 100644 (file)
@@ -2434,8 +2434,8 @@ 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)`
-* `get_animation()`: returns range, frame_speed and frame_blend
+* `set_animation({x=1,y=1}, frame_speed=15, frame_blend=0, frame_loop=true)`
+* `get_animation()`: returns range, frame_speed, frame_blend and frame_loop
 * `set_attach(parent, bone, position, rotation)`
     * `bone`: string
     * `position`: `{x=num, y=num, z=num}` (relative)
index 01be1422c8511139058080e6bfce368b31580bdd..d38cb892a3bc1966de794af59fd1f2ef841b4b73 100644 (file)
@@ -565,6 +565,7 @@ GenericCAO::GenericCAO(IGameDef *gamedef, ClientEnvironment *env):
                m_animation_range(v2s32(0,0)),
                m_animation_speed(15),
                m_animation_blend(0),
+               m_animation_loop(true),
                m_bone_position(std::map<std::string, core::vector2d<v3f> >()),
                m_attachment_bone(""),
                m_attachment_position(v3f(0,0,0)),
@@ -1465,9 +1466,18 @@ void GenericCAO::updateAnimation()
 {
        if(m_animated_meshnode == NULL)
                return;
-       m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y);
-       m_animated_meshnode->setAnimationSpeed(m_animation_speed);
+
+       if (m_animated_meshnode->getStartFrame() != m_animation_range.X ||
+               m_animated_meshnode->getEndFrame() != m_animation_range.Y)
+                       m_animated_meshnode->setFrameLoop(m_animation_range.X, m_animation_range.Y);
+       if (m_animated_meshnode->getAnimationSpeed() != m_animation_speed)
+               m_animated_meshnode->setAnimationSpeed(m_animation_speed);
        m_animated_meshnode->setTransitionTime(m_animation_blend);
+// Requires Irrlicht 1.8 or greater
+#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR > 1
+       if (m_animated_meshnode->getLoopMode() != m_animation_loop)
+               m_animated_meshnode->setLoopMode(m_animation_loop);
+#endif
 }
 
 void GenericCAO::updateBonePosition()
@@ -1633,6 +1643,8 @@ void GenericCAO::processMessage(const std::string &data)
                        m_animation_range = v2s32((s32)range.X, (s32)range.Y);
                        m_animation_speed = readF1000(is);
                        m_animation_blend = readF1000(is);
+                       // these are sent inverted so we get true when the server sends nothing
+                       m_animation_loop = !readU8(is);
                        updateAnimation();
                } else {
                        LocalPlayer *player = m_env->getLocalPlayer();
@@ -1641,6 +1653,8 @@ void GenericCAO::processMessage(const std::string &data)
                                m_animation_range = v2s32((s32)range.X, (s32)range.Y);
                                m_animation_speed = readF1000(is);
                                m_animation_blend = readF1000(is);
+                               // these are sent inverted so we get true when the server sends nothing
+                               m_animation_loop = !readU8(is);
                        }
                        // update animation only if local animations present
                        // and received animation is unknown (except idle animation)
index 58c373389868c977ee7f596d8ffb06bb4faa6c52..1e526d1cd4fedce30d8dd265709a98613d96480f 100644 (file)
@@ -86,6 +86,7 @@ private:
        v2s32 m_animation_range;
        int m_animation_speed;
        int m_animation_blend;
+       bool m_animation_loop;
        std::map<std::string, core::vector2d<v3f> > m_bone_position; // stores position and rotation for each bone name
        std::string m_attachment_bone;
        v3f m_attachment_position;
index 984d2ffa3468dbe610c7fce27b22fc135226d798..386b7e070d160fb4d083b452c67b48029d9eff70 100644 (file)
@@ -136,6 +136,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
        m_armor_groups_sent(false),
        m_animation_speed(0),
        m_animation_blend(0),
+       m_animation_loop(true),
        m_animation_sent(false),
        m_bone_position_sent(false),
        m_attachment_parent_id(0),
@@ -324,7 +325,8 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
 
        if(m_animation_sent == false){
                m_animation_sent = true;
-               std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend);
+               std::string str = gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
                m_messages_out.push(aom);
@@ -366,7 +368,8 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
                writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
                os<<serializeLongString(getPropertyPacket()); // message 1
                os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
-               os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
+               os<<serializeLongString(gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
                for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
                        os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
                }
@@ -533,19 +536,21 @@ ItemGroupList LuaEntitySAO::getArmorGroups()
        return m_armor_groups;
 }
 
-void LuaEntitySAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend)
+void LuaEntitySAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop)
 {
        m_animation_range = frame_range;
        m_animation_speed = frame_speed;
        m_animation_blend = frame_blend;
+       m_animation_loop = frame_loop;
        m_animation_sent = false;
 }
 
-void LuaEntitySAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend)
+void LuaEntitySAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop)
 {
        *frame_range = m_animation_range;
        *frame_speed = m_animation_speed;
        *frame_blend = m_animation_blend;
+       *frame_loop = m_animation_loop;
 }
 
 void LuaEntitySAO::setBonePosition(const std::string &bone, v3f position, v3f rotation)
@@ -733,6 +738,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
        m_is_singleplayer(is_singleplayer),
        m_animation_speed(0),
        m_animation_blend(0),
+       m_animation_loop(true),
        m_animation_sent(false),
        m_bone_position_sent(false),
        m_attachment_parent_id(0),
@@ -828,7 +834,8 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
                writeU8(os, 6 + m_bone_position.size()); // number of messages stuffed in here
                os<<serializeLongString(getPropertyPacket()); // message 1
                os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
-               os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
+               os<<serializeLongString(gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3
                for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
                        os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
                }
@@ -967,7 +974,8 @@ void PlayerSAO::step(float dtime, bool send_recommended)
 
        if(m_animation_sent == false){
                m_animation_sent = true;
-               std::string str = gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend);
+               std::string str = gob_cmd_update_animation(
+                       m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop);
                // create message and add to list
                ActiveObjectMessage aom(getId(), true, str);
                m_messages_out.push(aom);
@@ -1166,20 +1174,22 @@ ItemGroupList PlayerSAO::getArmorGroups()
        return m_armor_groups;
 }
 
-void PlayerSAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend)
+void PlayerSAO::setAnimation(v2f frame_range, float frame_speed, float frame_blend, bool frame_loop)
 {
        // store these so they can be updated to clients
        m_animation_range = frame_range;
        m_animation_speed = frame_speed;
        m_animation_blend = frame_blend;
+       m_animation_loop = frame_loop;
        m_animation_sent = false;
 }
 
-void PlayerSAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend)
+void PlayerSAO::getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend, bool *frame_loop)
 {
        *frame_range = m_animation_range;
        *frame_speed = m_animation_speed;
        *frame_blend = m_animation_blend;
+       *frame_loop = m_animation_loop;
 }
 
 void PlayerSAO::setBonePosition(const std::string &bone, v3f position, v3f rotation)
index 2417880660df13659995a384494b492019181856..f61566665310061e5b316536a52300988ff89e9a 100644 (file)
@@ -59,8 +59,8 @@ public:
        s16 getHP() const;
        void setArmorGroups(const ItemGroupList &armor_groups);
        ItemGroupList getArmorGroups();
-       void setAnimation(v2f frame_range, float frame_speed, float frame_blend);
-       void getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend);
+       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 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);
@@ -106,6 +106,7 @@ private:
        v2f m_animation_range;
        float m_animation_speed;
        float m_animation_blend;
+       bool m_animation_loop;
        bool m_animation_sent;
 
        std::map<std::string, core::vector2d<v3f> > m_bone_position;
@@ -197,8 +198,8 @@ public:
        void setBreath(u16 breath);
        void setArmorGroups(const ItemGroupList &armor_groups);
        ItemGroupList getArmorGroups();
-       void setAnimation(v2f frame_range, float frame_speed, float frame_blend);
-       void getAnimation(v2f *frame_range, float *frame_speed, float *frame_blend);
+       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 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);
@@ -312,6 +313,7 @@ private:
        v2f m_animation_range;
        float m_animation_speed;
        float m_animation_blend;
+       bool m_animation_loop;
        bool m_animation_sent;
 
        std::map<std::string, core::vector2d<v3f> > m_bone_position; // Stores position and rotation for each bone name
index 5daba55edfeea4fda0cc4e34b97af21ef0eabeab..90e8cf3d35c537a344e523eedf5e5f141059f4ab 100644 (file)
@@ -133,7 +133,7 @@ std::string gob_cmd_update_physics_override(float physics_override_speed, float
        return os.str();
 }
 
-std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend)
+std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend, bool frame_loop)
 {
        std::ostringstream os(std::ios::binary);
        // command 
@@ -142,6 +142,8 @@ std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_
        writeV2F1000(os, frames);
        writeF1000(os, frame_speed);
        writeF1000(os, frame_blend);
+       // these are sent inverted so we get true when the server sends nothing
+       writeU8(os, !frame_loop);
        return os.str();
 }
 
index b36a3830d88511a3bdd3894d6ceb2217a099bb31..b92570831475025bb973fded7dc216ff05182a71 100644 (file)
@@ -69,7 +69,7 @@ std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups);
 std::string gob_cmd_update_physics_override(float physics_override_speed,
                float physics_override_jump, float physics_override_gravity, bool sneak, bool sneak_glitch);
 
-std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend);
+std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend, bool frame_loop);
 
 std::string gob_cmd_update_bone_position(std::string bone, v3f position, v3f rotation);
 
index 48d054dcdb0ffebc0ac39868bb726ea1e832e4aa..4b1cc39fb9775049eb43908ec80b32e99d8fffe2 100644 (file)
@@ -449,7 +449,7 @@ int ObjectRef::l_get_physics_override(lua_State *L)
        return 1;
 }
 
-// set_animation(self, frame_range, frame_speed, frame_blend)
+// set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
 int ObjectRef::l_set_animation(lua_State *L)
 {
        NO_MAP_LOCK_REQUIRED;
@@ -466,7 +466,10 @@ int ObjectRef::l_set_animation(lua_State *L)
        float frame_blend = 0;
        if(!lua_isnil(L, 4))
                frame_blend = lua_tonumber(L, 4);
-       co->setAnimation(frames, frame_speed, frame_blend);
+       bool frame_loop = true;
+       if(lua_isboolean(L, 5))
+               frame_loop = lua_toboolean(L, 5);
+       co->setAnimation(frames, frame_speed, frame_blend, frame_loop);
        return 0;
 }
 
@@ -482,12 +485,14 @@ int ObjectRef::l_get_animation(lua_State *L)
        v2f frames = v2f(1,1);
        float frame_speed = 15;
        float frame_blend = 0;
-       co->getAnimation(&frames, &frame_speed, &frame_blend);
+       bool frame_loop = true;
+       co->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop);
 
        push_v2f(L, frames);
        lua_pushnumber(L, frame_speed);
        lua_pushnumber(L, frame_blend);
-       return 3;
+       lua_pushboolean(L, frame_loop);
+       return 4;
 }
 
 // set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
index 02bb06eccc34cd93093756629e62baee65ab7dfa..9e4a62058fbdd51c92722ee38347473fab5c63c0 100644 (file)
@@ -111,7 +111,7 @@ private:
        // get_physics_override(self)
        static int l_get_physics_override(lua_State *L);
 
-       // set_animation(self, frame_range, frame_speed, frame_blend)
+       // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
        static int l_set_animation(lua_State *L);
 
        // get_animation(self)
index 5de1071d17d5065d2af77ceed8e286abf8b53905..7204fe3aedd2416922f85b5b05160273987d6edf 100644 (file)
@@ -151,9 +151,9 @@ public:
        { return ItemGroupList(); }
        virtual void setPhysicsOverride(float physics_override_speed, float physics_override_jump, float physics_override_gravity)
        {}
-       virtual void setAnimation(v2f frames, float frame_speed, float frame_blend)
+       virtual void setAnimation(v2f frames, float frame_speed, float frame_blend, bool frame_loop)
        {}
-       virtual void getAnimation(v2f *frames, float *frame_speed, float *frame_blend)
+       virtual void getAnimation(v2f *frames, float *frame_speed, float *frame_blend, bool *frame_loop)
        {}
        virtual void setBonePosition(const std::string &bone, v3f position, v3f rotation)
        {}