32 #include <QMessageBox>
33 #include <QFileDialog>
35 #include <QToolButton>
54 #include "ui_editorwindow.h"
75 m_previousSceneGameObjects = QList<CGameObject>();
77 m_currentSceneFilename =
"";
78 m_isEditingProperty =
false;
81 QBoxLayout* tmp =
new QBoxLayout(QBoxLayout::LeftToRight, 0);
82 tmp->addWidget(m_glViewport);
87 connect(m_glViewport, SIGNAL(newGameObjectSelected(uint)),
88 this, SLOT(onNewGameObjectSelected(uint)));
90 ui->wViewportContainer->setLayout(tmp);
92 setCentralWidget(ui->wViewportContainer);
96 m_timer =
new QTimer(
this);
102 connect(m_propertyBrowser, SIGNAL(selectedObjectOnInspector(QString)),
105 QVBoxLayout* vertical_layout = ui->dwProperties->findChild<QVBoxLayout*>(
"mainLayout");
106 vertical_layout->insertWidget(2, m_propertyBrowser);
108 ui->dwProperties->setContentsMargins(0,0,0,0);
109 ui->wViewportContainer->setFocus();
111 setUpBulletToolbar();
112 setFocusPolicy(Qt::ClickFocus);
125 CDIRECTOR->runWithScene(m_gameEditorScene);
135 void EditorWindow::setState(State state) {
154 void EditorWindow::loadResources() {
169 std::vector<CGameObject*>* gameobjects =
CDIRECTOR->currentGameScene()->getGameObjects();
170 std::vector<CGameObject*>::iterator it;
171 for (it = gameobjects->begin();
172 it != gameobjects->end();
175 if (gameobj->uid() == gameobj_uid) {
186 std::vector<CGameObject*>* gameobjects =
CDIRECTOR->currentGameScene()->getGameObjects();
187 for (
unsigned int i = 0; i < gameobjects->size(); i++) {
189 if (gameobj->objectName() == name) {
221 ui->actionDelete->setEnabled(gameobj_selected);
222 ui->actionDuplicate->setEnabled(gameobj_selected);
223 ui->actionRecalc_AABB->setEnabled(gameobj_selected);
226 ui->actionPlay->setEnabled(m_state ==
EDITING);
227 ui->actionStop->setEnabled(m_state ==
PLAYING);
232 std::string undo_action_description =
"Undo ";
234 undo_action_description += tmp;
236 ui->actionUndo->setText(undo_action_description.c_str());
238 undo_action_description =
"Redo ";
240 undo_action_description += tmp;
242 ui->actionRedo->setText(undo_action_description.c_str());
245 QString res =
":/images/metro/cameraspeed" + QString::number(camera_speed) +
".png";
246 ui->actionToggleCameraSpeed->setIcon(QIcon(res));
248 ui->actionMemory_Leaks_detection->setChecked(m_memoryLeaksDetection);
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));
293 if (!m_isInitialized) {
295 m_isInitialized =
true;
299 m_glViewport->updateGL();
309 m_propertyBrowser->
addChild(game_object,
true);
321 QMainWindow::closeEvent(event);
334 m_tmrBulletProfiler->stop();
349 QApplication::quit();
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()));
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));
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());
379 CDIRECTOR->currentGameScene()->dynamicsWorld()->getDebugDrawer()->setDebugMode(
380 settings.value(
"bulletDebugState").toByteArray().toInt());
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());
388 if(m_recentScenes.size() > 10) m_recentScenes.resize(10);
390 updateMemoryLeaksDetectionStatus();
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) {
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);
410 action->
setHint(
"Add GameObject");
415 return new_game_object;
420 void EditorWindow::on_actionNewScene_triggered() {
421 if (m_currentSceneFilename !=
"" ||
CDIRECTOR->currentGameScene()->getGameObjects()->size() > 0) {
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);
427 if (ret == QMessageBox::Yes) {
428 m_currentSceneFilename =
"";
443 void EditorWindow::on_actionSave_Scene_2_triggered() {
444 if (m_currentSceneFilename !=
"") {
447 on_actionSave_As_triggered();
453 void EditorWindow::on_actionExit_triggered() {
459 void EditorWindow::on_actionSave_As_triggered() {
460 std::string filter =
"RioEngine Game Scenes (*.";
461 filter.append(k_CGameScene_DefaultExt);
464 QString file_name = QFileDialog::getSaveFileName(
this, tr(
"Save Game Scene"),
"/",
467 if (file_name !=
"") {
468 m_currentSceneFilename = file_name.toStdString();
477 void EditorWindow::on_actionAbout_triggered() {
484 void EditorWindow::on_actionReset_Camera_triggered() {
485 CDIRECTOR->getCameraWithId(k_QGLGameEditorViewport_CameraId)->reset();
490 void EditorWindow::on_actionPlay_triggered() {
496 m_previousSceneGameObjects =
CDIRECTOR->currentGameScene()->gameObjects();
504 m_currentGameWindow->setAttribute(Qt::WA_DeleteOnClose,
true);
506 m_currentGameWindow->show();
515 void EditorWindow::on_actionStop_triggered() {
522 m_currentGameWindow = NULL;
530 for(
int i = 0; i < m_recentScenes.size(); i++) {
531 if(m_recentScenes[i] == current_scene_filename) {
537 m_recentScenes.remove(index);
539 m_recentScenes.push(current_scene_filename);
540 if(m_recentScenes.size() > 10) {
541 m_recentScenes.resize(10);
547 void EditorWindow::on_menuRecent_scenes_aboutToShow() {
548 QMenu* menu_recent_files = ui->menuFile->findChild<QMenu*>(
"menuRecent_scenes");
549 menu_recent_files->clear();
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()));
560 void EditorWindow::on_menuEdit_aboutToShow() {
566 void EditorWindow::on_actionUndo_triggered() {
573 void EditorWindow::on_actionRedo_triggered() {
580 void EditorWindow::on_actionShader_Designer_triggered() {
586 void EditorWindow::onNewGameObjectSelected(uint selected_gameobj_uid) {
592 void EditorWindow::on_actionScale_triggered() {
598 void EditorWindow::on_actionTranslate_triggered() {
604 void EditorWindow::on_actionRotate_triggered() {
610 void EditorWindow::on_actionNone_triggered() {
616 void EditorWindow::on_actionUniform_Scale_triggered() {
622 void EditorWindow::on_actionMenuGlobal_triggered() {
628 void EditorWindow::on_actionMenuLocal_triggered() {
634 void EditorWindow::on_actionDelete_triggered() {
637 std::string obj_name = game_obj->objectName().toStdString();
638 if (
CDIRECTOR->currentGameScene()->removeGameObject(game_obj->uid())) {
642 action->
setHint(
"Remove GameObject");
651 void EditorWindow::on_actionQuery_bullet_profiler_triggered() {
652 CProfileManager::dumpAll();
657 void EditorWindow::on_actionOpen_triggered() {
658 std::string filter =
"RioEngine Game Scenes (*.";
659 filter.append(k_CGameScene_DefaultExt);
662 QString file_name = QFileDialog::getOpenFileName(
this, tr(
"Load Game Scene"),
"",
665 if (file_name !=
"") {
666 loadScene(file_name);
672 void EditorWindow::on_menuGAME_OBJECT_aboutToShow() {
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;
690 m_isEditingProperty =
true;
692 if (property_name ==
"EnablePhysics") {
693 deployOrRemoveGameObjInDynamicsWorld(game_obj, value.toBool());
699 void EditorWindow::on_actionCreate_new_triggered() {
700 showCreateGameObjectMenu();
705 void EditorWindow::on_actionDuplicate_triggered() {
706 const CGameObject* gameobj = getSelectedGameObject();
719 void EditorWindow::on_actionRecalc_AABB_triggered() {
722 if (selected_gameobj == NULL || !selected_gameobj->bPhysicsEnabled()) {
725 selected_gameobj->removeFromDynamicsWorld();
726 selected_gameobj->calcSize();
728 selected_gameobj->deployIntoDynamicsWorld();
734 void EditorWindow::on_actionAutoRecalc_AABB_on_resize_triggered(
bool state) {
740 void EditorWindow::on_actionToggleCameraSpeed_triggered() {
747 void EditorWindow::on_actionMemory_Leaks_detection_triggered() {
748 m_memoryLeaksDetection = !m_memoryLeaksDetection;
749 updateMemoryLeaksDetectionStatus();
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());
758 regenerateBodyIfNeeded(static_cast<CGameObject*>(obj), property_name);
759 m_propertyBrowser->
update();
770 if (m_lastPropertyChange.
obj != NULL &&
771 m_lastPropertyChange.
oldValue != m_lastPropertyChange.
obj->property(qPrintable(m_lastPropertyChange.
name))) {
774 m_propertyBrowser->
update();
776 regenerateBodyIfNeeded(static_cast<CGameObject*>(m_lastPropertyChange.
obj), m_lastPropertyChange.
name);
777 m_isEditingProperty =
false;
782 void EditorWindow::onBulletProfilerTimeout() {
783 if (ui->actionBulletProfiler->isChecked()) {
784 CProfileManager::dumpAll();
790 void EditorWindow::onChangeBulletProfilerInterval(
int value) {
791 m_tmrBulletProfiler->start(value * 1000);
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()));
814 m_tmrBulletProfiler =
new QTimer();
815 connect(m_tmrBulletProfiler, SIGNAL(
timeout()),
816 this, SLOT(onBulletProfilerTimeout()));
817 m_tmrBulletProfiler->start(profiler_interval->value() * 1000);
822 void EditorWindow::deployOrRemoveGameObjInDynamicsWorld(
CGameObject* game_obj,
bool deploy) {
823 ( deploy ? game_obj->deployIntoDynamicsWorld() : game_obj->removeFromDynamicsWorld() );
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);
837 void EditorWindow::onModeButtonTriggered() {
838 QToolButton* btn_debug_mode = findChild<QToolButton*>(
"btnDebugMode");
840 QPoint global_pos = btn_debug_mode->mapToGlobal(QPoint(10, 10));
843 int dbg_mode =
CDIRECTOR->currentGameScene()->dynamicsWorld()->getDebugDrawer()->getDebugMode();
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);
861 mode_menu.addSeparator();
862 mode_menu.addAction(
"Default");
863 mode_menu.addAction(
"Select All");
864 mode_menu.addAction(
"No Debug");
867 QAction* selectedItem = mode_menu.exec(global_pos);
871 for (
int i = 0; i < mode_menu.actions().size(); i++) {
872 if (selectedItem == mode_menu.actions()[i]) {
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;
902 dbg_mode = dbg_mode ^ btIDebugDraw::DBG_NoDebug;
904 CDIRECTOR->currentGameScene()->dynamicsWorld()->getDebugDrawer()->setDebugMode(dbg_mode);
909 void EditorWindow::regenerateBodyIfNeeded(
CGameObject* game_object, QString property_name) {
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"
924 if (m_lastPropertyChange.
obj->property(
"EnablePhysics").toBool()) {
926 game_obj->removeFromDynamicsWorld();
927 game_obj->deployIntoDynamicsWorld();
934 void EditorWindow::addDefaultPlane() {
936 plane->setbPhysicsEnabled(
true);
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();
949 void EditorWindow::stopGame() {
954 if (m_currentGameWindow != NULL) {
955 m_currentGameWindow->close();
964 CDIRECTOR->currentGameScene()->setGameObjects(m_previousSceneGameObjects);
966 m_previousSceneGameObjects.clear();
974 void EditorWindow::showCreateGameObjectMenu() {
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)));
986 QAction* res = menu.exec(QCursor::pos());
989 std::string selected_node_str = res->text().toStdString();
990 addNodeHavingId(selected_node_str);
996 const CGameObject* EditorWindow::getSelectedGameObject() {
1008 selected_gameobj->removeFromDynamicsWorld();
1009 selected_gameobj->calcSize();
1011 selected_gameobj->deployIntoDynamicsWorld();
1015 m_propertyBrowser->
update();
1020 void EditorWindow::onRecentSceneSelected() {
1021 QAction* action =
static_cast<QAction*
>(sender());
1022 QString action_text = action->text();
1023 loadScene(action_text);
1028 void EditorWindow::loadScene(QString filename) {
1032 m_currentSceneFilename = filename.toStdString();
1038 void EditorWindow::updateMemoryLeaksDetectionStatus() {
1046 void EditorWindow::afterViewportInitializeGLCall(
QGLGameViewport* game_viewport) {
static void releasePools()
void selectMostRecentGameObject()
void setSelectedTransformMode(Transform::TransformMode transform_mode)
bool areResourcesLoaded()
void repopulatePropertyBrowser()
void selectGameObject(CGameObject *game_object)
void onEditPropertyBegin()
void onGameWindowDestroyedCallback(QObject *obj=0)
EditorWindow(QWidget *parent=0)
Property * createCustomProperty(const QString &name, QObject *propertyObject, Property *parent)
uint selectedGameObjectUID() const
void setSelectedGameObjectUID(uint)
void setSelectedManipulatorType(QGLGameEditorViewport::ManipulatorTypes manipulator_type)
virtual void setHint(const std::string &hint)
void loadResourcesIfNeeded()
std::vector< CGameObject * > * getGameObjects() const
static EditorWindow * currentInstance
#define UNDOABLEACTIONSMANAGER
const bool physicsEnabled() const
void setSelectedTransformMode(const Transform::TransformMode &value)
static void serialize(CObject *obj, QString path)
static void registerCustomStreamOperators()
static void deserialize(CObject *obj, QString path)
void addChild(QObject *child, bool select_immediately=true)
void removeChildFromInspector(QString child_name)
void selectGameObjectHavingUID(uint gameobj_uid)
#define CLASSETSREPOSITORY
void addSceneFilenameToRecentSceneList(QString scene_filename)
void setSelectedManipulatorType(const ManipulatorTypes &value)
State currentState() const
bool autoRecalcAABBOnResize() const
void setAutoRecalcAABBOnResize(bool)
void propertyChanged(QObject *obj, QString property_name, QVariant value, QVariant old_value)
virtual void closeEvent(QCloseEvent *event)
QPropertyEditorWidget * getQPropertyEditorWidget() const
void removeChildInInspector(std::string child)
virtual IUndoableAction * getOppositeAction()