Ken's 64bit patches weren't merged over to orange for some reason.
[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 #if defined(_WIN64)
39 typedef unsigned __int64 uint_ptr;
40 #else
41 typedef unsigned long uint_ptr;
42 #endif
43
44 #ifdef WIN32
45 // This warning tells us about truncation of __long__ stl-generated names.
46 // It can occasionally cause DevStudio to have internal compiler warnings.
47 #pragma warning( disable : 4786 )     
48 #endif
49
50 #include "KX_IPO_SGController.h"
51 #include "KX_ScalarInterpolator.h"
52 #include "KX_GameObject.h"
53 #include "KX_IPhysicsController.h"
54
55 // All objects should start on frame 1! Will we ever need an object to 
56 // start on another frame, the 1.0 should change.
57 KX_IpoSGController::KX_IpoSGController() 
58 : m_modify_position(false),
59   m_modify_orientation(false),
60   m_modify_scaling(false),
61   m_ipo_as_force(false),
62   m_force_ipo_acts_local(false),
63   m_modified(true),
64   m_ipotime(1.0)
65 {
66         m_game_object = NULL;
67
68 }
69
70
71 void KX_IpoSGController::SetOption(
72         int option,
73         int value)
74 {
75         switch (option) {
76         case SG_CONTR_IPO_IPO_AS_FORCE:
77                 m_ipo_as_force = (value != 0);
78                 m_modified = true;
79                 break;
80         case SG_CONTR_IPO_FORCES_ACT_LOCAL:
81                 m_force_ipo_acts_local = (value != 0);
82                 m_modified = true;
83                 break;
84         default:
85                 ; /* just ignore the rest */
86         }
87 }
88
89         void 
90 KX_IpoSGController::UpdateSumoReference(
91         )
92 {
93         if (m_game_object) {
94
95         }
96 }
97
98         void 
99 KX_IpoSGController::SetGameObject(
100         KX_GameObject* go
101         )
102 {
103         m_game_object = go;
104 }
105
106
107
108 bool KX_IpoSGController::Update(double currentTime)
109 {
110         if (m_modified)
111         {
112                 T_InterpolatorList::iterator i;
113                 for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
114                         (*i)->Execute(m_ipotime);//currentTime);
115                 }
116                 
117                 SG_Spatial* ob = (SG_Spatial*)m_pObject;
118                 
119                 if (m_modify_position) {
120                         if (m_ipo_as_force) {
121                                 
122                                 if (m_game_object && ob) {
123                                         m_game_object->GetPhysicsController()->ApplyForce(m_force_ipo_acts_local ?
124                                                 ob->GetWorldOrientation() * m_ipo_xform.GetPosition() :
125                                                 m_ipo_xform.GetPosition(), false);
126                                 }
127
128                         } else {
129                                 ob->SetLocalPosition(m_ipo_xform.GetPosition());
130                         }
131                 }
132                 if (m_modify_orientation) {
133                         if (m_ipo_as_force) {
134                                 
135                                 if (m_game_object && ob) {
136                                         m_game_object->ApplyTorque(m_force_ipo_acts_local ?
137                                                 ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
138                                                 m_ipo_xform.GetEulerAngles(), false);
139                                 }
140
141                         } else {
142                                 ob->SetLocalOrientation(MT_Matrix3x3(m_ipo_xform.GetEulerAngles()));
143                         }
144                 }
145                 if (m_modify_scaling)
146                         ob->SetLocalScale(m_ipo_xform.GetScaling());
147
148                 m_modified=false;
149         }
150         return false;
151 }
152
153
154 void KX_IpoSGController::AddInterpolator(KX_IInterpolator* interp)
155 {
156         this->m_interpolators.push_back(interp);
157 }
158
159 SG_Controller*  KX_IpoSGController::GetReplica(class SG_Node* destnode)
160 {
161         KX_IpoSGController* iporeplica = new KX_IpoSGController(*this);
162         // clear object that ipo acts on in the replica.
163         iporeplica->ClearObject();
164
165         // dirty hack, ask Gino for a better solution in the ipo implementation
166         // hacken en zagen, in what we call datahiding, not written for replication :(
167
168         T_InterpolatorList oldlist = m_interpolators;
169         iporeplica->m_interpolators.clear();
170
171         T_InterpolatorList::iterator i;
172         for (i = oldlist.begin(); !(i == oldlist.end()); ++i) {
173                 KX_ScalarInterpolator* copyipo = new KX_ScalarInterpolator(*((KX_ScalarInterpolator*)*i));
174                 iporeplica->AddInterpolator(copyipo);
175
176                 MT_Scalar* scaal = ((KX_ScalarInterpolator*)*i)->GetTarget();
177                 uint_ptr orgbase = (uint_ptr)&m_ipo_xform;
178                 uint_ptr orgloc = (uint_ptr)scaal;
179                 uint_ptr offset = orgloc-orgbase;
180                 uint_ptr newaddrbase = (uint_ptr)&iporeplica->m_ipo_xform;
181                 newaddrbase += offset;
182                 MT_Scalar* blaptr = (MT_Scalar*) newaddrbase;
183                 copyipo->SetNewTarget((MT_Scalar*)blaptr);
184         }
185         
186         return iporeplica;
187 }
188
189 KX_IpoSGController::~KX_IpoSGController()
190 {
191
192         T_InterpolatorList::iterator i;
193         for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) {
194                 delete (*i);
195         }
196         
197 }