e54fb11dc1436bb4e6a3a326b09b17a44df92893
[blender-staging.git] / source / gameengine / Ketsji / KX_IPO_SGController.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Scenegraph controller for ipos.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #ifdef WIN32
39 // This warning tells us about truncation of __long__ stl-generated names.
40 // It can occasionally cause DevStudio to have internal compiler warnings.
41 #pragma warning( disable : 4786 )     
42 #endif
43
44 #include "KX_IPO_SGController.h"
45 #include "KX_ScalarInterpolator.h"
46 #include "KX_GameObject.h"
47 #include "KX_IPhysicsController.h"
48
49 // All objects should start on frame 1! Will we ever need an object to 
50 // start on another frame, the 1.0 should change.
51 KX_IpoSGController::KX_IpoSGController() 
52 : m_modify_position(false),
53   m_modify_orientation(false),
54   m_modify_scaling(false),
55   m_ipo_as_force(false),
56   m_force_ipo_acts_local(false),
57   m_modified(true),
58   m_ipotime(1.0)
59 {
60         m_game_object = NULL;
61
62 }
63
64
65 void KX_IpoSGController::SetOption(
66         int option,
67         int value)
68 {
69         switch (option) {
70         case SG_CONTR_IPO_IPO_AS_FORCE:
71                 m_ipo_as_force = (value != 0);
72                 m_modified = true;
73                 break;
74         case SG_CONTR_IPO_FORCES_ACT_LOCAL:
75                 m_force_ipo_acts_local = (value != 0);
76                 m_modified = true;
77                 break;
78         default:
79                 ; /* just ignore the rest */
80         }
81 }
82
83         void 
84 KX_IpoSGController::UpdateSumoReference(
85         )
86 {
87         if (m_game_object) {
88
89         }
90 }
91
92         void 
93 KX_IpoSGController::SetGameObject(
94         KX_GameObject* go
95         )
96 {
97         m_game_object = go;
98 }
99
100
101
102 bool KX_IpoSGController::Update(double currentTime)
103 {
104         if (m_modified)
105         {
106                 T_InterpolatorList::iterator i;
107                 for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
108                         (*i)->Execute(m_ipotime);//currentTime);
109                 }
110                 
111                 SG_Spatial* ob = (SG_Spatial*)m_pObject;
112                 
113                 if (m_modify_position) {
114                         if (m_ipo_as_force) {
115                                 
116                                 if (m_game_object && ob) {
117                                         m_game_object->GetPhysicsController()->ApplyForce(m_force_ipo_acts_local ?
118                                                 ob->GetWorldOrientation() * m_ipo_xform.GetPosition() :
119                                                 m_ipo_xform.GetPosition(), false);
120                                 }
121
122                         } else {
123                                 ob->SetLocalPosition(m_ipo_xform.GetPosition());
124                         }
125                 }
126                 if (m_modify_orientation) {
127                         if (m_ipo_as_force) {
128                                 
129                                 if (m_game_object && ob) {
130                                         m_game_object->ApplyTorque(m_force_ipo_acts_local ?
131                                                 ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
132                                                 m_ipo_xform.GetEulerAngles(), false);
133                                 }
134
135                         } else {
136                                 ob->SetLocalOrientation(MT_Matrix3x3(m_ipo_xform.GetEulerAngles()));
137                         }
138                 }
139                 if (m_modify_scaling)
140                         ob->SetLocalScale(m_ipo_xform.GetScaling());
141
142                 m_modified=false;
143         }
144         return false;
145 }
146
147
148 void KX_IpoSGController::AddInterpolator(KX_IInterpolator* interp)
149 {
150         this->m_interpolators.push_back(interp);
151 }
152
153 SG_Controller*  KX_IpoSGController::GetReplica(class SG_Node* destnode)
154 {
155         KX_IpoSGController* iporeplica = new KX_IpoSGController(*this);
156         // clear object that ipo acts on in the replica.
157         iporeplica->ClearObject();
158
159         // dirty hack, ask Gino for a better solution in the ipo implementation
160         // hacken en zagen, in what we call datahiding, not written for replication :(
161
162         T_InterpolatorList oldlist = m_interpolators;
163         iporeplica->m_interpolators.clear();
164
165         T_InterpolatorList::iterator i;
166         for (i = oldlist.begin(); !(i == oldlist.end()); ++i) {
167                 KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i));
168                 iporeplica->AddInterpolator(copyipo);
169
170                 MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
171                 int orgbase = (int)&m_ipo_xform;
172                 int orgloc = (int)scaal;
173                 int offset = orgloc-orgbase;
174                 int newaddrbase = (int)&iporeplica->m_ipo_xform;
175                 newaddrbase += offset;
176                 MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
177                 copyipo->SetNewTarget((MT_Scalar*)blaptr);
178         }
179         
180         return iporeplica;
181 }
182
183 KX_IpoSGController::~KX_IpoSGController()
184 {
185
186         T_InterpolatorList::iterator i;
187         for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
188                 delete (*i);
189         }
190         
191 }