patch 8235 8218 8211 added: various gameengine improvements, fixed windows project...
[blender.git] / source / gameengine / Ketsji / KX_Scene.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  * Ketsji scene. Holds references to all scene data.
32  */
33
34 #ifdef WIN32
35 #pragma warning (disable : 4786)
36 #endif //WIN32
37
38 #include "KX_Scene.h"
39 #include "MT_assert.h"
40
41 #include "KX_KetsjiEngine.h"
42 #include "RAS_IPolygonMaterial.h"
43 #include "ListValue.h"
44 #include "SCA_LogicManager.h"
45 #include "SCA_TimeEventManager.h"
46 #include "SCA_AlwaysEventManager.h"
47 #include "SCA_RandomEventManager.h"
48 #include "KX_RayEventManager.h"
49 #include "KX_TouchEventManager.h"
50 #include "SCA_KeyboardManager.h"
51 #include "SCA_MouseManager.h"
52 #include "SCA_PropertyEventManager.h"
53 #include "KX_Camera.h"
54 #include "SCA_JoystickManager.h"
55
56 #include "RAS_MeshObject.h"
57 #include "BL_SkinMeshObject.h"
58
59 #include "RAS_IRasterizer.h"
60 #include "RAS_BucketManager.h"
61
62 #include "FloatValue.h"
63 #include "SCA_IController.h"
64 #include "SCA_IActuator.h"
65 #include "SG_Node.h"
66 #include "SYS_System.h"
67 #include "SG_Controller.h"
68 #include "SG_IObject.h"
69 #include "SG_Tree.h"
70
71 #include "KX_SG_NodeRelationships.h"
72
73 #include "KX_NetworkEventManager.h"
74 #include "NG_NetworkScene.h"
75 #include "PHY_IPhysicsEnvironment.h"
76 #include "KX_IPhysicsController.h"
77
78 #include "BL_SkinDeformer.h"
79 #include "BL_DeformableGameObject.h"
80
81
82 void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
83 {
84         KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj);
85
86         return (void*)replica;
87 }
88
89 void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
90 {
91         ((KX_Scene*)scene)->RemoveNodeDestructObject(node,(KX_GameObject*)gameobj);
92
93         return NULL;
94 };
95
96 SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(KX_SceneReplicationFunc,KX_SceneDestructionFunc,KX_GameObject::UpdateTransformFunc);
97
98 // temporarily var until there is a button in the userinterface
99 // (defined in KX_PythonInit.cpp)
100 extern bool gUseVisibilityTemp;
101
102 KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
103                                    class SCA_IInputDevice* mousedevice,
104                                    class NG_NetworkDeviceInterface *ndi,
105                                    class SND_IAudioDevice* adi,
106                                    const STR_String& sceneName): 
107         PyObjectPlus(&KX_Scene::Type),
108         m_keyboardmgr(NULL),
109         m_mousemgr(NULL),
110         m_physicsEnvironment(0),
111         m_sceneName(sceneName),
112         m_adi(adi),
113         m_networkDeviceInterface(ndi),
114         m_active_camera(NULL),
115         m_ueberExecutionPriority(0)
116 {
117         m_suspendedtime = 0.0;
118         m_suspendeddelta = 0.0;
119
120         m_activity_culling = false;
121         m_suspend = false;
122         m_isclearingZbuffer = true;
123         m_tempObjectList = new CListValue();
124         m_objectlist = new CListValue();
125         m_parentlist = new CListValue();
126         m_lightlist= new CListValue();
127         m_euthanasyobjects = new CListValue();
128         m_delayReleaseObjects = new CListValue();
129
130         m_logicmgr = new SCA_LogicManager();
131         
132         m_timemgr = new SCA_TimeEventManager(m_logicmgr);
133         m_keyboardmgr = new SCA_KeyboardManager(m_logicmgr,keyboarddevice);
134         m_mousemgr = new SCA_MouseManager(m_logicmgr,mousedevice);
135         
136         SCA_AlwaysEventManager* alwaysmgr = new SCA_AlwaysEventManager(m_logicmgr);
137         SCA_PropertyEventManager* propmgr = new SCA_PropertyEventManager(m_logicmgr);
138         SCA_RandomEventManager* rndmgr = new SCA_RandomEventManager(m_logicmgr);
139         KX_RayEventManager* raymgr = new KX_RayEventManager(m_logicmgr);
140
141         KX_NetworkEventManager* netmgr = new KX_NetworkEventManager(m_logicmgr, ndi);
142         
143         SCA_JoystickManager *joymgr     = new SCA_JoystickManager(m_logicmgr);
144
145         m_logicmgr->RegisterEventManager(alwaysmgr);
146         m_logicmgr->RegisterEventManager(propmgr);
147         m_logicmgr->RegisterEventManager(m_keyboardmgr);
148         m_logicmgr->RegisterEventManager(m_mousemgr);
149         m_logicmgr->RegisterEventManager(m_timemgr);
150         m_logicmgr->RegisterEventManager(rndmgr);
151         m_logicmgr->RegisterEventManager(raymgr);
152         m_logicmgr->RegisterEventManager(netmgr);
153         m_logicmgr->RegisterEventManager(joymgr);
154
155         m_soundScene = new SND_Scene(adi);
156         MT_assert (m_networkDeviceInterface != NULL);
157         m_networkScene = new NG_NetworkScene(m_networkDeviceInterface);
158         
159         m_rootnode = NULL;
160
161         m_bucketmanager=new RAS_BucketManager();
162
163         m_canvasDesignWidth = 0;
164         m_canvasDesignHeight = 0;
165         
166         m_attrlist = PyDict_New(); /* new ref */
167 }
168
169
170
171 KX_Scene::~KX_Scene()
172 {
173         
174         while (GetRootParentList()->GetCount() > 0) 
175         {
176                 KX_GameObject* parentobj = (KX_GameObject*) GetRootParentList()->GetValue(0);
177                 this->RemoveObject(parentobj);
178         }
179
180         if(m_objectlist)
181                 m_objectlist->Release();
182
183         if (m_parentlist)
184                 m_parentlist->Release();
185         
186         if (m_lightlist)
187                 m_lightlist->Release();
188         
189         if (m_tempObjectList)
190                 m_tempObjectList->Release();
191
192         if (m_euthanasyobjects)
193                 m_euthanasyobjects->Release();
194         if (m_delayReleaseObjects)
195                 m_delayReleaseObjects->Release();
196
197         if (m_logicmgr)
198                 delete m_logicmgr;
199
200         if (m_physicsEnvironment)
201                 delete m_physicsEnvironment;
202
203         if (m_soundScene)
204                 delete m_soundScene;
205
206         if (m_networkScene)
207                 delete m_networkScene;
208         
209         if (m_bucketmanager)
210         {
211                 delete m_bucketmanager;
212         }
213
214         //Py_DECREF(m_attrlist);
215 }
216
217
218
219
220 void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
221 {
222         m_projectionmat = pmat;
223 }
224
225
226
227 RAS_BucketManager* KX_Scene::GetBucketManager()
228 {
229         return m_bucketmanager;
230 }
231
232
233
234 CListValue* KX_Scene::GetObjectList()
235 {
236         return m_objectlist;
237 }
238
239
240
241 CListValue* KX_Scene::GetRootParentList()
242 {
243         return m_parentlist;
244 }
245
246
247
248 CListValue* KX_Scene::GetLightList()
249 {
250         return m_lightlist;
251 }
252
253 SCA_LogicManager* KX_Scene::GetLogicManager()
254 {
255         return m_logicmgr;
256 }
257
258 SCA_TimeEventManager* KX_Scene::GetTimeEventManager()
259 {
260         return m_timemgr;
261 }
262
263
264
265  
266 list<class KX_Camera*>* KX_Scene::GetCameras()
267 {
268         return &m_cameras;
269 }
270
271
272
273 void KX_Scene::SetFramingType(RAS_FrameSettings & frame_settings)
274 {
275         m_frame_settings = frame_settings;
276 };
277
278 /**
279  * Return a const reference to the framing 
280  * type set by the above call.
281  * The contents are not guarenteed to be sensible
282  * if you don't call the above function.
283  */
284 const RAS_FrameSettings& KX_Scene::GetFramingType() const 
285 {
286         return m_frame_settings;
287 };      
288
289
290
291 /**
292  * Store the current scene's viewport on the 
293  * game engine canvas.
294  */
295 void KX_Scene::SetSceneViewport(const RAS_Rect &viewport)
296 {
297         m_viewport = viewport;
298 }
299
300
301
302 const RAS_Rect& KX_Scene::GetSceneViewport() const 
303 {
304         return m_viewport;
305 }
306
307
308
309 void KX_Scene::SetWorldInfo(class KX_WorldInfo* worldinfo)
310 {
311         m_worldinfo = worldinfo;
312 }
313
314
315
316 class KX_WorldInfo* KX_Scene::GetWorldInfo()
317 {
318         return m_worldinfo;
319 }
320
321
322
323 SND_Scene* KX_Scene::GetSoundScene()
324 {
325         return m_soundScene;
326 }
327
328 const STR_String& KX_Scene::GetName()
329 {
330         return m_sceneName;
331 }
332
333
334 void KX_Scene::Suspend()
335 {
336         m_suspend = true;
337 }
338
339 void KX_Scene::Resume()
340 {
341         m_suspend = false;
342 }
343
344 void KX_Scene::SetActivityCulling(bool b)
345 {
346         m_activity_culling = b;
347 }
348
349 bool KX_Scene::IsSuspended()
350 {
351         return m_suspend;
352 }
353
354 bool KX_Scene::IsClearingZBuffer()
355 {
356         return m_isclearingZbuffer;
357 }
358
359 void KX_Scene::EnableZBufferClearing(bool isclearingZbuffer)
360 {
361         m_isclearingZbuffer = isclearingZbuffer;
362 }
363
364 void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gameobj)
365 {
366         KX_GameObject* orgobj = (KX_GameObject*)gameobj;        
367         NewRemoveObject(orgobj);
368
369         if (node)
370                 delete node;
371 }
372
373 KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CValue* gameobj)
374 {
375         KX_GameObject* orgobj = (KX_GameObject*)gameobj;
376         KX_GameObject* newobj = (KX_GameObject*)orgobj->GetReplica();
377         m_map_gameobject_to_replica.insert(orgobj, newobj);
378
379         // also register 'timers' (time properties) of the replica
380         int numprops = newobj->GetPropertyCount();
381
382         for (int i = 0; i < numprops; i++)
383         {
384                 CValue* prop = newobj->GetProperty(i);
385
386                 if (prop->GetProperty("timer"))
387                         this->m_timemgr->AddTimeProperty(prop);
388         }
389
390         if (node)
391         {
392                 newobj->SetSGNode((SG_Node*)node);
393         }
394         else
395         {
396                 m_rootnode = new SG_Node(newobj,this,KX_Scene::m_callbacks);
397         
398                 // this fixes part of the scaling-added object bug
399                 SG_Node* orgnode = orgobj->GetSGNode();
400                 m_rootnode->SetLocalScale(orgnode->GetLocalScale());
401                 m_rootnode->SetLocalPosition(orgnode->GetLocalPosition());
402                 m_rootnode->SetLocalOrientation(orgnode->GetLocalOrientation());
403
404                 // define the relationship between this node and it's parent.
405                 KX_NormalParentRelation * parent_relation = 
406                         KX_NormalParentRelation::New();
407                 m_rootnode->SetParentRelation(parent_relation);
408
409                 newobj->SetSGNode(m_rootnode);
410         }
411         
412         SG_IObject* replicanode = newobj->GetSGNode();
413 //      SG_Node* rootnode = (replicanode == m_rootnode ? NULL : m_rootnode);
414
415         replicanode->SetSGClientObject(newobj);
416
417         // this is the list of object that are send to the graphics pipeline
418         m_objectlist->Add(newobj);
419         newobj->Bucketize();
420
421         // logic cannot be replicated, until the whole hierarchy is replicated.
422         m_logicHierarchicalGameObjects.push_back(newobj);
423         //replicate controllers of this node
424         SGControllerList        scenegraphcontrollers = orgobj->GetSGNode()->GetSGControllerList();
425         replicanode->RemoveAllControllers();
426         SGControllerList::iterator cit;
427         //int numcont = scenegraphcontrollers.size();
428         
429         for (cit = scenegraphcontrollers.begin();!(cit==scenegraphcontrollers.end());++cit)
430         {
431                 // controller replication is quite complicated
432                 // only replicate ipo and physics controller for now
433
434                 SG_Controller* replicacontroller = (*cit)->GetReplica((SG_Node*) replicanode);
435                 if (replicacontroller)
436                 {
437                         replicacontroller->SetObject(replicanode);
438                         replicanode->AddSGController(replicacontroller);
439                 }
440         }
441         
442         return newobj;
443 }
444
445
446
447 // before calling this method KX_Scene::ReplicateLogic(), make sure to
448 // have called 'GameObject::ReParentLogic' for each object this
449 // hierarchy that's because first ALL bricks must exist in the new
450 // replica of the hierarchy in order to make cross-links work properly
451 // !
452 void KX_Scene::ReplicateLogic(KX_GameObject* newobj)
453 {
454         // also relink the controller to sensors/actuators
455         SCA_ControllerList& controllers = newobj->GetControllers();
456         //SCA_SensorList&     sensors     = newobj->GetSensors();
457         //SCA_ActuatorList&   actuators   = newobj->GetActuators();
458
459         for (SCA_ControllerList::iterator itc = controllers.begin(); !(itc==controllers.end());itc++)
460         {
461                 SCA_IController* cont = (*itc);
462                 cont->SetUeberExecutePriority(m_ueberExecutionPriority);
463                 vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors();
464                 vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
465
466                 // disconnect the sensors and actuators
467                 cont->UnlinkAllSensors();
468                 cont->UnlinkAllActuators();
469                 
470                 // now relink each sensor
471                 for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++)
472                 {
473                         SCA_ISensor* oldsensor = (*its);
474                         STR_String name = oldsensor->GetName();
475                         //find this name in the list
476                         SCA_ISensor* newsensor = newobj->FindSensor(name);
477                 
478                         if (newsensor)
479                         {
480                                 // relink this newsensor to the controller
481                                 m_logicmgr->RegisterToSensor(cont,newsensor);
482                         }
483                         else
484                         {
485                                 // it can be linked somewhere in the hierarchy or...
486                                 for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin();
487                                 !(git==m_logicHierarchicalGameObjects.end());++git)
488                                 {
489                                         newsensor = (*git)->FindSensor(name);
490                                         if (newsensor)
491                                                 break;
492                                 } 
493
494                                 if (newsensor)
495                                 {
496                                         // relink this newsensor to the controller somewhere else within this
497                                         // hierarchy
498                                         m_logicmgr->RegisterToSensor(cont,newsensor);
499                                 }
500                                 else
501                                 {
502                                         // must be an external sensor, so...
503                                         m_logicmgr->RegisterToSensor(cont,oldsensor);
504                                 }
505                         }
506                 }
507                 
508                 // now relink each actuator
509                 for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());ita++)
510                 {
511                         SCA_IActuator* oldactuator = (*ita);
512                         STR_String name = oldactuator->GetName();
513                         //find this name in the list
514                         SCA_IActuator* newactuator = newobj->FindActuator(name);
515                         if (newactuator)
516                         {
517                                 // relink this newsensor to the controller
518                                 m_logicmgr->RegisterToActuator(cont,newactuator);
519                                 newactuator->SetUeberExecutePriority(m_ueberExecutionPriority);
520                         }
521                         else
522                         {
523                                 // it can be linked somewhere in the hierarchy or...
524                                 for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin();
525                                 !(git==m_logicHierarchicalGameObjects.end());++git)
526                                 {
527                                         newactuator= (*git)->FindActuator(name);
528                                         if (newactuator)
529                                                 break;
530                                 } 
531
532                                 if (newactuator)
533                                 {
534                                         // relink this actuator to the controller somewhere else within this
535                                         // hierarchy
536                                         m_logicmgr->RegisterToActuator(cont,newactuator);
537                                         newactuator->SetUeberExecutePriority(m_ueberExecutionPriority);
538                                 }
539                                 else
540                                 {
541                                         // must be an external actuator, so...
542                                         m_logicmgr->RegisterToActuator(cont,oldactuator);
543                                 }
544                         }
545                 }
546         }
547 }
548
549
550
551 SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
552                                                                                 class CValue* parentobject,
553                                                                                 int lifespan)
554 {
555
556         m_logicHierarchicalGameObjects.clear();
557         m_map_gameobject_to_replica.clear();
558
559         // todo: place a timebomb in the object, for temporarily objects :)
560         // lifespan of zero means 'this object lives forever'
561         KX_GameObject* originalobj = (KX_GameObject*) originalobject;
562         KX_GameObject* parentobj = (KX_GameObject*) parentobject;
563
564         m_ueberExecutionPriority++;
565
566         // lets create a replica
567         KX_GameObject* replica = (KX_GameObject*) AddNodeReplicaObject(NULL,originalobj);
568
569         if (lifespan > 0)
570         {
571                 // add a timebomb to this object
572                 // for now, convert between so called frames and realtime
573                 m_tempObjectList->Add(replica->AddRef());
574                 replica->SetProperty("::timebomb",new CFloatValue(lifespan*0.02));
575         }
576
577         // add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame)
578         m_parentlist->Add(replica->AddRef());
579
580         // recurse replication into children nodes
581
582         NodeList& children = originalobj->GetSGNode()->GetSGChildren();
583
584         replica->GetSGNode()->ClearSGChildren();
585         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
586         {
587                 SG_Node* orgnode = (*childit);
588                 SG_Node* childreplicanode = orgnode->GetSGReplica();
589                 replica->GetSGNode()->AddChild(childreplicanode);
590         }
591
592         //      relink any pointers as necessary, sort of a temporary solution
593         vector<KX_GameObject*>::iterator git;
594         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
595         {
596                 (*git)->Relink(&m_map_gameobject_to_replica);
597         }
598
599         // now replicate logic
600         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
601         {
602                 (*git)->ReParentLogic();
603         }
604         
605         // replicate crosslinks etc. between logic bricks
606         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
607         {
608                 ReplicateLogic((*git));
609         }
610         
611         MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
612         replica->NodeSetLocalPosition(newpos);
613
614         MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
615         replica->NodeSetLocalOrientation(newori);
616         
617         // get the rootnode's scale
618         MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
619
620         // set the replica's relative scale with the rootnode's scale
621         replica->NodeSetRelativeScale(newscale);
622
623         if (replica->GetPhysicsController())
624         {
625                 replica->GetPhysicsController()->setPosition(newpos);
626                 replica->GetPhysicsController()->setOrientation(newori.getRotation());
627                 replica->GetPhysicsController()->setScaling(newscale);
628         }
629
630         // here we want to set the relative scale: the rootnode's scale will override all other
631         // scalings, so lets better prepare for it
632
633
634         replica->GetSGNode()->UpdateWorldData(0);
635         replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
636         replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
637         
638         return replica;
639 }
640
641
642
643 void KX_Scene::RemoveObject(class CValue* gameobj)
644 {
645         KX_GameObject* newobj = (KX_GameObject*) gameobj;
646
647         // first disconnect child from parent
648         SG_Node* node = newobj->GetSGNode();
649
650         if (node)
651         {
652                 node->DisconnectFromParent();
653
654                 // recursively destruct
655                 node->Destruct();
656         }
657         newobj->SetSGNode(0);
658 }
659
660 void KX_Scene::DelayedReleaseObject(CValue* gameobj)
661 {
662         m_delayReleaseObjects->Add(gameobj->AddRef());
663 }
664
665
666 void KX_Scene::DelayedRemoveObject(class CValue* gameobj)
667 {
668         //KX_GameObject* newobj = (KX_GameObject*) gameobj;
669         if (!m_euthanasyobjects->SearchValue(gameobj))
670         {
671                 m_euthanasyobjects->Add(gameobj->AddRef());
672         } 
673 }
674
675
676
677 void KX_Scene::NewRemoveObject(class CValue* gameobj)
678 {
679         KX_GameObject* newobj = (KX_GameObject*) gameobj;
680
681         //todo: look at this
682         //GetPhysicsEnvironment()->RemovePhysicsController(gameobj->getPhysicsController());
683
684         // remove all sensors/controllers/actuators from logicsystem...
685         
686         SCA_SensorList& sensors = newobj->GetSensors();
687         for (SCA_SensorList::iterator its = sensors.begin();
688                  !(its==sensors.end());its++)
689         {
690                 m_logicmgr->RemoveSensor(*its);
691         }
692         
693     SCA_ControllerList& controllers = newobj->GetControllers();
694         for (SCA_ControllerList::iterator itc = controllers.begin();
695                  !(itc==controllers.end());itc++)
696         {
697                 (*itc)->UnlinkAllSensors();
698                 (*itc)->UnlinkAllActuators();
699         }
700
701         SCA_ActuatorList& actuators = newobj->GetActuators();
702         for (SCA_ActuatorList::iterator ita = actuators.begin();
703                  !(ita==actuators.end());ita++)
704         {
705                 m_logicmgr->RemoveDestroyedActuator(*ita);
706         }
707
708         // now remove the timer properties from the time manager
709         int numprops = newobj->GetPropertyCount();
710
711         for (int i = 0; i < numprops; i++)
712         {
713                 CValue* propval = newobj->GetProperty(i);
714                 if (propval->GetProperty("timer"))
715                 {
716                         m_timemgr->RemoveTimeProperty(propval);
717                 }
718         }
719         
720         newobj->RemoveMeshes();
721         if (m_objectlist->RemoveValue(newobj))
722                 newobj->Release();
723         if (m_tempObjectList->RemoveValue(newobj))
724                 newobj->Release();
725         if (m_parentlist->RemoveValue(newobj))
726                 newobj->Release();
727         if (m_euthanasyobjects->RemoveValue(newobj))
728                 newobj->Release();
729                 
730         if (newobj == m_active_camera)
731         {
732                 m_active_camera->Release();
733                 m_active_camera = NULL;
734         }
735 }
736
737
738
739 void KX_Scene::ReplaceMesh(class CValue* gameobj,void* meshobj)
740 {
741         KX_GameObject* newobj = static_cast<KX_GameObject*>(gameobj);
742         RAS_MeshObject* mesh = static_cast<RAS_MeshObject*>(meshobj);
743
744         const STR_String origMeshName = newobj->GetMesh(0)->GetName();
745
746         if( !newobj || !mesh ) 
747         {
748                 std::cout << "warning: invalid object, mesh will not be replaced" << std::endl;
749                 return;
750         }
751
752         newobj->RemoveMeshes();
753         newobj->AddMesh(mesh);
754
755         bool isDeformer = (newobj->m_isDeformable && mesh->m_class == 1);
756         if(isDeformer)
757         {
758                 /* FindBlendObjByGameObj() can return 0... 
759                         In the case of 0 here,
760                         the replicated object that is calling this function
761                         is some how not in the map. (which is strange because it's added)
762                         So we will search the map by the first mesh name
763                         to try to locate it there. If its still not found 
764                         spit some message rather than crash 
765                 */
766                 Object* blendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameObj(newobj));
767                 Object* oldblendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName()));
768         
769                 bool parSkin = blendobj && blendobj->parent && blendobj->parent->type == OB_ARMATURE && blendobj->partype==PARSKEL;
770                 bool releaseParent = true;
771                 KX_GameObject* parentobj = newobj->GetParent();
772
773
774                 // lookup by mesh name if blendobj is 0 
775                 if( !blendobj &&  parentobj )
776                 {
777                         blendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameMeshName(origMeshName));
778
779                         // replace the mesh on the parent armature 
780                         if( blendobj )
781                                 parSkin = parentobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE;
782
783                         // can't do it 
784                         else 
785                                 std::cout << "warning: child object for " << parentobj->GetName().ReadPtr() 
786                                         << " not found, and can't create!" << std::endl;
787                 }
788
789                 if( blendobj && oldblendobj )
790                 {
791                         isDeformer = (static_cast<Mesh*>(blendobj->data)->dvert != 0);
792                         BL_DeformableGameObject* deformIter =0;
793
794                         // armature parent
795                         if( parSkin && isDeformer )
796                         {
797                                 deformIter = static_cast<BL_DeformableGameObject*>( newobj );
798                                 delete deformIter->m_pDeformer;
799
800                                 BL_SkinDeformer* skinDeformer = new BL_SkinDeformer(
801                                         oldblendobj, blendobj,
802                                         static_cast<BL_SkinMeshObject*>(mesh),
803                                         true,
804                                         static_cast<BL_ArmatureObject*>( parentobj )
805                                 );
806                                 releaseParent= false;
807                                 deformIter->m_pDeformer = skinDeformer;
808                         }
809
810                         // normal deformer
811                         if( !parSkin && isDeformer)
812                         {
813                                 deformIter = static_cast<BL_DeformableGameObject*>( newobj );
814                                 delete deformIter->m_pDeformer;
815
816                                 BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(
817                                         oldblendobj, static_cast<BL_SkinMeshObject*>(mesh)
818                                 );
819
820                                 deformIter->m_pDeformer = meshdeformer;
821                         }
822                 }
823                 // release parent reference if its not being used 
824                 if( releaseParent && parentobj)
825                         parentobj->Release();
826         }
827         newobj->Bucketize();
828 }
829
830
831
832 MT_CmMatrix4x4& KX_Scene::GetViewMatrix()
833 {
834         MT_Scalar cammat[16];
835         m_active_camera->GetWorldToCamera().getValue(cammat);
836         m_viewmat = cammat;
837         return m_viewmat;
838 }
839
840
841
842 MT_CmMatrix4x4& KX_Scene::GetProjectionMatrix()
843 {
844         return m_projectionmat;
845 }
846
847
848 KX_Camera* KX_Scene::FindCamera(KX_Camera* cam)
849 {
850         list<KX_Camera*>::iterator it = m_cameras.begin();
851
852         while ( (it != m_cameras.end()) 
853                         && ((*it) != cam) ) {
854           it++;
855         }
856
857         return ((it == m_cameras.end()) ? NULL : (*it));
858 }
859
860
861 KX_Camera* KX_Scene::FindCamera(STR_String& name)
862 {
863         list<KX_Camera*>::iterator it = m_cameras.begin();
864
865         while ( (it != m_cameras.end()) 
866                         && ((*it)->GetName() != name) ) {
867           it++;
868         }
869
870         return ((it == m_cameras.end()) ? NULL : (*it));
871 }
872
873 void KX_Scene::AddCamera(KX_Camera* cam)
874 {
875         if (!FindCamera(cam))
876                 m_cameras.push_back(cam);
877 }
878
879 KX_Camera* KX_Scene::GetActiveCamera()
880 {       
881         // NULL if not defined
882         return m_active_camera;
883 }
884
885
886 void KX_Scene::SetActiveCamera(KX_Camera* cam)
887 {
888         // only set if the cam is in the active list? Or add it otherwise?
889         if (!FindCamera(cam)){
890                 AddCamera(cam);
891                 if (cam) std::cout << "Added cam " << cam->GetName() << std::endl;
892         } 
893
894         m_active_camera = cam;
895 }
896
897 void KX_Scene::SetCameraOnTop(KX_Camera* cam)
898 {
899         if (!FindCamera(cam)){
900                 // adding is always done at the back, so that's all that needs to be done
901                 AddCamera(cam);
902                 if (cam) std::cout << "Added cam " << cam->GetName() << std::endl;
903         } else {
904                 m_cameras.remove(cam);
905                 m_cameras.push_back(cam);
906         }
907 }
908
909
910 void KX_Scene::UpdateMeshTransformations()
911 {
912         // do this incrementally in the future
913         for (int i = 0; i < m_objectlist->GetCount(); i++)
914         {
915                 KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i);
916                 gameobj->GetOpenGLMatrix();
917 //              gameobj->UpdateNonDynas();
918         }
919 }
920
921 void KX_Scene::MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera* cam)
922 {
923         int intersect = KX_Camera::INTERSECT;
924         KX_GameObject *gameobj = node->Client()?(KX_GameObject*) node->Client()->GetSGClientObject():NULL;
925         bool dotest = (gameobj && gameobj->GetVisible()) || node->Left() || node->Right();
926         
927         /* If the camera is inside the box, assume intersect. */
928         if (dotest && !node->inside( cam->NodeGetWorldPosition()))
929         {
930                 MT_Scalar radius = node->Radius();
931                 MT_Point3 center = node->Center();
932                 
933                 intersect =  cam->SphereInsideFrustum(center, radius); 
934                 
935                 if (intersect == KX_Camera::INTERSECT)
936                 {
937                         MT_Point3 box[8];
938                         node->get(box);
939                         intersect = cam->BoxInsideFrustum(box);
940                 }
941         }
942
943         switch (intersect)
944         {
945                 case KX_Camera::OUTSIDE:
946                         MarkSubTreeVisible(node, rasty, false, cam);
947                         break;
948                 case KX_Camera::INTERSECT:
949                         if (gameobj)
950                                 MarkVisible(rasty, gameobj,cam);
951                         if (node->Left())
952                                 MarkVisible(node->Left(), rasty,cam);
953                         if (node->Right())
954                                 MarkVisible(node->Right(), rasty,cam);
955                         break;
956                 case KX_Camera::INSIDE:
957                         MarkSubTreeVisible(node, rasty, true,cam);
958                         break;
959         }
960 }
961
962 void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible,KX_Camera* cam)
963 {
964         if (node->Client())
965         {
966                 KX_GameObject *gameobj = (KX_GameObject*) node->Client()->GetSGClientObject();
967                 if (gameobj->GetVisible())
968                 {
969                         if (visible)
970                         {
971                                 int nummeshes = gameobj->GetMeshCount();
972                                 MT_Transform t( cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform());
973         
974                                 
975                                 for (int m=0;m<nummeshes;m++)
976                                 {
977                                         // this adds the vertices to the display list
978                                         (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode());
979                                 }
980                         }
981                         gameobj->MarkVisible(visible);
982                 }
983         }
984         if (node->Left())
985                 MarkSubTreeVisible(node->Left(), rasty, visible,cam);
986         if (node->Right())
987                 MarkSubTreeVisible(node->Right(), rasty, visible,cam);
988 }
989
990 void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Camera*  cam)
991 {
992         // User (Python/Actuator) has forced object invisible...
993         if (!gameobj->GetVisible())
994                 return;
995         // If Frustum culling is off, the object is always visible.
996         bool vis = !cam->GetFrustumCulling();
997         
998         // If the camera is inside this node, then the object is visible.
999         if (!vis)
1000         {
1001                 vis = gameobj->GetSGNode()->inside( GetActiveCamera()->GetCameraLocation() );
1002         }
1003                 
1004         // Test the object's bound sphere against the view frustum.
1005         if (!vis)
1006         {
1007                 MT_Vector3 scale = gameobj->GetSGNode()->GetWorldScaling();
1008                 MT_Scalar radius = fabs(scale[scale.closestAxis()] * gameobj->GetSGNode()->Radius());
1009                 switch (cam->SphereInsideFrustum(gameobj->NodeGetWorldPosition(), radius))
1010                 {
1011                         case KX_Camera::INSIDE:
1012                                 vis = true;
1013                                 break;
1014                         case KX_Camera::OUTSIDE:
1015                                 vis = false;
1016                                 break;
1017                         case KX_Camera::INTERSECT:
1018                                 // Test the object's bound box against the view frustum.
1019                                 MT_Point3 box[8];
1020                                 gameobj->GetSGNode()->getBBox(box); 
1021                                 vis = cam->BoxInsideFrustum(box) != KX_Camera::OUTSIDE;
1022                                 break;
1023                 }
1024         }
1025         
1026         if (vis)
1027         {
1028                 int nummeshes = gameobj->GetMeshCount();
1029                 MT_Transform t(cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform());
1030                 
1031                 for (int m=0;m<nummeshes;m++)
1032                 {
1033                         // this adds the vertices to the display list
1034                         (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode());
1035                 }
1036                 // Visibility/ non-visibility are marked
1037                 // elsewhere now.
1038                 gameobj->MarkVisible();
1039         } else {
1040                 gameobj->MarkVisible(false);
1041         }
1042 }
1043
1044 void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam)
1045 {
1046 // FIXME: When tree is operational
1047 #if 1
1048         // do this incrementally in the future
1049         for (int i = 0; i < m_objectlist->GetCount(); i++)
1050         {
1051                 MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam);
1052         }
1053 #else
1054         if (cam->GetFrustumCulling())
1055                 MarkVisible(m_objecttree, rasty, cam);
1056         else
1057                 MarkSubTreeVisible(m_objecttree, rasty, true, cam);
1058 #endif
1059 }
1060
1061 // logic stuff
1062 void KX_Scene::LogicBeginFrame(double curtime)
1063 {
1064         // have a look at temp objects ...
1065         int lastobj = m_tempObjectList->GetCount() - 1;
1066         
1067         for (int i = lastobj; i >= 0; i--)
1068         {
1069                 CValue* objval = m_tempObjectList->GetValue(i);
1070                 CFloatValue* propval = (CFloatValue*) objval->GetProperty("::timebomb");
1071                 
1072                 if (propval)
1073                 {
1074                         float timeleft = propval->GetNumber() - 1.0/KX_KetsjiEngine::GetTicRate();
1075                         
1076                         if (timeleft > 0)
1077                         {
1078                                 propval->SetFloat(timeleft);
1079                         }
1080                         else
1081                         {
1082                                 DelayedRemoveObject(objval);
1083                                 // remove obj
1084                         }
1085                 }
1086                 else
1087                 {
1088                         // all object is the tempObjectList should have a clock
1089                 }
1090         }
1091         m_logicmgr->BeginFrame(curtime, 1.0/KX_KetsjiEngine::GetTicRate());
1092 }
1093
1094
1095
1096 void KX_Scene::LogicUpdateFrame(double curtime, bool frame)
1097 {
1098         m_logicmgr->UpdateFrame(curtime, frame);
1099 }
1100
1101
1102
1103 void KX_Scene::LogicEndFrame()
1104 {
1105         m_logicmgr->EndFrame();
1106         int numobj = m_euthanasyobjects->GetCount();
1107         int i;
1108         for (i = numobj - 1; i >= 0; i--)
1109         {
1110                 KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i);
1111                 this->RemoveObject(gameobj);
1112         }
1113
1114         numobj= m_delayReleaseObjects->GetCount();
1115         for (i = numobj-1;i>=0;i--)
1116         {
1117                 KX_GameObject* gameobj = (KX_GameObject*)m_delayReleaseObjects->GetValue(i);
1118                 m_delayReleaseObjects->RemoveValue(gameobj);    
1119                 
1120         }
1121         
1122
1123 }
1124
1125
1126
1127 /**
1128   * UpdateParents: SceneGraph transformation update.
1129   */
1130 void KX_Scene::UpdateParents(double curtime)
1131 {
1132 //      int numrootobjects = GetRootParentList()->GetCount();
1133
1134         for (int i=0; i<GetRootParentList()->GetCount(); i++)
1135         {
1136                 KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
1137                 parentobj->NodeUpdateGS(curtime,true);
1138         }
1139 }
1140
1141
1142
1143 RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat)
1144 {
1145         return m_bucketmanager->RAS_BucketManagerFindBucket(polymat);
1146 }
1147
1148
1149
1150 void KX_Scene::RenderBuckets(const MT_Transform & cameratransform,
1151                                                          class RAS_IRasterizer* rasty,
1152                                                          class RAS_IRenderTools* rendertools)
1153 {
1154         m_bucketmanager->Renderbuckets(cameratransform,rasty,rendertools);
1155 }
1156
1157
1158
1159 void KX_Scene::UpdateObjectActivity(void) 
1160 {
1161         if (m_activity_culling) {
1162                 /* determine the activity criterium and set objects accordingly */
1163                 int i=0;
1164                 
1165                 MT_Point3 camloc = GetActiveCamera()->NodeGetWorldPosition(); //GetCameraLocation();
1166                 
1167                 for (i=0;i<GetObjectList()->GetCount();i++)
1168                 {
1169                         KX_GameObject* ob = (KX_GameObject*) GetObjectList()->GetValue(i);
1170                         
1171                         if (!ob->GetIgnoreActivityCulling()) {
1172                                 /* Simple test: more than 10 away from the camera, count
1173                                  * Manhattan distance. */
1174                                 MT_Point3 obpos = ob->NodeGetWorldPosition();
1175                                 
1176                                 if ( (fabs(camloc[0] - obpos[0]) > m_activity_box_radius)
1177                                          || (fabs(camloc[1] - obpos[1]) > m_activity_box_radius)
1178                                          || (fabs(camloc[2] - obpos[2]) > m_activity_box_radius) )
1179                                 {                       
1180                                         ob->Suspend();
1181                                 } else {
1182                                         ob->Resume();
1183                                 }
1184                         }
1185                 }               
1186         }
1187 }
1188
1189 void KX_Scene::SetActivityCullingRadius(float f)
1190 {
1191         if (f < 0.5)
1192                 f = 0.5;
1193         m_activity_box_radius = f;
1194 }
1195         
1196 NG_NetworkDeviceInterface* KX_Scene::GetNetworkDeviceInterface()
1197 {
1198         return m_networkDeviceInterface;
1199 }
1200
1201 NG_NetworkScene* KX_Scene::GetNetworkScene()
1202 {
1203         return m_networkScene;
1204 }
1205
1206 void KX_Scene::SetNetworkDeviceInterface(NG_NetworkDeviceInterface* newInterface)
1207 {
1208         m_networkDeviceInterface = newInterface;
1209 }
1210
1211 void KX_Scene::SetNetworkScene(NG_NetworkScene *newScene)
1212 {
1213         m_networkScene = newScene;
1214 }
1215
1216
1217 void    KX_Scene::SetGravity(const MT_Vector3& gravity)
1218 {
1219         GetPhysicsEnvironment()->setGravity(gravity[0],gravity[1],gravity[2]);
1220 }
1221
1222 void KX_Scene::SetNodeTree(SG_Tree* root)
1223 {
1224         m_objecttree = root;
1225 }
1226
1227 void KX_Scene::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv)
1228 {
1229         m_physicsEnvironment = physEnv;
1230
1231         KX_TouchEventManager* touchmgr = new KX_TouchEventManager(m_logicmgr, physEnv);
1232         m_logicmgr->RegisterEventManager(touchmgr);
1233         return;
1234 }
1235  
1236 void KX_Scene::setSuspendedTime(double suspendedtime)
1237 {
1238         m_suspendedtime = suspendedtime;
1239 }
1240 double KX_Scene::getSuspendedTime()
1241 {
1242         return m_suspendedtime;
1243 }
1244 void KX_Scene::setSuspendedDelta(double suspendeddelta)
1245 {
1246         m_suspendeddelta = suspendeddelta;
1247 }
1248 double KX_Scene::getSuspendedDelta()
1249 {
1250         return m_suspendeddelta;
1251 }
1252
1253 //----------------------------------------------------------------------------
1254 //Python
1255
1256 PyMethodDef KX_Scene::Methods[] = {
1257         KX_PYMETHODTABLE(KX_Scene, getLightList),
1258         KX_PYMETHODTABLE(KX_Scene, getObjectList),
1259         KX_PYMETHODTABLE(KX_Scene, getName),
1260         
1261         {NULL,NULL} //Sentinel
1262 };
1263
1264 PyTypeObject KX_Scene::Type = {
1265         PyObject_HEAD_INIT(&PyType_Type)
1266                 0,
1267                 "KX_Scene",
1268                 sizeof(KX_Scene),
1269                 0,
1270                 PyDestructor,
1271                 0,
1272                 __getattr,
1273                 __setattr,
1274                 0, //&MyPyCompare,
1275                 __repr,
1276                 0, //&cvalue_as_number,
1277                 0,
1278                 0,
1279                 0,
1280                 0, 0, 0, 0, 0, 0
1281 };
1282
1283 PyParentObject KX_Scene::Parents[] = {
1284         &KX_Scene::Type,
1285                 &CValue::Type,
1286                 NULL
1287 };
1288
1289 PyObject* KX_Scene::_getattr(const STR_String& attr)
1290 {
1291         if (attr == "name")
1292                 return PyString_FromString(GetName());
1293         
1294         if (attr == "active_camera")
1295         {
1296                 KX_Camera *camera = GetActiveCamera();
1297                 camera->AddRef();
1298                 return (PyObject*) camera;
1299         }
1300         
1301         if (attr == "suspended")
1302                 return PyInt_FromLong(m_suspend);
1303         
1304         if (attr == "activity_culling")
1305                 return PyInt_FromLong(m_activity_culling);
1306         
1307         if (attr == "activity_culling_radius")
1308                 return PyFloat_FromDouble(m_activity_box_radius);
1309         
1310         PyObject* value = PyDict_GetItemString(m_attrlist, const_cast<char *>(attr.ReadPtr()));
1311         if (value)
1312         {
1313                 Py_INCREF(value);
1314                 return value;
1315         }
1316         
1317         _getattr_up(PyObjectPlus);
1318 }
1319
1320 int KX_Scene::_delattr(const STR_String &attr)
1321 {
1322         PyDict_DelItemString(m_attrlist, const_cast<char *>(attr.ReadPtr()));
1323         return 0;
1324 }
1325
1326 int KX_Scene::_setattr(const STR_String &attr, PyObject *pyvalue)
1327 {
1328
1329         if (!PyDict_SetItemString(m_attrlist, const_cast<char *>(attr.ReadPtr()), pyvalue))
1330                 return 0;
1331
1332         return PyObjectPlus::_setattr(attr, pyvalue);
1333 }
1334
1335 KX_PYMETHODDEF_DOC(KX_Scene, getLightList,
1336 "getLightList() -> list [KX_Light]\n"
1337 "Returns a list of all lights in the scene.\n"
1338 )
1339 {
1340         m_lightlist->AddRef();
1341         return (PyObject*) m_lightlist;
1342 }
1343
1344 KX_PYMETHODDEF_DOC(KX_Scene, getObjectList,
1345 "getObjectList() -> list [KX_GameObject]\n"
1346 "Returns a list of all game objects in the scene.\n"
1347 )
1348 {
1349         m_objectlist->AddRef();
1350         return (PyObject*) m_objectlist;
1351 }
1352
1353 KX_PYMETHODDEF_DOC(KX_Scene, getName,
1354 "getName() -> string\n"
1355 "Returns the name of the scene.\n"
1356 )
1357 {
1358         return PyString_FromString(GetName());
1359 }