Cycles: svn merge -r41225:41232 ^/trunk/blender
[blender.git] / source / gameengine / Ketsji / BL_Action.cpp
index 6fe989296fdb9b0406186bd7c6d9ae3da6fd9042..2da3fdfd225f26e0e430466a51c1d3c0ea7cc5ce 100644 (file)
@@ -1,6 +1,4 @@
-/**
- * $Id$
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -49,25 +47,25 @@ extern "C" {
 
 BL_Action::BL_Action(class KX_GameObject* gameobj)
 :
+       m_action(NULL),
+       m_pose(NULL),
+       m_blendpose(NULL),
+       m_blendinpose(NULL),
+       m_ptrrna(NULL),
        m_obj(gameobj),
        m_startframe(0.f),
        m_endframe(0.f),
-       m_blendin(0.f),
-       m_playmode(0),
        m_endtime(0.f),
        m_localtime(0.f),
+       m_blendin(0.f),
        m_blendframe(0.f),
        m_blendstart(0.f),
        m_speed(0.f),
        m_priority(0),
+       m_playmode(0),
        m_ipo_flags(0),
-       m_pose(NULL),
-       m_blendpose(NULL),
-       m_blendinpose(NULL),
-       m_sg_contr(NULL),
-       m_ptrrna(NULL),
-       m_action(NULL),
-       m_done(true)
+       m_done(true),
+       m_calc_localtime(true)
 {
        if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
        {
@@ -97,13 +95,22 @@ BL_Action::~BL_Action()
                game_free_pose(m_blendpose);
        if (m_blendinpose)
                game_free_pose(m_blendinpose);
-       if (m_sg_contr)
-       {
-               m_obj->GetSGNode()->RemoveSGController(m_sg_contr);
-               delete m_sg_contr;
-       }
        if (m_ptrrna)
                delete m_ptrrna;
+       ClearControllerList();
+}
+
+void BL_Action::ClearControllerList()
+{
+       // Clear out the controller list
+       std::vector<SG_Controller*>::iterator it;
+       for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
+       {
+               m_obj->GetSGNode()->RemoveSGController((*it));
+               delete *it;
+       }
+
+       m_sg_contr_list.clear();
 }
 
 bool BL_Action::Play(const char* name,
@@ -135,10 +142,30 @@ bool BL_Action::Play(const char* name,
 
        if (prev_action != m_action)
        {
+               // First get rid of any old controllers
+               ClearControllerList();
+
                // Create an SG_Controller
-               m_sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
-               m_obj->GetSGNode()->AddSGController(m_sg_contr);
-               m_sg_contr->SetObject(m_obj->GetSGNode());
+               SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
+               m_sg_contr_list.push_back(sg_contr);
+               m_obj->GetSGNode()->AddSGController(sg_contr);
+               sg_contr->SetObject(m_obj->GetSGNode());
+
+               // Extra controllers
+               if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
+               {
+                       sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
+                       m_sg_contr_list.push_back(sg_contr);
+                       m_obj->GetSGNode()->AddSGController(sg_contr);
+                       sg_contr->SetObject(m_obj->GetSGNode());
+               }
+               else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
+               {
+                       sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
+                       m_sg_contr_list.push_back(sg_contr);
+                       m_obj->GetSGNode()->AddSGController(sg_contr);
+                       sg_contr->SetObject(m_obj->GetSGNode());
+               }
        }
        
        m_ipo_flags = ipo_flags;
@@ -196,11 +223,15 @@ bool BL_Action::IsDone()
 
 void BL_Action::InitIPO()
 {
-               // Initialize the IPO
-               m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
-               m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
-               m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
-               m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
+       // Initialize the IPOs
+       std::vector<SG_Controller*>::iterator it;
+       for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++)
+       {
+               (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
+               (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
+               (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
+               (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
+       }
 }
 
 bAction *BL_Action::GetAction()
@@ -215,24 +246,25 @@ float BL_Action::GetFrame()
 
 void BL_Action::SetFrame(float frame)
 {
-       float dt;
-
        // Clamp the frame to the start and end frame
        if (frame < min(m_startframe, m_endframe))
                frame = min(m_startframe, m_endframe);
        else if (frame > max(m_startframe, m_endframe))
                frame = max(m_startframe, m_endframe);
        
-       // We don't set m_localtime directly since it's recalculated
-       // in the next update. So, we modify the value (m_starttime) 
-       // used to calculate m_localtime the next time SetLocalTime() is called.
-
-       dt = frame-m_startframe;
+       m_localtime = frame;
+       m_calc_localtime = false;
+}
 
-       if (m_endframe < m_startframe)
-               dt = -dt;
+void BL_Action::SetPlayMode(short play_mode)
+{
+       m_playmode = play_mode;
+}
 
-       m_starttime -= dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
+void BL_Action::SetTimes(float start, float end)
+{
+       m_startframe = start;
+       m_endframe = end;
 }
 
 void BL_Action::SetLocalTime(float curtime)
@@ -245,6 +277,14 @@ void BL_Action::SetLocalTime(float curtime)
        m_localtime = m_startframe + dt;
 }
 
+void BL_Action::ResetStartTime(float curtime)
+{
+       float dt = m_localtime - m_startframe;
+
+       m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
+       SetLocalTime(curtime);
+}
+
 void BL_Action::IncrementBlending(float curtime)
 {
        // Setup m_blendstart if we need to
@@ -285,7 +325,14 @@ void BL_Action::Update(float curtime)
                return;
 
        curtime -= KX_KetsjiEngine::GetSuspendedDelta();
-       SetLocalTime(curtime);
+
+       if (m_calc_localtime)
+               SetLocalTime(curtime);
+       else
+       {
+               ResetStartTime(curtime);
+               m_calc_localtime = true;
+       }
 
        // Handle wrap around
        if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
@@ -312,9 +359,6 @@ void BL_Action::Update(float curtime)
 
                        break;
                }
-
-               if (!m_done && m_sg_contr)
-                       InitIPO();
        }
 
        if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
@@ -397,8 +441,6 @@ void BL_Action::Update(float curtime)
                        obj->SetActiveAction(NULL, 0, curtime);
                }
 
-
-               InitIPO();
                m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD);
        }
 }