void	imotion_position::state_end( )
{
	VERIFY( shell );
	inherited::state_end( );
	
	CPhysicsShellHolder *obj= static_cast<CPhysicsShellHolder*>( shell->get_ElementByStoreOrder( 0 )->PhysicsRefObject() );
	VERIFY( obj );
	obj->processing_deactivate();
	shell->Enable();
	shell->setForce( Fvector().set( 0.f, 0.f, 0.f ) );
	shell->setTorque( Fvector().set( 0.f, 0.f, 0.f ) );

	shell->AnimToVelocityState( end_delta, default_l_limit * 10, default_w_limit * 10 );
#ifdef	DEBUG
	dbg_draw_state_end( shell );
#endif
	shell->remove_ObjectContactCallback( get_depth );
	IKinematics *K = shell->PKinematics();
	disable_update( false );
	disable_bone_calculation( *K, false );
	K->SetUpdateCallback( saved_visual_callback );
	deinit_bones();

	save_fixes( K );
	
	shell->EnabledCallbacks( TRUE );

	restore_fixes( );

	VERIFY( K );

	IKinematicsAnimated	*KA = smart_cast<IKinematicsAnimated*>( shell->PKinematics() );
	VERIFY( KA );
	update_callback.motion = 0;
	KA->SetUpdateTracksCalback( 0 );

#if 0

			DBG_OpenCashedDraw();
			shell->dbg_draw_geometry( 0.02, D3DCOLOR_ARGB( 255, 0, 255, 0 )  );
			DBG_DrawBones( *shell->get_ElementByStoreOrder( 0 )->PhysicsRefObject() );
			DBG_ClosedCashedDraw( 50000 );

#endif

	u16 root = K->LL_GetBoneRoot();
	if( root!=0 )
	{
		K->LL_GetTransform( 0 ).set( Fidentity );
		K->LL_SetBoneVisible( 0, FALSE, FALSE );
		u16 bip01 = K->LL_BoneID( "bip01" );
		if( bip01 != BI_NONE && bip01 != root )
		{
			K->LL_GetTransform( bip01 ).set( Fidentity );
			K->LL_SetBoneVisible( bip01, FALSE, FALSE );
		}
	}

	K->CalculateBones_Invalidate();
	K->CalculateBones( true );

#if 0 

			DBG_OpenCashedDraw();
			shell->dbg_draw_geometry( 0.02, D3DCOLOR_ARGB( 255, 0, 0, 255 )  );
			DBG_DrawBones( *shell->get_ElementByStoreOrder( 0 )->PhysicsRefObject() );
			DBG_ClosedCashedDraw( 50000 );

#endif
}
void imotion_position::state_start( )
{
	VERIFY( shell );
	inherited::state_start( );
	
	IKinematics			*K	= shell->PKinematics();
	saved_visual_callback = K->GetUpdateCallback();
	K->SetUpdateCallback( 0 );
	IKinematicsAnimated	*KA = smart_cast<IKinematicsAnimated*>( shell->PKinematics() );
	VERIFY( KA );
	KA->SetUpdateTracksCalback( &update_callback );
	update_callback.motion = this;
	struct get_controled_blend: 
		public IterateBlendsCallback,
		private boost::noncopyable
		
	{
		CBlend					*blend;
		const	PlayCallback	cb;
		get_controled_blend(const	PlayCallback	_cb):blend( 0 ),cb(_cb){}
		virtual	void	operator () ( CBlend &B )
		{
			if( cb == B.Callback && B.bone_or_part == 0 )
				blend = &B;
		}
	} get_blend(anim_callback);
	
	KA->LL_IterateBlends( get_blend );
#ifdef DEBUG
	if(!get_blend.blend)
	{
		Msg( "bad animation params : %p", anim_callback );
		KA->LL_DumpBlends_dbg();
		NODEFAULT;
	}
#endif
	VERIFY( get_blend.blend );
	const CBlend &B = *get_blend.blend;

	blend = get_blend.blend;

	VERIFY2( B.stop_at_end, 
		make_string( "can not use cyclic anim in death animth motion: %s", 
		KA->LL_MotionDefName_dbg( B.motionID ).first ) 
	);
	time_to_end = B.timeTotal - (SAMPLE_SPF+EPS) - B.timeCurrent;
	time_to_end/=B.speed;
	shell->add_ObjectContactCallback( get_depth );
	/*
	collide();
	if( flags.test( fl_switch_dm_toragdoll ) )
	{
		flags.assign( 0 );
		shell->remove_ObjectContactCallback( get_depth );
		return;
	}
*/
	
	if( !is_enabled( ) )
				return;
	CPhysicsShellHolder *obj= static_cast<CPhysicsShellHolder*>( shell->get_ElementByStoreOrder( 0 )->PhysicsRefObject() );
	VERIFY( obj );
	obj->processing_activate();
	shell->Disable( );
	//K->LL_SetBoneRoot( 0 );
	shell->EnabledCallbacks( FALSE );
	init_bones();


	shell->mXFORM.set( obj->XFORM() );
	disable_update( true );
	disable_bone_calculation( *K, true );
	//K->CalculateBones_Invalidate();
	collide_not_move( *KA );
	if(flags.test(fl_switch_dm_toragdoll))
	{
		interactive_motion_diagnostic("stoped immediately");
		switch_to_free	( );
		flags.set(fl_not_played,TRUE);
		return;
	}
	move( float( Device.dwTimeDelta )/1000, *KA );
	if(flags.test(fl_switch_dm_toragdoll))
			switch_to_free	( );
	//K->CalculateBones_Invalidate();
}