diff --git a/doc/lua_api.txt b/doc/lua_api.txt index a65c53c1a..d2505284a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -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) diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 01be1422c..d38cb892a 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -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 >()), 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) diff --git a/src/content_cao.h b/src/content_cao.h index 58c373389..1e526d1cd 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -86,6 +86,7 @@ private: v2s32 m_animation_range; int m_animation_speed; int m_animation_blend; + bool m_animation_loop; std::map > m_bone_position; // stores position and rotation for each bone name std::string m_attachment_bone; v3f m_attachment_position; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 984d2ffa3..386b7e070 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -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< >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ os< >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ os< > 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 > m_bone_position; // Stores position and rotation for each bone name diff --git a/src/genericobject.cpp b/src/genericobject.cpp index 5daba55ed..90e8cf3d3 100644 --- a/src/genericobject.cpp +++ b/src/genericobject.cpp @@ -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(); } diff --git a/src/genericobject.h b/src/genericobject.h index b36a3830d..b92570831 100644 --- a/src/genericobject.h +++ b/src/genericobject.h @@ -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); diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 48d054dcd..4b1cc39fb 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -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) diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index 02bb06ecc..9e4a62058 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -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) diff --git a/src/serverobject.h b/src/serverobject.h index 5de1071d1..7204fe3ae 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -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) {}