Index: /trunk/nv/formats/md5_loader.hh
===================================================================
--- /trunk/nv/formats/md5_loader.hh	(revision 287)
+++ /trunk/nv/formats/md5_loader.hh	(revision 288)
@@ -72,5 +72,5 @@
 		size_t get_num_joints() const { return m_num_joints; }
 		size_t get_frame_rate() const { return m_frame_rate; }
-		size_t get_frame_count() const { return m_num_frames; }
+		float get_duration() const { return (float)m_num_frames; }
 
 	protected:
Index: /trunk/nv/gfx/keyframed_mesh.hh
===================================================================
--- /trunk/nv/gfx/keyframed_mesh.hh	(revision 287)
+++ /trunk/nv/gfx/keyframed_mesh.hh	(revision 288)
@@ -16,22 +16,4 @@
 {
 
-	class keyframed_animation_entry : public animation_entry
-	{
-	public:
-		friend class keyframed_mesh;
-
-		keyframed_animation_entry( const std::string& name, uint32 a_start, uint32 a_frames, uint32 a_fps, bool a_loop )
-			: animation_entry( name ), m_start( a_start ), m_frames( a_frames ), m_fps( a_fps ), m_looping( a_loop ) {}
-		virtual uint32 get_frame_rate() const { return m_fps; }
-		virtual float get_duration() const { return (float)m_frames; }
-		virtual bool is_looping() const { return m_looping; }
-	protected:
-		uint32 m_start;
-		uint32 m_frames;
-		uint32 m_fps;
-		bool   m_looping;
-	};
-
-
 	class keyframed_mesh : public animated_mesh
 	{
@@ -43,10 +25,10 @@
 		virtual transform get_node_transform( uint32 node_id ) const;
 		virtual mat4 get_node_matrix( uint32 node_id ) const;
-		virtual void setup_animation( uint32 start, uint32 count, uint32 fps, bool loop );
-		virtual void set_frame( uint32 frame );
 		virtual void update_animation( animation_entry*, uint32 a_anim_time );
 		virtual void update( program* a_program ) const;
 		virtual ~keyframed_mesh();
 	protected:
+		virtual void set_frame( uint32 frame );
+
 		struct vertex_pn
 		{
@@ -62,11 +44,7 @@
 		const mesh_nodes_data* m_tag_map;
 
-		uint32 m_start_frame;
-		uint32 m_stop_frame;
 		uint32 m_last_frame;
 		uint32 m_next_frame;
-		uint32 m_fps;
 		f32    m_interpolation;
-		bool   m_looping;
 		bool   m_active;
 
Index: /trunk/nv/gfx/skeletal_mesh.hh
===================================================================
--- /trunk/nv/gfx/skeletal_mesh.hh	(revision 287)
+++ /trunk/nv/gfx/skeletal_mesh.hh	(revision 288)
@@ -23,13 +23,11 @@
 
 		skeletal_animation_entry( const std::string& name, md5_animation* a_animation, bool a_looping ) 
-			: animation_entry( name ), m_animation( a_animation ), m_looping( a_looping ) {}
-		virtual uint32 get_frame_rate() const { return m_animation->get_frame_rate(); }
-		virtual uint32 get_frame_count() const { return m_animation->get_frame_count(); }
-		virtual bool is_looping() const { return m_looping; }
+			: animation_entry( name, a_looping, a_animation->get_frame_rate(), 0.0f, a_animation->get_duration() ), m_animation( a_animation ) {}
+		skeletal_animation_entry( const std::string& name, md5_animation* a_animation, float time_start, float time_end, bool a_looping )
+			: animation_entry( name, a_looping, a_animation->get_frame_rate(), time_start, time_end ), m_animation( a_animation ) {}
 		uint32 get_num_joints() const { return m_animation->get_num_joints();}
 		void update_skeleton( transform* tr, float time ) const { return m_animation->update_skeleton( tr, time );}
 	protected:
 		md5_animation* m_animation;
-		bool           m_looping;
 	};
 
@@ -56,13 +54,26 @@
  	{
  	public:
- 		skeletal_animation_entry_gpu( const std::string& name, const mesh_nodes_data* anim, bool a_looping );
- 		virtual uint32 get_frame_rate() const { return m_node_data->get_frame_rate(); }
- 		virtual float get_duration() const { return m_node_data->get_duration(); }
- 		virtual bool is_looping() const { return m_looping; }
+ 		skeletal_animation_entry_gpu( const std::string& name, const mesh_nodes_data* anim, bool a_looping )
+			: animation_entry( name, a_looping, anim->get_frame_rate(), 0.0f, anim->get_duration() )
+			, m_node_data( anim )
+		{
+			initialize();
+		}
+
+		skeletal_animation_entry_gpu( const std::string& name, const mesh_nodes_data* anim, float time_start, float time_end, bool a_looping )
+			: animation_entry( name, a_looping, anim->get_frame_rate(), time_start, time_end )
+			, m_node_data( anim )
+		{
+			initialize();
+		}
+
 		void prepare( const mesh_nodes_data* bones );
 		void update_skeleton( mat4* tr, uint32 time ) const;
 		~skeletal_animation_entry_gpu();
  	protected:
+		void initialize();
 		void animate_rec( mat4* data, float time, uint32 node_id, const mat4& parent_mat ) const;
+
+	protected:
 		const mesh_nodes_data* m_node_data;
 		std::vector< uint32 >* m_children;
@@ -70,5 +81,4 @@
 		mat4* m_offsets;
 		bool m_prepared;
- 		bool m_looping;
  	};
 
Index: /trunk/nv/interface/animated_mesh.hh
===================================================================
--- /trunk/nv/interface/animated_mesh.hh	(revision 287)
+++ /trunk/nv/interface/animated_mesh.hh	(revision 288)
@@ -25,12 +25,20 @@
 	{
 	public:
-		animation_entry( const std::string& name ) : m_name( name ) {}
-		virtual const std::string& get_name() const { return m_name; }
-		virtual uint32 get_frame_rate() const = 0;
-		virtual float get_duration() const = 0;
-		virtual bool is_looping() const = 0;
+		animation_entry( const std::string& name, bool looping, uint32 frame_rate, float a_start, float a_end ) : m_name( name ), m_looping( looping ), m_frame_rate( frame_rate ),
+		m_start( a_start ), m_end( a_end ), m_duration( m_end - m_start ) {}
+		const std::string& get_name() const { return m_name; }
+		uint32 get_frame_rate() const { return m_frame_rate; }
+		float get_duration() const { return m_duration; }
+		float get_start() const { return m_start; }
+		float get_end() const  { return m_end; }
+		bool is_looping() const { return m_looping; }
 		virtual ~animation_entry() {}
 	protected:
 		std::string m_name;
+		bool   m_looping;
+		uint32 m_frame_rate;
+		float  m_start;
+		float  m_end;
+		float  m_duration;
 	};
 
Index: /trunk/nv/lua/lua_state.hh
===================================================================
--- /trunk/nv/lua/lua_state.hh	(revision 287)
+++ /trunk/nv/lua/lua_state.hh	(revision 288)
@@ -228,4 +228,5 @@
 			unsigned get_unsigned( const std::string& element, unsigned defval = 0 );
 			double get_double( const std::string& element, double defval = 0.0 );
+			float get_float( const std::string& element, float defval = 0.0 );
 			bool get_boolean( const std::string& element, bool defval = false );
 
Index: /trunk/src/gfx/keyframed_mesh.cc
===================================================================
--- /trunk/src/gfx/keyframed_mesh.cc	(revision 287)
+++ /trunk/src/gfx/keyframed_mesh.cc	(revision 288)
@@ -19,11 +19,7 @@
 	, m_mesh_data( a_data )
 	, m_tag_map( a_tag_map )
-	, m_start_frame( false )
-	, m_stop_frame( false )
 	, m_last_frame( 0 )
 	, m_next_frame( 0 )
-	, m_fps( 0 )
 	, m_interpolation( 0.0f )
-	, m_looping( false )
 	, m_active( false )
 {
@@ -56,16 +52,4 @@
 }
 
-void keyframed_mesh::setup_animation( uint32 start, uint32 count, uint32 fps, bool loop )
-{
-	m_start_frame   = start;
-	m_stop_frame    = start+count-1;
-	m_looping       = loop;
-	m_fps           = fps;
-	m_active        = count > 1;
-	m_last_frame    = start;
-	m_next_frame    = (count > 1 ? start + 1 : start );
-	m_interpolation = 0.0f;
-}
-
 void nv::keyframed_mesh::set_frame( uint32 frame )
 {
@@ -76,31 +60,29 @@
 }
 
-void nv::keyframed_mesh::update_animation( animation_entry*, uint32 a_anim_time )
+void nv::keyframed_mesh::update_animation( animation_entry* anim, uint32 a_anim_time )
 {
 	if ( m_active )
 	{
-		uint32 f_diff = (m_stop_frame - m_start_frame);
-		float  f_time = 1000 / (float)m_fps;
-		float f_max   = ( m_looping ? ( f_diff + 1 ) : f_diff ) * f_time;
-		uint32 time   = a_anim_time;
-		if ( time >= f_max )
+		float tick_time = ( (float)a_anim_time * 0.001f ) * anim->get_frame_rate();
+		float duration  = anim->is_looping() ? anim->get_duration() + 1.0f : anim->get_duration();
+		if ( tick_time >= duration )
 		{
-			if ( m_looping )
+			if ( anim->is_looping() )
 			{
-				time = time % static_cast< uint32 >( f_max );
+				tick_time = fmodf( tick_time, duration );
 			}
 			else
 			{
 				m_active     = false;
-				m_last_frame = m_stop_frame;
-				m_next_frame = m_stop_frame;
+				m_last_frame = (uint32)anim->get_end();
+				m_next_frame = m_last_frame;
+				m_interpolation = 0.0f;
+				return;
 			}
 		}
-		float f_pos   = time / f_time;
-
-		m_last_frame    = (uint32)glm::floor( f_pos ) + m_start_frame;
+		m_last_frame    = (uint32)( glm::floor( tick_time ) + anim->get_start() );
 		m_next_frame    = m_last_frame + 1;
-		if ( m_next_frame > m_stop_frame ) m_next_frame = m_start_frame;
-		m_interpolation = f_pos - glm::floor( f_pos );
+		if ( m_next_frame > (uint32)anim->get_end() ) m_next_frame = (uint32)anim->get_start();
+		m_interpolation = tick_time - glm::floor( tick_time );
 	}
 }
@@ -121,7 +103,8 @@
 	if ( a_anim )
 	{
-		keyframed_animation_entry * anim = down_cast<keyframed_animation_entry>(a_anim);
-		m_active = true;
-		setup_animation( anim->m_start, anim->m_frames, anim->m_fps, anim->m_looping );
+		m_active        = true;
+		m_last_frame    = 0;
+		m_next_frame    = 0;
+		m_interpolation = 0.0f;
 	}
 	else
Index: /trunk/src/gfx/skeletal_mesh.cc
===================================================================
--- /trunk/src/gfx/skeletal_mesh.cc	(revision 287)
+++ /trunk/src/gfx/skeletal_mesh.cc	(revision 288)
@@ -33,7 +33,7 @@
 		skeletal_animation_entry * anim = (skeletal_animation_entry*)a_anim;
 		float frame_duration = 1000.f / (float)anim->get_frame_rate();
-		uint32 anim_duration = uint32( frame_duration * (float)anim->get_frame_count() );
-		uint32 new_time = a_anim_time % anim_duration;
-		anim->update_skeleton( m_transform.data(), (float)new_time * 0.001f );
+		float anim_duration = frame_duration * anim->get_duration();
+		float new_time = fmodf( (float)a_anim_time, anim_duration );
+		anim->update_skeleton( m_transform.data(), new_time * 0.001f );
 
 		//m_mesh_data->apply( m_transform.data() );
@@ -87,15 +87,10 @@
 }
 
-
-nv::skeletal_animation_entry_gpu::skeletal_animation_entry_gpu( const std::string& name, const mesh_nodes_data* anim, bool a_looping ) 
-	: animation_entry( name )
-	, m_node_data( anim )
-{
-	uint32 node_count = m_node_data->get_count();
-
+void nv::skeletal_animation_entry_gpu::initialize()
+{
 	m_prepared  = false;
-	m_looping   = a_looping;
 	m_children  = nullptr;
 	m_offsets   = nullptr;
+	uint32 node_count = m_node_data->get_count();
 	m_bone_ids  = new sint16[ node_count ];
 
Index: /trunk/src/lua/lua_state.cc
===================================================================
--- /trunk/src/lua/lua_state.cc	(revision 287)
+++ /trunk/src/lua/lua_state.cc	(revision 288)
@@ -148,5 +148,5 @@
 {
 	lua_getfield( m_state, -1, element.c_str() );
-	bool result = lua_isnil( m_state, -1 );
+	bool result = !( lua_isnil( m_state, -1 ) );
 	lua_pop( m_state, 1 );
 	return result;
@@ -189,4 +189,13 @@
 	lua_getfield( m_state, -1, element.c_str() );
 	double result = lua_type( m_state, -1 ) == LUA_TNUMBER ? lua_tonumber( m_state, -1 ) : defval;
+	lua_pop( m_state, 1 );
+	return result;
+}
+
+
+float nv::lua::table_guard::get_float( const std::string& element, float defval /*= 0.0 */ )
+{
+	lua_getfield( m_state, -1, element.c_str() );
+	float result = lua_type( m_state, -1 ) == LUA_TNUMBER ? (float)lua_tonumber( m_state, -1 ) : defval;
 	lua_pop( m_state, 1 );
 	return result;
