RioEngine  0.1
My first attempt to create a 3D WYSIWYG Game Engine
cgamescene.cpp
Go to the documentation of this file.
1 //--------------------------------------------------------------- @License begins
2 // RioEngine: The late night Coke -without whores- debugging sessions
3 // 2012-2015 Leopoldo Lomas Flores. Torreon, Coahuila. MEXICO
4 // leopoldolomas [at] gmail
5 // www.rioengine.com
6 // www.leopoldolomas.info
7 // "You have a problem, you face it like a man."
8 //
9 // This is free and unencumbered software released into the public domain.
10 //
11 // Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
12 // software, either in source code form or as a compiled binary, for any purpose,
13 // commercial or non-commercial, and by any means.
14 //
15 // In jurisdictions that recognize copyright laws, the author or authors of this
16 // software dedicate any and all copyright interest in the software to the public
17 // domain. We make this dedication for the benefit of the public at large and to
18 // the detriment of our heirs and successors. We intend this dedication to be
19 // an overt act of relinquishment in perpetuity of all present and future
20 // rights to this software under copyright law.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS
24 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
26 // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //--------------------------------------------------------------- @License ends
29 
30 #include <regex>
31 #include "constants.h"
32 #include "misc/transform.h"
33 #include "misc/genericshelper.hpp"
34 #include "cengine/cgameobject.h"
37 #include "cengine/cdirector.h"
38 #include "cengine/ccamera.h"
39 #include "cengine/cgamescene.h"
40 
41 //-----------------------------------------------------------------------------
42 
44  m_gameObjects = new std::vector<CGameObject*>();
45  m_gameObjectsPendingToBeAdded = new std::vector<CGameObject*>();
46  m_gameObjectsPendingToBeRemoved = new std::vector<CGameObject*>();
47 
48  m_collisionShapes = btAlignedObjectArray<btCollisionShape*>();
49  m_collisionConfiguration = new btDefaultCollisionConfiguration();
50  m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
51  m_overlappingPairCache = new btDbvtBroadphase();
52  m_solver = new btSequentialImpulseConstraintSolver();
53  m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher,
55  m_solver,
56  m_collisionConfiguration);
57  m_dynamicsWorld->setGravity(btVector3(0.0f, -9.8f, 0.0f));
58  m_isRunningUpdateLoops = false;
59 }
60 
61 //-----------------------------------------------------------------------------
62 
63 CGameScene::CGameScene(const CGameScene& original_obj) : CObject() {
64  copyValuesFromObject(original_obj);
65 }
66 
67 //-----------------------------------------------------------------------------
68 
70  if (this == &original_obj)
71  return *this;
72 
73  copyValuesFromObject(original_obj);
74 
75  return *this;
76 }
77 
78 //-----------------------------------------------------------------------------
79 
80 void CGameScene::copyValuesFromObject(const CGameScene& original_obj) {
81  // TODO
82 }
83 
84 //-----------------------------------------------------------------------------
85 
86 btDiscreteDynamicsWorld* CGameScene::dynamicsWorld() const {
87  return m_dynamicsWorld;
88 }
89 
90 //-----------------------------------------------------------------------------
91 
92 void CGameScene::callStart_R(CGameObject* child) {
93  child->start();
94  for(QObjectList::const_iterator it = child->children().begin();
95  it != child->children().end();
96  ++it) {
97  CGameObject* child_as_gameobject = qobject_cast<CGameObject*>(*it);
98  if(child_as_gameobject != NULL) {
99  callStart_R(child_as_gameobject);
100  }
101  }
102 }
103 
104 //-----------------------------------------------------------------------------
105 
106 void CGameScene::callPreUpdate_R(CGameObject* child) {
107  child->preUpdate();
108  for(QObjectList::const_iterator it = child->children().begin();
109  it != child->children().end();
110  ++it) {
111  CGameObject* child_as_gameobject = qobject_cast<CGameObject*>(*it);
112  if(child_as_gameobject != NULL) {
113  callPreUpdate_R(child_as_gameobject);
114  }
115  }
116 }
117 
118 //-----------------------------------------------------------------------------
119 
120 void CGameScene::callUpdate_R(CGameObject* child) {
121  child->update();
122  for(QObjectList::const_iterator it = child->children().begin();
123  it != child->children().end();
124  ++it) {
125  CGameObject* child_as_gameobject = qobject_cast<CGameObject*>(*it);
126  if(child_as_gameobject != NULL) {
127  callUpdate_R(child_as_gameobject);
128  }
129  }
130 }
131 
132 //-----------------------------------------------------------------------------
133 
134 void CGameScene::callPostUpdate_R(CGameObject* child) {
135  child->postUpdate();
136  for(QObjectList::const_iterator it = child->children().begin();
137  it != child->children().end();
138  ++it) {
139  CGameObject* child_as_gameobject = qobject_cast<CGameObject*>(*it);
140  if(child_as_gameobject != NULL) {
141  callPostUpdate_R(child_as_gameobject);
142  }
143  }
144 }
145 
146 //-----------------------------------------------------------------------------
147 
149  m_isRunningUpdateLoops = true;
150  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
151  it != m_gameObjects->end();
152  ++it) {
153  callStart_R(*it);
154  }
155 }
156 
157 //-----------------------------------------------------------------------------
158 
160  m_isRunningUpdateLoops = true;
161  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
162  it != m_gameObjects->end();
163  ++it) {
164  callPreUpdate_R(*it);
165  }
166 }
167 
168 //-----------------------------------------------------------------------------
169 
171  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
172  it != m_gameObjects->end();
173  ++it) {
174  callUpdate_R(*it);
175  }
176 
177  updateWorld();
178  postUpdateWorld();
180 }
181 
182 //-----------------------------------------------------------------------------
183 
185  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
186  it != m_gameObjects->end();
187  ++it) {
188  callPostUpdate_R(*it);
189  }
190  m_isRunningUpdateLoops = false;
191 
192  // move objects from m_queuedGameObject to m_gameObjects
193  for (std::vector<CGameObject*>::iterator it = m_gameObjectsPendingToBeAdded->begin();
194  it != m_gameObjectsPendingToBeAdded->end();
195  ++it) {
196  SAFE_RETAIN(*it);
197  m_gameObjects->push_back(*it);
198  }
200  m_gameObjectsPendingToBeAdded = new std::vector<CGameObject*>();
201 
202  // delete the objects that are pending to be removed
203  for (std::vector<CGameObject*>::iterator it = m_gameObjectsPendingToBeRemoved->begin();
204  it != m_gameObjectsPendingToBeRemoved->end();
205  ++it) {
206  removeGameObject((*it)->uid());
207  }
209  m_gameObjectsPendingToBeRemoved = new std::vector<CGameObject*>();
210 }
211 
212 //-----------------------------------------------------------------------------
213 
214 CGameObject* CGameScene::createGameObjectWithNode(const std::string& node_id, bool add_to_scene, const char* object_type) {
215  if (CLASSETSREPOSITORY->getNodeHavingId(node_id)) {
216  CLNode* original_node = CLASSETSREPOSITORY->getNodeHavingId(node_id);
217  CLNode* node_copy = new CLNode(*original_node);
218 
219  CGameObject* game_object = NULL;
220  if(object_type) {
221  game_object = CGameObjectFactory::createInstance(object_type);
222  SAFE_RETAIN(game_object);
223  } else {
224  game_object = new CGameObject();
225  }
226  RE_ASSERT(game_object);
227 
228  game_object->copyNodeValuesFromNode(node_copy);
229  SAFE_RELEASE(node_copy);
230  std::string fixed_node_id = node_id;
231  game_object->setProperty("objectName", QString::fromStdString(createUniqueGameObjectName(fixed_node_id)));
232 
233  if (add_to_scene) {
234  addGameObject(game_object);
235  }
236  game_object->autorelease();
237  return game_object;
238  }
239  return NULL;
240 }
241 
242 //-----------------------------------------------------------------------------
243 
245  SAFE_RETAIN(game_object);
246  game_object->setParent(this);
248  m_gameObjectsPendingToBeAdded->push_back(game_object);
249  } else {
250  m_gameObjects->push_back(game_object);
251  }
252  if(game_object->bulletProperties.physicsEnabled()) {
253  game_object->deployIntoDynamicsWorld();
254  }
255  callStart_R(game_object);
256 }
257 
258 //-----------------------------------------------------------------------------
259 
260 const CGameObject* CGameScene::getGameObject(const std::string& name) const {
261  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
262  it != m_gameObjects->end();
263  ++it) {
264  CGameObject* game_obj = *it;
265  if (game_obj->objectName().toStdString() == name) {
266  return game_obj;
267  }
268  }
269  return NULL;
270 }
271 
272 //-----------------------------------------------------------------------------
273 
274 const CGameObject* CGameScene::getGameObject(uint uid) const {
275  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
276  it != m_gameObjects->end();
277  ++it) {
278  CGameObject* game_obj = *it;
279  if (game_obj->uid() == uid) {
280  return game_obj;
281  }
282  }
283  return NULL;
284 }
285 
286 //-----------------------------------------------------------------------------
287 
288 std::vector<CGameObject*>* CGameScene::getGameObjects() const {
289  return m_gameObjects;
290 }
291 
292 //-----------------------------------------------------------------------------
293 
294 bool CGameScene::existsGameObjectWithName(const std::string& name) {
295  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
296  it != m_gameObjects->end();
297  ++it) {
298  if ((*it)->name() == name) {
299  return true;
300  }
301  }
302 
303  return false;
304 }
305 
306 //-----------------------------------------------------------------------------
307 
308 std::string& CGameScene::fixName(std::string& name) {
309  std::string regex_ext_str = "_([0-9]*)";
310  std::tr1::regex regex_ext(regex_ext_str);
311  std::tr1::cmatch match;
312  if (regex_search(name.c_str(), match, regex_ext)) {
313  std::string match_str = match.str().substr(1, match.str().size() - 1); // remove the '_' char
314  unsigned int index = atoi(match_str.c_str());
315 
316  name = name.substr(0, name.size() - match_str.length() - 1);
317 
318  char suffix[4]; // up to '_' char and a maximum of 3 digits
319  sprintf_s(suffix, "_%i", ++index);
320 
321  name.append(suffix);
322  } else // then we just need to add a suffix, for example: my_game_object => my_game_object_1
323  name.append("_1");
324 
325  return name;
326 }
327 
328 //-----------------------------------------------------------------------------
329 
330 std::string& CGameScene::createUniqueGameObjectName(std::string& name) {
331  while (existsGameObjectWithName(name)) {
332  name = fixName(name);
333  }
334  return name;
335 }
336 
337 //-----------------------------------------------------------------------------
338 
340  CGameObject* clone = new CGameObject(*game_object);
341  clone->setName(createUniqueGameObjectName(game_object->name()));
342  addGameObject(clone);
343  SAFE_RELEASE(clone);
344 
345  return clone;
346 }
347 
348 //-----------------------------------------------------------------------------
349 
351  // retain the game object, it will be deleted until the undo/redo action goes out of scope
352  CGameObject* game_object = NULL;
353  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
354  it != m_gameObjects->end();
355  ++it) {
356  if ((*it)->uid() == uid) {
357  game_object = (*it);
358  break;
359  }
360  }
361  if (game_object == NULL) {
362  return false;
363  }
364 
365  game_object->aboutToBeRemoved();
366  game_object->removeFromDynamicsWorld();
367  game_object->retain();
368  game_object->setParent(NULL);
370 }
371 
372 //-----------------------------------------------------------------------------
373 
375  RE_ASSERT(object);
376 
378  m_gameObjectsPendingToBeRemoved->push_back(object);
379  }
380 }
381 
382 //-----------------------------------------------------------------------------
383 
385  stopAllActions();
386  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
387  it != m_gameObjects->end();
388  ++it) {
389  CGameObject* obj = *it;
390  obj->aboutToBeRemoved();
391  }
393  m_gameObjects = new std::vector<CGameObject*>();
394  CDIRECTOR->getCameraWithId(k_CDirector_DefaultCameraId)->reset();
395 }
396 
397 //-----------------------------------------------------------------------------
398 
399 QList<CGameObject> CGameScene::gameObjects() {
400  QList<CGameObject> vec = QList<CGameObject>();
401  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
402  it != m_gameObjects->end();
403  ++it) {
404  CGameObject obj = *(*it);
405  vec.append(obj);
406  }
407  return vec;
408 }
409 
410 //-----------------------------------------------------------------------------
411 
412 void CGameScene::setGameObjects(QList<CGameObject> vec) {
413  clear();
414  for (int i = 0; i < vec.count(); i++) {
415  CGameObject* gameobj_copy = new CGameObject(vec[i]);
416  gameobj_copy->autorelease();
417  addGameObject(gameobj_copy);
418  }
419 }
420 
421 //-----------------------------------------------------------------------------
422 
424  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
425  it != m_gameObjects->end();
426  ++it) {
427  CGameObject* obj = (*it);
428 
429  int type_id = QMetaType::type(obj->CObjectTypeName().toStdString().c_str());
430  RE_ASSERT(type_id);
431  CGameObject *new_obj = NULL;
432  new_obj = static_cast<CGameObject*>(QMetaType::create(type_id, obj));
433  new_obj->setParent(this);
434  new_obj->bulletProperties = obj->bulletProperties;
436  if(new_obj->bulletProperties.physicsEnabled()) {
437  new_obj->deployIntoDynamicsWorld();
438  }
439  SAFE_RELEASE(new_obj);
440  }
441  start();
442 }
443 
444 //-----------------------------------------------------------------------------
445 
447  BT_PROFILE("update");
448  m_dynamicsWorld->stepSimulation (1.f/60.f,10);
449  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
450  it != m_gameObjects->end();
451  ++it) {
452  CGameObject* obj = *it;
453  if (obj->bulletProperties.physicsEnabled()) {
454  btRigidBody* body = obj->bulletProperties.rigidBody();
455  btTransform trans;
456  body->getMotionState()->getWorldTransform(trans);
457  obj->transform().setLocalPosition(trans.getOrigin() / k_QGLGameEditorViewport_SizeFactor);
458  obj->transform().setLocalRotation(trans.getRotation());
459  }
460  }
461 }
462 
463 //-----------------------------------------------------------------------------
464 
466  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
467  it != m_gameObjects->end();
468  ++it) {
469  (*it)->postWorldUpdate();
470  }
471 }
472 
473 //-----------------------------------------------------------------------------
474 
476  //remove the rigidbodies from the dynamics world and delete them
477  for (int i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0 ;i--) {
478  btCollisionObject* obj = m_dynamicsWorld ->getCollisionObjectArray()[i];
479  btRigidBody* body = btRigidBody::upcast(obj);
480  if (body && body ->getMotionState()) {
481  SAFE_RELEASE(body->getMotionState());
482  SAFE_RELEASE(body->getCollisionShape());
483  }
484  m_dynamicsWorld ->removeCollisionObject( obj );
485  SAFE_RELEASE(obj);
486  }
487 
488  //delete collision shapes
489  for (int j=0;j<m_collisionShapes.size();j++) {
490  btCollisionShape* shape = m_collisionShapes[j];
491  m_collisionShapes[j] = 0;
492  SAFE_RELEASE(shape);
493  }
494 
495  //delete dynamics world
497 
498  //delete solver
500 
501  //delete broadphase
503 
504  //delete dispatcher
506 
508 
509  m_collisionShapes.clear();
510 }
511 
513  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
514  it != m_gameObjects->end();
515  ++it) {
516  (*it)->stopAllActions();
517  for (QList<QObject*>::const_iterator inner_it = (*it)->children().begin();
518  inner_it != (*it)->children().end();
519  ++inner_it) {
520  if (qobject_cast<CGameObject*>(*inner_it) != NULL) {
521  static_cast<CGameObject*>(*inner_it)->stopAllActions();
522  }
523  }
524  }
525 }
526 
527 //-----------------------------------------------------------------------------
528 
530  int numManifolds = dynamicsWorld()->getDispatcher()->getNumManifolds();
531  for (int i=0;i<numManifolds;i++)
532  {
533  btPersistentManifold* contactManifold = dynamicsWorld()->getDispatcher()->getManifoldByIndexInternal(i);
534  const btCollisionObject* obA = contactManifold->getBody0();
535  const btCollisionObject* obB = contactManifold->getBody1();
536 
537  int numContacts = contactManifold->getNumContacts();
538  for (int j=0;j<numContacts;j++)
539  {
540  btManifoldPoint& pt = contactManifold->getContactPoint(j);
541  if (pt.getDistance() < 0.f)
542  {
543  CGameObject* objectA = static_cast<CGameObject*>(obA->getUserPointer());
544  CGameObject* objectB = static_cast<CGameObject*>(obB->getUserPointer());
545 
546  RE_ASSERT(objectA->isValidCObject());
547  RE_ASSERT(objectB->isValidCObject());
548 
549  objectA->onCollisionWithObject(objectB);
550  objectB->onCollisionWithObject(objectA);
551  }
552  }
553  }
554 }
555 
556 //-----------------------------------------------------------------------------
557 
559  for (std::vector<CGameObject*>::iterator it = m_gameObjects->begin();
560  it != m_gameObjects->end();
561  ++it) {
562  CGameObject* game_obj = *it;
563  if (game_obj->tag() == tag) {
564  return game_obj;
565  }
566  }
567  return NULL;
568 }
569 
570 //-----------------------------------------------------------------------------
571 
573  deleteWorld();
574 
575  // rigid bodies were deleted in deleteWorld(). So we need to set their references in bulletProperties to NULL so they don't get overreleased.
576  for (uint i = 0; i < m_gameObjects->size(); i++) {
577  CGameObject* obj = m_gameObjects->at(i);
578  obj->bulletProperties.setRigidBody(NULL);
579  }
580 
584 }
virtual void clear()
Definition: cgamescene.cpp:384
void copyNodeValuesFromNode(CLNode *node)
Definition: clnode.cpp:123
btSequentialImpulseConstraintSolver * m_solver
Definition: cgamescene.h:174
virtual void start()
Definition: cgamescene.cpp:148
void setRigidBody(btRigidBody *rigid_body)
btDefaultCollisionConfiguration * m_collisionConfiguration
Definition: cgamescene.h:171
static void deleteVector(std::vector< T * > *vec)
CGameObject * duplicateGameObject(const CGameObject *game_object)
Definition: cgamescene.cpp:339
static bool replaceObjectInVector(std::vector< T * > *vec, T *object_to_replace, T *replacement)
btDiscreteDynamicsWorld * m_dynamicsWorld
Definition: cgamescene.h:175
static CGameObject * createInstance(const char *class_name)
Definition: clnode.h:37
btBroadphaseInterface * m_overlappingPairCache
Definition: cgamescene.h:173
btDiscreteDynamicsWorld * dynamicsWorld() const
Definition: cgamescene.cpp:86
std::vector< CGameObject * > * m_gameObjectsPendingToBeAdded
stores GameObjects added during the update loop
Definition: cgamescene.h:164
virtual void performCollisionCallbacks()
Definition: cgamescene.cpp:529
virtual ~CGameScene()
Definition: cgamescene.cpp:572
virtual void run()
Definition: cgamescene.cpp:423
std::vector< CGameObject * > * m_gameObjectsPendingToBeRemoved
stores GameObjects removed during the update loop
Definition: cgamescene.h:167
virtual void deleteWorld()
Definition: cgamescene.cpp:475
bool isValidCObject() const
Definition: cobject.cpp:100
CGameObject * getGameObjectHavingTag(int tag) const
Definition: cgamescene.cpp:558
void setLocalRotation(float w, float x, float y, float z)
Definition: transform.cpp:209
btAlignedObjectArray< btCollisionShape * > m_collisionShapes
Definition: cgamescene.h:170
bool m_isRunningUpdateLoops
Definition: cgamescene.h:159
virtual void postUpdate()
Definition: cgamescene.cpp:184
virtual void update()
Definition: cgamescene.cpp:170
std::string & createUniqueGameObjectName(std::string &original_name)
Definition: cgamescene.cpp:330
virtual void postUpdateWorld()
Definition: cgamescene.cpp:465
btCollisionDispatcher * m_dispatcher
Definition: cgamescene.h:172
void setGameObjects(QList< CGameObject > game_objects)
Definition: cgamescene.cpp:412
CGameObject * createGameObjectWithNode(const std::string &node_id, bool add_to_scene=true, const char *object_type=NULL)
Creates a GameObject based upon the specified Node id.
Definition: cgamescene.cpp:214
bool existsGameObjectWithName(const std::string &name)
Definition: cgamescene.cpp:294
std::vector< CGameObject * > * getGameObjects() const
Definition: cgamescene.cpp:288
#define SAFE_RELEASE(x)
Definition: cobject.h:36
const CGameObject * getGameObject(const std::string &name) const
Definition: cgamescene.cpp:260
bool removeGameObject(uint uid)
Definition: cgamescene.cpp:350
CObject * autorelease()
Definition: cobject.cpp:87
QList< CGameObject > gameObjects()
Definition: cgamescene.cpp:399
const bool physicsEnabled() const
#define SAFE_RETAIN(x)
Definition: cobject.h:35
virtual void copyValuesFromObject(const CGameScene &game_scene)
Definition: cgamescene.cpp:80
#define RE_ASSERT
Definition: macro.h:57
virtual void stopAllActions()
Definition: cgamescene.cpp:512
virtual void preUpdate()
Definition: cgamescene.cpp:159
btRigidBody * rigidBody() const
#define CDIRECTOR
Definition: cdirector.h:37
CGameScene & operator=(const CGameScene &game_scene)
Definition: cgamescene.cpp:69
#define CLASSETSREPOSITORY
static bool deleteObjectFromVector(std::vector< T * > *vec, void *object_to_delete)
CGameScene()
used to serialize the GameScene
Definition: cgamescene.cpp:43
static bool vectorContainsObject(std::vector< T > *vec, T object_to_find)
void setLocalPosition(float x, float y, float z)
Definition: transform.cpp:165
void removeGameObjectWhenAble(CGameObject *game_object)
Definition: cgamescene.cpp:374
std::vector< CGameObject * > * m_gameObjects
Definition: cgamescene.h:161
Transform & transform()
Definition: clnode.cpp:69
void addGameObject(CGameObject *game_object)
Definition: cgamescene.cpp:244
virtual void updateWorld()
Definition: cgamescene.cpp:446
CObject * retain()
Definition: cobject.cpp:66