RioEngine  0.1
My first attempt to create a 3D WYSIWYG Game Engine
editorwindow.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 <QTimer>
31 #include <QSettings>
32 #include <QMessageBox>
33 #include <QFileDialog>
34 #include <QSpinBox>
35 #include <QToolButton>
36 #include "constants.h"
37 #include "misc/transform.h"
38 #include "misc/matrixstack.h"
42 #include "cengine/csoundplayer.h"
43 #include "cengine/ccamera.h"
44 #include "cengine/cdirector.h"
52 #include "editor/about.h"
54 #include "ui_editorwindow.h"
55 #include "editor/editorwindow.h"
56 
57 #if VLD_ENABLED
58 #include <vld.h>
59 #endif
60 
61 //-----------------------------------------------------------------------------
62 
64 
65 EditorWindow::EditorWindow(QWidget *parent) :
66  QMainWindow(parent),
67  ui(new Ui::EditorWindow) {
68  currentInstance = this;
71  ui->setupUi(this);
72 
74 
75  m_previousSceneGameObjects = QList<CGameObject>();
76  m_isClosing = false;
77  m_currentSceneFilename = "";
78  m_isEditingProperty = false;
79 
80  m_glViewport = new QGLGameEditorViewport(CLASSETSREPOSITORY, NULL);
81  QBoxLayout* tmp = new QBoxLayout(QBoxLayout::LeftToRight, 0);
82  tmp->addWidget(m_glViewport);
83 
84  loadResources();
85 
86  CCustomScene* m_gameEditorScene = new CCustomScene();
87  connect(m_glViewport, SIGNAL(newGameObjectSelected(uint)),
88  this, SLOT(onNewGameObjectSelected(uint)));
89 
90  ui->wViewportContainer->setLayout(tmp);
91 
92  setCentralWidget(ui->wViewportContainer);
93 
94  INPUTMANAGER->initializeJoystick((HWND)winId());
95 
96  m_timer = new QTimer(this);
97  connect(m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
98  m_timer->start(17); // 60 fps
99 
100  m_propertyBrowser = new QPropertyBrowser(this);
102  connect(m_propertyBrowser, SIGNAL(selectedObjectOnInspector(QString)),
103  this, SLOT(selectGameObject(QString)));
104 
105  QVBoxLayout* vertical_layout = ui->dwProperties->findChild<QVBoxLayout*>("mainLayout");
106  vertical_layout->insertWidget(2, m_propertyBrowser);
107 
108  ui->dwProperties->setContentsMargins(0,0,0,0);
109  ui->wViewportContainer->setFocus();
110 
111  setUpBulletToolbar();
112  setFocusPolicy(Qt::ClickFocus);
113  setState(EDITING);
114  clearSelection();
115 
118 
119  connect(m_glViewport, SIGNAL(selectedGameObjectTransformChanged(QGLGameEditorViewport::ManipulatorTypes)),
120  this, SLOT(onSelectedGameObjectTransformChanged(QGLGameEditorViewport::ManipulatorTypes)));
121 
122  connect(m_glViewport, SIGNAL(afterInitializeGL(QGLGameViewport*)),
123  this, SLOT(afterViewportInitializeGLCall(QGLGameViewport*)));
124 
125  CDIRECTOR->runWithScene(m_gameEditorScene);
126  CDIRECTOR->pause();
127 
128  addDefaultPlane();
129 
130  SAFE_RELEASE(m_gameEditorScene);
131 }
132 
133 //-----------------------------------------------------------------------------
134 
135 void EditorWindow::setState(State state) {
136  m_state = state;
137  updateGUIState();
138 }
139 
140 //-----------------------------------------------------------------------------
141 
143  return m_state;
144 }
145 
146 //-----------------------------------------------------------------------------
147 
149  return CLASSETSREPOSITORY->nodes()->size() > 0;
150 }
151 
152 //-----------------------------------------------------------------------------
153 
154 void EditorWindow::loadResources() {
155  CLASSETSREPOSITORY->loadResources();
156 }
157 
158 //-----------------------------------------------------------------------------
159 
161  if (!areResourcesLoaded()) {
162  loadResources();
163  }
164 }
165 
166 //-----------------------------------------------------------------------------
167 
169  std::vector<CGameObject*>* gameobjects = CDIRECTOR->currentGameScene()->getGameObjects();
170  std::vector<CGameObject*>::iterator it;
171  for (it = gameobjects->begin();
172  it != gameobjects->end();
173  ++it) {
174  CGameObject* gameobj = *it;
175  if (gameobj->uid() == gameobj_uid) {
176  selectGameObject(gameobj);
177  return;
178  }
179  }
180  selectGameObject(NULL);
181 }
182 
183 //-----------------------------------------------------------------------------
184 
185 void EditorWindow::selectGameObject(QString name) {
186  std::vector<CGameObject*>* gameobjects = CDIRECTOR->currentGameScene()->getGameObjects();
187  for (unsigned int i = 0; i < gameobjects->size(); i++) {
188  CGameObject* gameobj = gameobjects->at(i);
189  if (gameobj->objectName() == name) {
190  selectGameObject(gameobj);
191  return;
192  }
193  }
194  selectGameObject(NULL);
195 }
196 
197 //-----------------------------------------------------------------------------
198 
200  m_glViewport->setSelectedTransformMode(transform_mode);
201 
202  ui->actionMenuGlobal->setChecked(transform_mode == Transform::GLOBAL);
203  ui->actionMenuLocal->setChecked(transform_mode == Transform::LOCAL);
204 }
205 
206 //-----------------------------------------------------------------------------
207 
209  m_glViewport->setSelectedManipulatorType(manipulator_type);
210  ui->actionTranslate->setChecked(manipulator_type == QGLGameEditorViewport::TRANSLATION);
211  ui->actionNone->setChecked(manipulator_type == QGLGameEditorViewport::NOMANIPULATOR);
212  ui->actionRotate->setChecked(manipulator_type == QGLGameEditorViewport::ROTATION);
213  ui->actionScale->setChecked(manipulator_type == QGLGameEditorViewport::SCALE);
214  ui->actionUniform_Scale->setChecked(manipulator_type == QGLGameEditorViewport::UNIFORMSCALE);
215 }
216 
217 //-----------------------------------------------------------------------------
218 
220  bool gameobj_selected = m_glViewport->selectedGameObjectUID() != 0;
221  ui->actionDelete->setEnabled(gameobj_selected);
222  ui->actionDuplicate->setEnabled(gameobj_selected);
223  ui->actionRecalc_AABB->setEnabled(gameobj_selected);
224  ui->actionAutoRecalc_AABB_on_resize->setChecked(m_glViewport->autoRecalcAABBOnResize());
225 
226  ui->actionPlay->setEnabled(m_state == EDITING);
227  ui->actionStop->setEnabled(m_state == PLAYING);
228 
229  ui->actionUndo->setEnabled(UNDOABLEACTIONSMANAGER->hasUndoActions());
230  ui->actionRedo->setEnabled(UNDOABLEACTIONSMANAGER->hasRedoActions());
231 
232  std::string undo_action_description = "Undo ";
233  std::string tmp = UNDOABLEACTIONSMANAGER->getHintForCurrentUndoAction();
234  undo_action_description += tmp;
235 
236  ui->actionUndo->setText(undo_action_description.c_str());
237 
238  undo_action_description = "Redo ";
239  tmp = UNDOABLEACTIONSMANAGER->getHintForCurrentRedoAction();
240  undo_action_description += tmp;
241 
242  ui->actionRedo->setText(undo_action_description.c_str());
243 
244  int camera_speed = m_glViewport->cameraSpeed();
245  QString res = ":/images/metro/cameraspeed" + QString::number(camera_speed) + ".png";
246  ui->actionToggleCameraSpeed->setIcon(QIcon(res));
247 
248  ui->actionMemory_Leaks_detection->setChecked(m_memoryLeaksDetection);
249 }
250 
251 //-----------------------------------------------------------------------------
252 
254  selectGameObject(NULL);
255 }
256 
257 //-----------------------------------------------------------------------------
258 
260  m_propertyBrowser->clearModel();
261  std::vector<CGameObject*>* game_objs = CDIRECTOR->currentGameScene()->getGameObjects();
262  for (uint i = 0; i < game_objs->size(); i++) {
263  m_propertyBrowser->addChild(game_objs->at(i));
264  }
265 }
266 
267 //-----------------------------------------------------------------------------
268 
270  CGameScene* game_scene = CDIRECTOR->currentGameScene();
271  unsigned int vec_size = game_scene->getGameObjects()->size();
272  if (vec_size > 0) {
273  CGameObject* last_added = game_scene->getGameObjects()->at(vec_size - 1);
274  selectGameObject(last_added);
275  } else {
276  selectGameObject(NULL);
277  clearSelection();
278  m_propertyBrowser->clearModel();
279  m_propertyBrowser->clearSelection();
280  }
281  updateGUIState();
282 }
283 
284 //-----------------------------------------------------------------------------
285 
287  m_propertyBrowser->removeChildInInspector(name.toStdString());
288 }
289 
290 //-----------------------------------------------------------------------------
291 
293  if (!m_isInitialized) {
294  if (areResourcesLoaded())
295  m_isInitialized = true;
296  }
297 
298  if (m_glViewport) {
299  m_glViewport->updateGL();
300  }
301 
302  CAUTORELEASEPOOL->drain();
303 }
304 
305 //-----------------------------------------------------------------------------
306 
308  if (game_object) {
309  m_propertyBrowser->addChild(game_object, true);
310  m_glViewport->setSelectedGameObjectUID(game_object->uid());
311  updateGUIState();
312  } else {
313  m_glViewport->setSelectedGameObjectUID(0);
314  m_propertyBrowser->clearSelection();
315  }
316 }
317 
318 //-----------------------------------------------------------------------------
319 
320 void EditorWindow::closeEvent(QCloseEvent *event) {
321  QMainWindow::closeEvent(event);
322  // TODO ask for user confirmation
323  //event->ignore(); cancels the event
324  saveLayout();
325 
326  m_isClosing = true;
327  stopGame();
328 
329  SAFE_RELEASE(m_glViewport);
330  m_glViewport = NULL;
331 
332  m_timer->stop();
333  SAFE_RELEASE(m_timer);
334  m_tmrBulletProfiler->stop();
335  SAFE_RELEASE(m_tmrBulletProfiler);
336  // ---------------------------------
339  // ---------------------------------
346 
347  SAFE_RELEASE(m_propertyBrowser);
348 
349  QApplication::quit();
350 }
351 
352 //-----------------------------------------------------------------------------
353 
354 void EditorWindow::saveLayout() {
355  QSettings settings("rioengine.ini", QSettings::IniFormat);
356  settings.setValue("MemoryLeaksDetection", QVariant::fromValue(m_memoryLeaksDetection));
357  settings.setValue("Geometry", saveGeometry());
358  settings.setValue("WindowState", saveState());
359  settings.setValue("bulletDebugState", QByteArray::number(
360  CDIRECTOR->currentGameScene()->dynamicsWorld()->getDebugDrawer()->getDebugMode()));
361 
362  QStringList sceneList = m_recentScenes.toList();
363  settings.beginWriteArray("RecentScenes", sceneList.size());
364  for (int j = 0; j < sceneList.size(); ++j) {
365  settings.setArrayIndex(j);
366  settings.setValue("scene", sceneList.at(j));
367  }
368  settings.endArray();
369 }
370 
371 //-----------------------------------------------------------------------------
372 
373 void EditorWindow::restoreLayout() {
374  QSettings settings("rioengine.ini", QSettings::IniFormat);
375  m_memoryLeaksDetection = settings.value("MemoryLeaksDetection").toBool();
376  restoreGeometry(settings.value("Geometry").toByteArray());
377  restoreState(settings.value("WindowState").toByteArray());
378 
379  CDIRECTOR->currentGameScene()->dynamicsWorld()->getDebugDrawer()->setDebugMode(
380  settings.value("bulletDebugState").toByteArray().toInt());
381 
382  int sceneCount = settings.beginReadArray("RecentScenes");
383  for (int i = 0; i < sceneCount; ++i) {
384  settings.setArrayIndex(i);
385  m_recentScenes.push(settings.value("scene").toString());
386  }
387  settings.endArray();
388  if(m_recentScenes.size() > 10) m_recentScenes.resize(10);
389 
390  updateMemoryLeaksDetectionStatus();
391 }
392 
393 //-----------------------------------------------------------------------------
394 
395 CGameObject* EditorWindow::addNodeHavingId(std::string node_id) {
396  CGameObject* new_game_object = CDIRECTOR->currentGameScene()->createGameObjectWithNode(node_id);
397  new_game_object->calcSize();
398  if (new_game_object) {
399  selectGameObject(new_game_object);
400  } else {
401  QMessageBox msgBox;
402  msgBox.setIcon(QMessageBox::Warning);
403  msgBox.setWindowTitle("Error");
404  msgBox.setText("The node does not exist in the Assets Repository.");
405  msgBox.setStandardButtons(QMessageBox::Ok);
406  msgBox.exec();
407  }
408 
409  AddOrRemoveGameObjectAction* action = new AddOrRemoveGameObjectAction(this, CDIRECTOR->currentGameScene(), new_game_object, true);
410  action->setHint("Add GameObject");
411  UNDOABLEACTIONSMANAGER->pushUndoAction(action->getOppositeAction());
412  SAFE_RELEASE(action);
413  updateGUIState();
414 
415  return new_game_object;
416 }
417 
418 //-----------------------------------------------------------------------------
419 
420 void EditorWindow::on_actionNewScene_triggered() {
421  if (m_currentSceneFilename != "" || CDIRECTOR->currentGameScene()->getGameObjects()->size() > 0) {
422  // ask for user confirmation
423  int ret = QMessageBox::warning(this, tr("Create new scene"),
424  tr("All unsaved changes will be lost. Are you sure you want to continue?"),
425  QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
426 
427  if (ret == QMessageBox::Yes) {
428  m_currentSceneFilename = "";
429  clearSelection();
430  m_propertyBrowser->clearModel();
431  m_propertyBrowser->clearSelection();
432  CDIRECTOR->currentGameScene()->clear();
433  CDIRECTOR->getActiveCamera()->reset();
434  UNDOABLEACTIONSMANAGER->clear();
435  updateGUIState();
436  addDefaultPlane();
437  }
438  }
439 }
440 
441 //-----------------------------------------------------------------------------
442 
443 void EditorWindow::on_actionSave_Scene_2_triggered() {
444  if (m_currentSceneFilename != "") {
445  QSerializer::serialize(CDIRECTOR->currentGameScene(), QString::fromStdString(m_currentSceneFilename)); // save the updated content
446  } else {
447  on_actionSave_As_triggered(); // launch the Save As dialog
448  }
449 }
450 
451 //-----------------------------------------------------------------------------
452 
453 void EditorWindow::on_actionExit_triggered() {
454  close();
455 }
456 
457 //-----------------------------------------------------------------------------
458 
459 void EditorWindow::on_actionSave_As_triggered() {
460  std::string filter = "RioEngine Game Scenes (*.";
461  filter.append(k_CGameScene_DefaultExt);
462  filter.append(")");
463 
464  QString file_name = QFileDialog::getSaveFileName(this, tr("Save Game Scene"), "/",
465  tr(filter.c_str()));
466 
467  if (file_name != "") {
468  m_currentSceneFilename = file_name.toStdString();
469  addSceneFilenameToRecentSceneList(QString::fromStdString(m_currentSceneFilename));
470  QSerializer::serialize(CDIRECTOR->currentGameScene(), QString::fromStdString(m_currentSceneFilename));
471  saveLayout();
472  }
473 }
474 
475 //-----------------------------------------------------------------------------
476 
477 void EditorWindow::on_actionAbout_triggered() {
478  About about = About(this);
479  about.exec();
480 }
481 
482 //-----------------------------------------------------------------------------
483 
484 void EditorWindow::on_actionReset_Camera_triggered() {
485  CDIRECTOR->getCameraWithId(k_QGLGameEditorViewport_CameraId)->reset();
486 }
487 
488 //-----------------------------------------------------------------------------
489 
490 void EditorWindow::on_actionPlay_triggered() {
491  if (currentState() == PLAYING) {
492  return;
493  }
494 
495  // store the current game scene
496  m_previousSceneGameObjects = CDIRECTOR->currentGameScene()->gameObjects();
497 
498  clearSelection();
499  CDIRECTOR->currentGameScene()->run();
501  UNDOABLEACTIONSMANAGER->clear();
502 
503  m_currentGameWindow = new QGameWindow(this, CLASSETSREPOSITORY, CDIRECTOR->currentGameScene(), m_glViewport);
504  m_currentGameWindow->setAttribute(Qt::WA_DeleteOnClose, true);
505 
506  m_currentGameWindow->show();
507 
508  connect(m_currentGameWindow, SIGNAL(destroyed(QObject*)), this, SLOT(onGameWindowDestroyedCallback(QObject*)));
509 
510  setState(PLAYING);
511 }
512 
513 //-----------------------------------------------------------------------------
514 
515 void EditorWindow::on_actionStop_triggered() {
516  stopGame();
517 }
518 
519 //-----------------------------------------------------------------------------
520 
522  m_currentGameWindow = NULL;
523  stopGame();
524 }
525 
526 //-----------------------------------------------------------------------------
527 
528 void EditorWindow::addSceneFilenameToRecentSceneList(QString current_scene_filename) {
529  int index = -1;
530  for(int i = 0; i < m_recentScenes.size(); i++) {
531  if(m_recentScenes[i] == current_scene_filename) {
532  index = i;
533  break;
534  }
535  }
536  if(index != -1) {
537  m_recentScenes.remove(index);
538  }
539  m_recentScenes.push(current_scene_filename);
540  if(m_recentScenes.size() > 10) {
541  m_recentScenes.resize(10);
542  }
543 }
544 
545 //-----------------------------------------------------------------------------
546 
547 void EditorWindow::on_menuRecent_scenes_aboutToShow() {
548  QMenu* menu_recent_files = ui->menuFile->findChild<QMenu*>("menuRecent_scenes");
549  menu_recent_files->clear();
550 
551  for(int i = m_recentScenes.size() - 1; i >= 0; i--) {
552  QAction* action = new QAction(m_recentScenes[i], menu_recent_files);
553  menu_recent_files->addAction(action);
554  QObject::connect(action, SIGNAL(triggered()), SLOT(onRecentSceneSelected()));
555  }
556 }
557 
558 //-----------------------------------------------------------------------------
559 
560 void EditorWindow::on_menuEdit_aboutToShow() {
561  updateGUIState();
562 }
563 
564 //-----------------------------------------------------------------------------
565 
566 void EditorWindow::on_actionUndo_triggered() {
567  UNDOABLEACTIONSMANAGER->performUndo();
568  updateGUIState();
569 }
570 
571 //-----------------------------------------------------------------------------
572 
573 void EditorWindow::on_actionRedo_triggered() {
574  UNDOABLEACTIONSMANAGER->performRedo();
575  updateGUIState();
576 }
577 
578 //-----------------------------------------------------------------------------
579 
580 void EditorWindow::on_actionShader_Designer_triggered() {
581  // TODO remove
582 }
583 
584 //-----------------------------------------------------------------------------
585 
586 void EditorWindow::onNewGameObjectSelected(uint selected_gameobj_uid) {
587  selectGameObjectHavingUID(selected_gameobj_uid);
588 }
589 
590 //-----------------------------------------------------------------------------
591 
592 void EditorWindow::on_actionScale_triggered() {
594 }
595 
596 //-----------------------------------------------------------------------------
597 
598 void EditorWindow::on_actionTranslate_triggered() {
600 }
601 
602 //-----------------------------------------------------------------------------
603 
604 void EditorWindow::on_actionRotate_triggered() {
606 }
607 
608 //-----------------------------------------------------------------------------
609 
610 void EditorWindow::on_actionNone_triggered() {
612 }
613 
614 //-----------------------------------------------------------------------------
615 
616 void EditorWindow::on_actionUniform_Scale_triggered() {
618 }
619 
620 //-----------------------------------------------------------------------------
621 
622 void EditorWindow::on_actionMenuGlobal_triggered() {
624 }
625 
626 //-----------------------------------------------------------------------------
627 
628 void EditorWindow::on_actionMenuLocal_triggered() {
630 }
631 
632 //-----------------------------------------------------------------------------
633 
634 void EditorWindow::on_actionDelete_triggered() {
635  CGameObject* game_obj = (CGameObject*)getSelectedGameObject();
636  RE_ASSERT(game_obj);
637  std::string obj_name = game_obj->objectName().toStdString();
638  if (CDIRECTOR->currentGameScene()->removeGameObject(game_obj->uid())) {
639  m_propertyBrowser->removeChildInInspector(obj_name);
640  AddOrRemoveGameObjectAction* action = new AddOrRemoveGameObjectAction(this, CDIRECTOR->currentGameScene(),
641  game_obj, false);
642  action->setHint("Remove GameObject");
643  UNDOABLEACTIONSMANAGER->pushUndoAction(action->getOppositeAction());
644  SAFE_RELEASE(action);
646  }
647 }
648 
649 //-----------------------------------------------------------------------------
650 
651 void EditorWindow::on_actionQuery_bullet_profiler_triggered() {
652  CProfileManager::dumpAll();
653 }
654 
655 //-----------------------------------------------------------------------------
656 
657 void EditorWindow::on_actionOpen_triggered() {
658  std::string filter = "RioEngine Game Scenes (*.";
659  filter.append(k_CGameScene_DefaultExt);
660  filter.append(")");
661 
662  QString file_name = QFileDialog::getOpenFileName(this, tr("Load Game Scene"), "",
663  tr(filter.c_str()));
664 
665  if (file_name != "") {
666  loadScene(file_name);
667  }
668 }
669 
670 //-----------------------------------------------------------------------------
671 
672 void EditorWindow::on_menuGAME_OBJECT_aboutToShow() {
673  updateGUIState();
674 }
675 
676 //-----------------------------------------------------------------------------
677 
678 void EditorWindow::propertyChanged(QObject * obj, QString property_name, QVariant value, QVariant old_value) {
679  CGameObject* game_obj = static_cast<CGameObject*>(obj);
680  if (!m_isEditingProperty) {
681  std::vector<CGameObject*>* game_objs = CDIRECTOR->currentGameScene()->getGameObjects();
682  for (uint i = 0; i < game_objs->size(); i++) {
683  if (game_objs->at(i) == obj) {
684  m_lastPropertyChange.obj = obj;
685  m_lastPropertyChange.name = property_name;
686  m_lastPropertyChange.value = value;
687  m_lastPropertyChange.oldValue = old_value;
688  }
689  }
690  m_isEditingProperty = true;
691  }
692  if (property_name == "EnablePhysics") {
693  deployOrRemoveGameObjInDynamicsWorld(game_obj, value.toBool());
694  }
695 }
696 
697 //-----------------------------------------------------------------------------
698 
699 void EditorWindow::on_actionCreate_new_triggered() {
700  showCreateGameObjectMenu();
701 }
702 
703 //-----------------------------------------------------------------------------
704 
705 void EditorWindow::on_actionDuplicate_triggered() {
706  const CGameObject* gameobj = getSelectedGameObject();
707  RE_ASSERT(gameobj);
708  CGameObject* clone = CDIRECTOR->currentGameScene()->duplicateGameObject(gameobj);
709  clone->transform().setLocalPosition(clone->transform().localPosition() + btVector3(0.1f, 0, 0));
711  selectGameObject(clone);
712 
713  DuplicateGameObject* action = new DuplicateGameObject(this, CDIRECTOR->currentGameScene(), clone, true);
714  UNDOABLEACTIONSMANAGER->pushUndoAction(action->getOppositeAction());
715 }
716 
717 //-----------------------------------------------------------------------------
718 
719 void EditorWindow::on_actionRecalc_AABB_triggered() {
720  CGameObject* selected_gameobj = (CGameObject*)getSelectedGameObject();
721  RE_ASSERT(selected_gameobj);
722  if (selected_gameobj == NULL || !selected_gameobj->bPhysicsEnabled()) {
723  return;
724  }
725  selected_gameobj->removeFromDynamicsWorld();
726  selected_gameobj->calcSize();
727  if(selected_gameobj->bulletProperties.physicsEnabled()) {
728  selected_gameobj->deployIntoDynamicsWorld();
729  }
730 }
731 
732 //-----------------------------------------------------------------------------
733 
734 void EditorWindow::on_actionAutoRecalc_AABB_on_resize_triggered(bool state) {
735  m_glViewport->setAutoRecalcAABBOnResize(state);
736 }
737 
738 //-----------------------------------------------------------------------------
739 
740 void EditorWindow::on_actionToggleCameraSpeed_triggered() {
741  m_glViewport->nextCameraSpeed();
742  updateGUIState();
743 }
744 
745 //-----------------------------------------------------------------------------
746 
747 void EditorWindow::on_actionMemory_Leaks_detection_triggered() {
748  m_memoryLeaksDetection = !m_memoryLeaksDetection;
749  updateMemoryLeaksDetectionStatus();
750 }
751 
752 //-----------------------------------------------------------------------------
753 
754 void EditorWindow::onInspectorActionPeformed(QObject* obj, QString property_name, QVariant value, QVariant old_value) {
755  if (property_name == "EnablePhysics") {
756  deployOrRemoveGameObjInDynamicsWorld(reinterpret_cast<CGameObject*>(obj), value.toBool());
757  }
758  regenerateBodyIfNeeded(static_cast<CGameObject*>(obj), property_name);
759  m_propertyBrowser->update();
760 }
761 
762 //-----------------------------------------------------------------------------
763 
765 }
766 
767 //-----------------------------------------------------------------------------
768 
770  if (m_lastPropertyChange.obj != NULL &&
771  m_lastPropertyChange.oldValue != m_lastPropertyChange.obj->property(qPrintable(m_lastPropertyChange.name))) {
772  InspectorAction* action = new InspectorAction(reinterpret_cast<CGameObject*>(m_lastPropertyChange.obj), m_lastPropertyChange.name, m_lastPropertyChange.oldValue);
773  UNDOABLEACTIONSMANAGER->pushUndoAction(reinterpret_cast<IUndoableAction*>(action));
774  m_propertyBrowser->update();
775  }
776  regenerateBodyIfNeeded(static_cast<CGameObject*>(m_lastPropertyChange.obj), m_lastPropertyChange.name);
777  m_isEditingProperty = false;
778 }
779 
780 //-----------------------------------------------------------------------------
781 
782 void EditorWindow::onBulletProfilerTimeout() {
783  if (ui->actionBulletProfiler->isChecked()) {
784  CProfileManager::dumpAll();
785  }
786 }
787 
788 //-----------------------------------------------------------------------------
789 
790 void EditorWindow::onChangeBulletProfilerInterval(int value) {
791  m_tmrBulletProfiler->start(value * 1000);
792 }
793 
794 //-----------------------------------------------------------------------------
795 
796 void EditorWindow::setUpBulletToolbar() {
797  QSpinBox* profiler_interval = new QSpinBox();
798  QToolButton* mode_button = new QToolButton();
799  mode_button->setObjectName("btnDebugMode");
800  mode_button->setText("Debug Mode");
801  profiler_interval->setMinimum(1);
802  profiler_interval->setValue(5);
803  profiler_interval->setMaximumWidth(50);
804  profiler_interval->setMaximumHeight(ui->tbBullet->height());
805  connect(profiler_interval, SIGNAL(valueChanged(int)),
806  this, SLOT(onChangeBulletProfilerInterval(int)));
807  ui->tbBullet->addWidget(profiler_interval);
808  ui->actionBulletProfiler->setEnabled(true);
809  ui->tbBullet->addAction(ui->actionBulletProfiler);
810  ui->tbBullet->addWidget(mode_button);
811  connect(mode_button, SIGNAL(clicked()),
812  this, SLOT(onModeButtonTriggered()));
813 
814  m_tmrBulletProfiler = new QTimer();
815  connect(m_tmrBulletProfiler, SIGNAL(timeout()),
816  this, SLOT(onBulletProfilerTimeout()));
817  m_tmrBulletProfiler->start(profiler_interval->value() * 1000);
818 }
819 
820 //-----------------------------------------------------------------------------
821 
822 void EditorWindow::deployOrRemoveGameObjInDynamicsWorld(CGameObject* game_obj, bool deploy) {
823  ( deploy ? game_obj->deployIntoDynamicsWorld() : game_obj->removeFromDynamicsWorld() );
824 }
825 
826 //-----------------------------------------------------------------------------
827 
828 void EditorWindow::createActionForDebugModeMenu(QMenu* menu, QString text, int bitmask, int option) {
829  QAction* action = new QAction(text, menu);
830  action->setCheckable(true);
831  action->setChecked(bitmask & option);
832  menu->addAction(action);
833 }
834 
835 //-----------------------------------------------------------------------------
836 
837 void EditorWindow::onModeButtonTriggered() {
838  QToolButton* btn_debug_mode = findChild<QToolButton*>("btnDebugMode");
839  RE_ASSERT(btn_debug_mode);
840  QPoint global_pos = btn_debug_mode->mapToGlobal(QPoint(10, 10));
841  QMenu mode_menu;
842 
843  int dbg_mode = CDIRECTOR->currentGameScene()->dynamicsWorld()->getDebugDrawer()->getDebugMode();
844 
845  createActionForDebugModeMenu(&mode_menu, "DrawWireframe", dbg_mode, (int)btIDebugDraw::DBG_DrawWireframe);
846  createActionForDebugModeMenu(&mode_menu, "DrawAabb", dbg_mode, (int)btIDebugDraw::DBG_DrawAabb);
847  createActionForDebugModeMenu(&mode_menu, "DrawFeaturesText", dbg_mode, (int)btIDebugDraw::DBG_DrawFeaturesText);
848  createActionForDebugModeMenu(&mode_menu, "DrawContactPoints", dbg_mode, (int)btIDebugDraw::DBG_DrawContactPoints);
849  createActionForDebugModeMenu(&mode_menu, "NoDeactivation", dbg_mode, (int)btIDebugDraw::DBG_NoDeactivation);
850  createActionForDebugModeMenu(&mode_menu, "NoHelpText", dbg_mode, (int)btIDebugDraw::DBG_NoHelpText);
851  createActionForDebugModeMenu(&mode_menu, "DrawText", dbg_mode, (int)btIDebugDraw::DBG_DrawText);
852  createActionForDebugModeMenu(&mode_menu, "ProfileTimings", dbg_mode, (int)btIDebugDraw::DBG_ProfileTimings);
853  createActionForDebugModeMenu(&mode_menu, "EnableSatComparison", dbg_mode, (int)btIDebugDraw::DBG_EnableSatComparison);
854  createActionForDebugModeMenu(&mode_menu, "DisableBulletLCP", dbg_mode, (int)btIDebugDraw::DBG_DisableBulletLCP);
855  createActionForDebugModeMenu(&mode_menu, "EnableCCD", dbg_mode, (int)btIDebugDraw::DBG_EnableCCD);
856  createActionForDebugModeMenu(&mode_menu, "DrawContraints", dbg_mode, (int)btIDebugDraw::DBG_DrawConstraints);
857  createActionForDebugModeMenu(&mode_menu, "DrawContraintsLimits", dbg_mode, (int)btIDebugDraw::DBG_DrawConstraintLimits);
858  createActionForDebugModeMenu(&mode_menu, "FastWireframe", dbg_mode, (int)btIDebugDraw::DBG_FastWireframe);
859  createActionForDebugModeMenu(&mode_menu, "DrawNormals", dbg_mode, (int)btIDebugDraw::DBG_DrawNormals);
860 
861  mode_menu.addSeparator();
862  mode_menu.addAction("Default");
863  mode_menu.addAction("Select All");
864  mode_menu.addAction("No Debug");
865  // ...
866 
867  QAction* selectedItem = mode_menu.exec(global_pos);
868  // TODO is there an easier way to get the index of the action in the QMenu?
869  int index = -1;
870  if (selectedItem) {
871  for (int i = 0; i < mode_menu.actions().size(); i++) {
872  if (selectedItem == mode_menu.actions()[i]) {
873  index = i;
874  break;
875  }
876  }
877  }
878  if (index < 0) {
879  return;
880  }
881 
882  switch (index) {
883  case 0: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawWireframe; break;
884  case 1: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawAabb; break;
885  case 2: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawFeaturesText; break;
886  case 3: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawContactPoints; break;
887  case 4: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_NoDeactivation; break;
888  case 5: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_NoHelpText; break;
889  case 6: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawText; break;
890  case 7: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_ProfileTimings; break;
891  case 8: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_EnableSatComparison; break;
892  case 9: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DisableBulletLCP; break;
893  case 10: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_EnableCCD; break;
894  case 11: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawConstraints; break;
895  case 12: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawConstraintLimits; break;
896  case 13: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_FastWireframe; break;
897  case 14: dbg_mode = dbg_mode ^ btIDebugDraw::DBG_DrawNormals; break;
898  case 16: dbg_mode = k_bdebugdraw_DefaultDebugMode; break;
899  case 17: dbg_mode = INT_MAX; break;
900  case 18: dbg_mode = 0; break;
901  default:
902  dbg_mode = dbg_mode ^ btIDebugDraw::DBG_NoDebug;
903  }
904  CDIRECTOR->currentGameScene()->dynamicsWorld()->getDebugDrawer()->setDebugMode(dbg_mode);
905 }
906 
907 //-----------------------------------------------------------------------------
908 
909 void EditorWindow::regenerateBodyIfNeeded(CGameObject* game_object, QString property_name) {
910  if (
911  property_name == "Mass" ||
912  property_name == "Restitution" ||
913  property_name == "Friction" ||
914  property_name == "LinearFactor" ||
915  property_name == "AngularFactor" ||
916  property_name == "ShapeType" ||
917  property_name == "ShapeType_Radius" ||
918  property_name == "ShapeType_Height" ||
919  property_name == "ShapeType_Size" ||
920  property_name == "ShapeType_Vertices" ||
921  property_name == "ShapeType_PlaneNormal" ||
922  property_name == "ShapeType_PlaneConstant"
923  ) {
924  if (m_lastPropertyChange.obj->property("EnablePhysics").toBool()) {
925  CGameObject* game_obj = static_cast<CGameObject*>(m_lastPropertyChange.obj);
926  game_obj->removeFromDynamicsWorld();
927  game_obj->deployIntoDynamicsWorld();
928  }
929  }
930 }
931 
932 //-----------------------------------------------------------------------------
933 
934 void EditorWindow::addDefaultPlane() {
935  CGameObject* plane = addNodeHavingId("Grass");
936  plane->setbPhysicsEnabled(true);
937  plane->setShapeType(CBulletProperties::StaticPlane);
938  plane->setbShapeTypePlaneNormal(btVector3(0,0,1));
939  plane->setRotation(-90.0f, 0, 0);
940  plane->setbRestitution(1.0f);
941  plane->setbFriction(1.5f);
942  plane->setScale(50.0f, 50.0f, 50.0f);
943  plane->deployIntoDynamicsWorld();
944  clearSelection();
945 }
946 
947 //-----------------------------------------------------------------------------
948 
949 void EditorWindow::stopGame() {
950  if (m_state != PLAYING) {
951  return;
952  }
953 
954  if (m_currentGameWindow != NULL) {
955  m_currentGameWindow->close();
956  }
957 
958  CDIRECTOR->pause();
959  m_glViewport->setSelectedGameObjectUID(0);
960 
961  CDIRECTOR->currentGameScene()->clear();
962  // restore the original scene's game objects
963  if (!m_isClosing) {
964  CDIRECTOR->currentGameScene()->setGameObjects(m_previousSceneGameObjects);
965  }
966  m_previousSceneGameObjects.clear();
968  CDIRECTOR->resetCameras();
969  setState(EDITING);
970 }
971 
972 //-----------------------------------------------------------------------------
973 
974 void EditorWindow::showCreateGameObjectMenu() {
975  QMenu menu(this);
976 
977  std::vector<std::string> nodes_list = CLASSETSREPOSITORY->getNodeIdList();
978  for (unsigned int i = 0; i < nodes_list.size(); i++) {
979  std::string node_id = nodes_list.at(i);
980  std::string prefix = "__hidden";
981  if (node_id.compare(0, 8, prefix) != 0) {
982  menu.addAction(QString::fromStdString(nodes_list.at(i)));
983  }
984  }
985 
986  QAction* res = menu.exec(QCursor::pos());
987 
988  if (res) {
989  std::string selected_node_str = res->text().toStdString();
990  addNodeHavingId(selected_node_str);
991  }
992 }
993 
994 //-----------------------------------------------------------------------------
995 
996 const CGameObject* EditorWindow::getSelectedGameObject() {
997  return static_cast<const CGameObject*>(CDIRECTOR->currentGameScene()->getGameObject(
998  m_glViewport->selectedGameObjectUID()));
999 }
1000 
1001 //-----------------------------------------------------------------------------
1002 
1003 void EditorWindow::onSelectedGameObjectTransformChanged(QGLGameEditorViewport::ManipulatorTypes selected_manipulator) {
1004  if (selected_manipulator == QGLGameEditorViewport::SCALE) {
1005  if (m_glViewport->autoRecalcAABBOnResize()) {
1006  CGameObject* selected_gameobj = (CGameObject*)getSelectedGameObject();
1007  RE_ASSERT(selected_gameobj);
1008  selected_gameobj->removeFromDynamicsWorld();
1009  selected_gameobj->calcSize();
1010  if(selected_gameobj->bulletProperties.physicsEnabled()) {
1011  selected_gameobj->deployIntoDynamicsWorld();
1012  }
1013  }
1014  }
1015  m_propertyBrowser->update();
1016 }
1017 
1018 //-----------------------------------------------------------------------------
1019 
1020 void EditorWindow::onRecentSceneSelected() {
1021  QAction* action = static_cast<QAction*>(sender());
1022  QString action_text = action->text();
1023  loadScene(action_text);
1024 }
1025 
1026 //-----------------------------------------------------------------------------
1027 
1028 void EditorWindow::loadScene(QString filename) {
1029  CDIRECTOR->currentGameScene()->clear();
1030  QSerializer::deserialize(CDIRECTOR->currentGameScene(), filename);
1032  m_currentSceneFilename = filename.toStdString();
1033  addSceneFilenameToRecentSceneList(QString::fromStdString(m_currentSceneFilename));
1034 }
1035 
1036 //-----------------------------------------------------------------------------
1037 
1038 void EditorWindow::updateMemoryLeaksDetectionStatus() {
1039 #if VLD_ENABLED
1040  ( m_memoryLeaksDetection ? VLDEnable() : VLDDisable() );
1041 #endif
1042 }
1043 
1044 //-----------------------------------------------------------------------------
1045 
1046 void EditorWindow::afterViewportInitializeGLCall(QGLGameViewport* game_viewport) {
1047  restoreLayout();
1048  updateGUIState();
1049 }
1050 
1051 //-----------------------------------------------------------------------------
1052 
1054  SAFE_RELEASE(ui);
1055 }
#define VLDDisable()
Definition: vld.h:291
#define CSOUNDPLAYER
Definition: csoundplayer.h:38
void registerTypes()
Definition: customtypes.cpp:41
static void releasePools()
void selectMostRecentGameObject()
Definition: about.h:6
QVariant oldValue
Definition: editorwindow.h:50
void registerCustomPropertyCB(UserTypeCB callback)
void setSelectedTransformMode(Transform::TransformMode transform_mode)
Definition: about.h:10
bool areResourcesLoaded()
void repopulatePropertyBrowser()
const btVector3 & localPosition(UnitType unit_type=WORLD) const
Definition: transform.cpp:105
void selectGameObject(CGameObject *game_object)
void clearSelection()
void onEditPropertyBegin()
void onGameWindowDestroyedCallback(QObject *obj=0)
EditorWindow(QWidget *parent=0)
Property * createCustomProperty(const QString &name, QObject *propertyObject, Property *parent)
Definition: customtypes.cpp:68
void setSelectedManipulatorType(QGLGameEditorViewport::ManipulatorTypes manipulator_type)
void timeout(void)
virtual void setHint(const std::string &hint)
void loadResourcesIfNeeded()
std::vector< CGameObject * > * getGameObjects() const
Definition: cgamescene.cpp:288
#define SAFE_RELEASE(x)
Definition: cobject.h:36
static void free()
Definition: csingleton.h:49
static EditorWindow * currentInstance
Definition: editorwindow.h:69
#define UNDOABLEACTIONSMANAGER
const bool physicsEnabled() const
QVariant value
Definition: editorwindow.h:50
void setSelectedTransformMode(const Transform::TransformMode &value)
void updateGUIState()
static void serialize(CObject *obj, QString path)
Definition: qserializer.cpp:42
#define RE_ASSERT
Definition: macro.h:57
static void registerCustomStreamOperators()
#define VLDEnable()
Definition: vld.h:290
void onEditPropertyEnd()
static void deserialize(CObject *obj, QString path)
Definition: qserializer.cpp:62
void addChild(QObject *child, bool select_immediately=true)
void removeChildFromInspector(QString child_name)
void selectGameObjectHavingUID(uint gameobj_uid)
#define CDIRECTOR
Definition: cdirector.h:37
#define CLASSETSREPOSITORY
#define CAUTORELEASEPOOL
QObject * obj
Definition: editorwindow.h:48
void setLocalPosition(float x, float y, float z)
Definition: transform.cpp:165
void addSceneFilenameToRecentSceneList(QString scene_filename)
void setSelectedManipulatorType(const ManipulatorTypes &value)
State currentState() const
#define INPUTMANAGER
Definition: inputmanager.h:39
void propertyChanged(QObject *obj, QString property_name, QVariant value, QVariant old_value)
virtual void closeEvent(QCloseEvent *event)
QPropertyEditorWidget * getQPropertyEditorWidget() const
Transform & transform()
Definition: clnode.cpp:69
void removeChildInInspector(std::string child)
virtual IUndoableAction * getOppositeAction()