diff --git a/src/Mara/Gui/Icons/gizmo.png b/src/Mara/Gui/Icons/gizmo.png new file mode 100644 index 0000000000000000000000000000000000000000..0ce5f231b2ca453988e3e6e4f85efd581f319461 Binary files /dev/null and b/src/Mara/Gui/Icons/gizmo.png differ diff --git a/src/Mara/Gui/Icons/rotate.png b/src/Mara/Gui/Icons/rotate.png new file mode 100644 index 0000000000000000000000000000000000000000..524b79ee23813fea2c545513aa151e73057f1684 Binary files /dev/null and b/src/Mara/Gui/Icons/rotate.png differ diff --git a/src/Mara/Gui/Icons/scale.png b/src/Mara/Gui/Icons/scale.png new file mode 100644 index 0000000000000000000000000000000000000000..68a9165691c655b0af5b0a5d5a973382b1c5a1b1 Binary files /dev/null and b/src/Mara/Gui/Icons/scale.png differ diff --git a/src/Mara/Gui/Icons/select.png b/src/Mara/Gui/Icons/select.png new file mode 100644 index 0000000000000000000000000000000000000000..fcb01d78412bcfd0b631fbc9167565fcfe44bd48 Binary files /dev/null and b/src/Mara/Gui/Icons/select.png differ diff --git a/src/Mara/Gui/Icons/translate.png b/src/Mara/Gui/Icons/translate.png new file mode 100644 index 0000000000000000000000000000000000000000..9c52302bb31fbe4b7abdd068e90663040c426558 Binary files /dev/null and b/src/Mara/Gui/Icons/translate.png differ diff --git a/src/Mara/Gui/MainWindow.cpp b/src/Mara/Gui/MainWindow.cpp index 630690ba1f3b0f2cb94b3d6edcfd0d47e29eaf85..cafa1e2d6ce285e3fdd87373a1d40b30c511c7c7 100644 --- a/src/Mara/Gui/MainWindow.cpp +++ b/src/Mara/Gui/MainWindow.cpp @@ -6,10 +6,11 @@ #include <QColorDialog> #include <QFileDialog> #include <QMessageBox> +#include <QToolBar> #include <Gui/SelectionManager/SelectionManager.hpp> -#include <Gui/TreeModel/EntityTreeModel.hpp> #include <Gui/Viewer/CameraManipulator.hpp> +#include <Gui/Viewer/Gizmo/GizmoManager.hpp> #include <Gui/Viewer/Viewer.hpp> #include <PluginBase/RadiumPluginInterface.hpp> @@ -41,7 +42,10 @@ MainWindow::MainWindow( QWidget* parent ) : MainWindowInterface( parent ) { // Initialize the scene interactive representation m_sceneModel = new ItemModel( Ra::Engine::RadiumEngine::getInstance(), this ); m_selectionManager = new SelectionManager( m_sceneModel, this ); - + connect( m_selectionManager, + &Ra::Gui::SelectionManager::selectionChanged, + this, + &MainWindow::onSelectionChanged ); // initialize Gui for the application auto viewerwidget = QWidget::createWindowContainer( m_viewer.get() ); viewerwidget->setAutoFillBackground( false ); @@ -71,7 +75,124 @@ void MainWindow::cleanup() { m_viewer.reset( nullptr ); } +void MainWindow::addSelectionToolBar() { + auto selectionToolBar = new QToolBar( "Selection toolbar", this ); + + auto actionGizmoOff = new QAction( selectionToolBar ); + actionGizmoOff->setObjectName( QString::fromUtf8( "actionGizmoOff" ) ); + actionGizmoOff->setCheckable( false ); + actionGizmoOff->setChecked( false ); + QIcon icon3; + icon3.addFile( + QString::fromUtf8( ":/Resources/Icons/select.png" ), QSize(), QIcon::Normal, QIcon::On ); + actionGizmoOff->setIcon( icon3 ); + actionGizmoOff->setText( QCoreApplication::translate( "MainWindow", "No Gizmos", nullptr ) ); + actionGizmoOff->setToolTip( + QCoreApplication::translate( "MainWindow", "Disable transform gizmo.", nullptr ) ); + + auto actionGizmoTranslate = new QAction( selectionToolBar ); + actionGizmoTranslate->setObjectName( QString::fromUtf8( "actionGizmoTranslate" ) ); + actionGizmoTranslate->setCheckable( false ); + QIcon icon; + icon.addFile( + QString::fromUtf8( ":/Resources/Icons/translate.png" ), QSize(), QIcon::Normal, QIcon::On ); + actionGizmoTranslate->setIcon( icon ); + actionGizmoTranslate->setText( + QCoreApplication::translate( "MainWindow", "Translate", nullptr ) ); + actionGizmoTranslate->setToolTip( + QCoreApplication::translate( "MainWindow", "Translate selected object", nullptr ) ); + + auto actionGizmoRotate = new QAction( selectionToolBar ); + actionGizmoRotate->setObjectName( QString::fromUtf8( "actionGizmoRotate" ) ); + actionGizmoRotate->setCheckable( false ); + QIcon icon1; + icon1.addFile( + QString::fromUtf8( ":/Resources/Icons/rotate.png" ), QSize(), QIcon::Normal, QIcon::On ); + actionGizmoRotate->setIcon( icon1 ); + actionGizmoRotate->setText( QCoreApplication::translate( "MainWindow", "Rotate", nullptr ) ); + actionGizmoRotate->setToolTip( + QCoreApplication::translate( "MainWindow", "Rotate selected object", nullptr ) ); + + auto actionToggle_Local_Global = new QAction( selectionToolBar ); + actionToggle_Local_Global->setObjectName( QString::fromUtf8( "actionToggle_Local_Global" ) ); + actionToggle_Local_Global->setCheckable( true ); + QIcon icon2; + icon2.addFile( + QString::fromUtf8( ":/Resources/Icons/gizmo.png" ), QSize(), QIcon::Normal, QIcon::On ); + actionToggle_Local_Global->setIcon( icon2 ); + actionToggle_Local_Global->setText( + QCoreApplication::translate( "MainWindow", "Toggle Local/Global", nullptr ) ); + actionToggle_Local_Global->setToolTip( QCoreApplication::translate( + "MainWindow", "Changes the transform edition mode", nullptr ) ); + + auto actionGizmoScale = new QAction( selectionToolBar ); + actionGizmoScale->setObjectName( QString::fromUtf8( "actionGizmoScale" ) ); + actionGizmoScale->setCheckable( false ); + QIcon icon5; + icon5.addFile( + QString::fromUtf8( ":/Resources/Icons/scale.png" ), QSize(), QIcon::Normal, QIcon::Off ); + actionGizmoScale->setIcon( icon5 ); + actionGizmoScale->setText( QCoreApplication::translate( "MainWindow", "Scale", nullptr ) ); + actionGizmoScale->setToolTip( + QCoreApplication::translate( "MainWindow", "Scale selected object", nullptr ) ); + + selectionToolBar->addAction( actionToggle_Local_Global ); + selectionToolBar->addAction( actionGizmoTranslate ); + selectionToolBar->addAction( actionGizmoRotate ); + selectionToolBar->addAction( actionGizmoScale ); + selectionToolBar->addAction( actionGizmoOff ); + + connect( + this, &MainWindow::selectedItem, m_viewer->getGizmoManager(), &GizmoManager::setEditable ); + connect( actionGizmoOff, &QAction::triggered, this, &MainWindow::gizmoShowNone ); + connect( actionGizmoTranslate, &QAction::triggered, this, &MainWindow::gizmoShowTranslate ); + connect( actionGizmoRotate, &QAction::triggered, this, &MainWindow::gizmoShowRotate ); + connect( actionGizmoScale, &QAction::triggered, this, &MainWindow::gizmoShowScale ); + connect( actionToggle_Local_Global, + &QAction::toggled, + m_viewer->getGizmoManager(), + &GizmoManager::setLocal ); + connect( actionToggle_Local_Global, &QAction::toggled, this, &MainWindow::frameUpdate ); + + this->addToolBar( selectionToolBar ); + + auto showSelectionToolbar = new QAction( this ); + showSelectionToolbar->setObjectName( QString::fromUtf8( "showSelectionToolbar" ) ); + showSelectionToolbar->setCheckable( true ); + showSelectionToolbar->setChecked( true ); + showSelectionToolbar->setText( + QCoreApplication::translate( "MainWindow", "Selection toolbar", nullptr ) ); + showSelectionToolbar->setToolTip( + QCoreApplication::translate( "MainWindow", "Show/hide the selection toolbar", nullptr ) ); + + connect( showSelectionToolbar, &QAction::triggered, selectionToolBar, &QToolBar::setVisible ); + connect( selectionToolBar, &QToolBar::visibilityChanged, [showSelectionToolbar]( bool b ) { + showSelectionToolbar->setChecked( b ); + } ); + + menuToolbars->addAction( showSelectionToolbar ); +} + +void MainWindow::postOpenGLInitializations() { + addSelectionToolBar(); +} + void MainWindow::createConnections() { + // Radium engine and Gui initialization process + connect( m_viewer.get(), &Viewer::glInitialized, this, &MainWindow::postOpenGLInitializations ); + + // Define and connect Engine callbacks + auto add = std::bind( &MainWindow::ItemAdded, this, std::placeholders::_1 ); + auto del = std::bind( &MainWindow::ItemRemoved, this, std::placeholders::_1 ); + // Connect engine signals to the appropriate callbacks + auto theEngine = Ra::Engine::RadiumEngine::getInstance(); + theEngine->getSignalManager()->m_entityCreatedCallbacks.push_back( add ); + theEngine->getSignalManager()->m_entityDestroyedCallbacks.push_back( del ); + theEngine->getSignalManager()->m_componentAddedCallbacks.push_back( add ); + theEngine->getSignalManager()->m_componentRemovedCallbacks.push_back( del ); + theEngine->getSignalManager()->m_roAddedCallbacks.push_back( add ); + theEngine->getSignalManager()->m_roRemovedCallbacks.push_back( del ); + // Qt Gui callbacks connect( action_Load, &QAction::triggered, this, &MainWindow::loadFile ); connect( actionInfo, &QAction::triggered, this, &MainWindow::displayFileInfo ); @@ -88,18 +209,6 @@ void MainWindow::createConnections() { connect( actionTree_view, &QAction::triggered, this, &MainWindow::displayTreeView ); #endif - // Define and connect Engine callbacks - auto add = std::bind( &MainWindow::ItemAdded, this, std::placeholders::_1 ); - auto del = std::bind( &MainWindow::ItemRemoved, this, std::placeholders::_1 ); - // Connect engine signals to the appropriate callbacks - auto theEngine = Ra::Engine::RadiumEngine::getInstance(); - theEngine->getSignalManager()->m_entityCreatedCallbacks.push_back( add ); - theEngine->getSignalManager()->m_entityDestroyedCallbacks.push_back( del ); - theEngine->getSignalManager()->m_componentAddedCallbacks.push_back( add ); - theEngine->getSignalManager()->m_componentRemovedCallbacks.push_back( del ); - theEngine->getSignalManager()->m_roAddedCallbacks.push_back( add ); - theEngine->getSignalManager()->m_roRemovedCallbacks.push_back( del ); - // TODO : connect callbacks roAdded and roRemoved to the renderer and add observable on // RenderObject to manage more efficiently update for rendering connect( m_sceneModel, &ItemModel::visibilityROChanged, this, &MainWindow::setROVisible ); @@ -293,4 +402,43 @@ void MainWindow::on_actionStep_triggered() { Ra::Engine::RadiumEngine::getInstance()->step(); emit frameUpdate(); } + +void MainWindow::gizmoShowNone() { + m_viewer->getGizmoManager()->changeGizmoType( GizmoManager::NONE ); + emit frameUpdate(); +} + +void MainWindow::gizmoShowTranslate() { + m_viewer->getGizmoManager()->changeGizmoType( GizmoManager::TRANSLATION ); + emit frameUpdate(); +} + +void MainWindow::gizmoShowRotate() { + m_viewer->getGizmoManager()->changeGizmoType( GizmoManager::ROTATION ); + emit frameUpdate(); +} + +void MainWindow::gizmoShowScale() { + m_viewer->getGizmoManager()->changeGizmoType( GizmoManager::SCALE ); + emit frameUpdate(); +} + +void MainWindow::onSelectionChanged( const QItemSelection& /*selected*/, + const QItemSelection& /*deselected*/ ) { + std::cerr << "******************* MainWindow::onSelectionChanged " << std::endl; + if ( m_selectionManager->hasSelection() ) + { + const ItemEntry& ent = m_selectionManager->currentItem(); + std::cerr << "******************* MainWindow::onSelectionChanged emit selected item " + << std::endl; + emit selectedItem( ent ); + /* + * @todo : complete this method to handle how events due to election changes + * cf RadiumSandBox/Mainwindow + */ + } + else + { emit selectedItem( ItemEntry() ); } +} + } // namespace Mara diff --git a/src/Mara/Gui/MainWindow.hpp b/src/Mara/Gui/MainWindow.hpp index 276dbfd4f6cf1dfc434412b2d38252fe715f20b3..ad25425cd5c22270758da779ee2a5e7fce3d34e0 100644 --- a/src/Mara/Gui/MainWindow.hpp +++ b/src/Mara/Gui/MainWindow.hpp @@ -81,6 +81,9 @@ class MainWindow : public Ra::Gui::MainWindowInterface, private Ui::MainWindow void timeFlow( bool state ); + /// Emitted when a new item is selected. An invalid entry is sent when no item is selected. + void selectedItem( const Ra::Engine::Scene::ItemEntry& entry ); + public slots: /// Called when a scene is ready to display to parameterize the application window and the /// viewer. @@ -133,7 +136,28 @@ class MainWindow : public Ra::Gui::MainWindowInterface, private Ui::MainWindow /// Slot for the user requesting to reset time. void on_actionStop_triggered(); + /// Show/hide gizmos when selected an object + void gizmoShowNone(); + + /// Display translation gizmo + void gizmoShowTranslate(); + + /// Display rotation gizmo + void gizmoShowRotate(); + + /// Display scaling gizmo + void gizmoShowScale(); + + /// React to a selection in the selection manager + void onSelectionChanged( const QItemSelection& selected, const QItemSelection& deselected ); + + /// Slot to init renderers once gl is ready + void postOpenGLInitializations(); + private: + /// add the selection toolbar + void addSelectionToolBar(); + /// create the UI connections void createConnections(); diff --git a/src/Mara/Gui/MaraResources.qrc b/src/Mara/Gui/MaraResources.qrc index 78012a0e67ab38af0c1538ea8de1be2c14663252..bd8f863fef5b03d37777a5785a071ebd06ff36b1 100644 --- a/src/Mara/Gui/MaraResources.qrc +++ b/src/Mara/Gui/MaraResources.qrc @@ -8,5 +8,10 @@ <file>Icons/step_on.png</file> <file>Icons/stop_off.png</file> <file>Icons/stop_on.png</file> + <file>Icons/gizmo.png</file> + <file>Icons/rotate.png</file> + <file>Icons/scale.png</file> + <file>Icons/select.png</file> + <file>Icons/translate.png</file> </qresource> </RCC> diff --git a/src/Mara/Gui/ui/MainWindow.ui b/src/Mara/Gui/ui/MainWindow.ui index 12c90b92574312f00c3bc4aa1f48bbbbc70c447e..003ad7431dae27d92a4baff6003f28cba5b655d4 100644 --- a/src/Mara/Gui/ui/MainWindow.ui +++ b/src/Mara/Gui/ui/MainWindow.ui @@ -50,25 +50,31 @@ <property name="title"> <string>Control</string> </property> - <addaction name="actionShow_toolbar"/> <addaction name="separator"/> <addaction name="actionInfo"/> <addaction name="separator"/> </widget> + <widget class="QMenu" name="menuToolbars"> + <property name="title"> + <string>Toolbars</string> + </property> + <addaction name="showAnimationToolbar"/> + </widget> + <addaction name="menuRadium"/> <addaction name="menu_File"/> <addaction name="menuControl"/> - <addaction name="menuRadium"/> + <addaction name="menuToolbars"/> </widget> <widget class="QStatusBar" name="statusbar"/> - <widget class="QToolBar" name="toolBar"> + <widget class="QToolBar" name="AnimationToolbar"> <property name="enabled"> <bool>true</bool> </property> <property name="windowTitle"> - <string>toolBar</string> + <string>Animation toolbar</string> </property> <property name="movable"> - <bool>false</bool> + <bool>true</bool> </property> <property name="iconSize"> <size> @@ -110,6 +116,9 @@ <property name="text"> <string>&Reload shaders</string> </property> + <property name="shortcut"> + <string>Ctrl+Alt+R</string> + </property> </action> <action name="actionTree_view"> <property name="text"> @@ -149,8 +158,7 @@ <normaloff>:/Resources/Icons/play_on.png</normaloff> <normalon>:/Resources/Icons/pause_on.png</normalon> <activeoff>:/Resources/Icons/play_on.png</activeoff> - <activeon>:/Resources/Icons/pause_on.png</activeon>:/Resources/Icons/play_on.png - </iconset> + <activeon>:/Resources/Icons/pause_on.png</activeon>:/Resources/Icons/play_on.png</iconset> </property> <property name="text"> <string>play</string> @@ -168,8 +176,7 @@ <normaloff>:/Resources/Icons/stop_on.png</normaloff> <normalon>:/Resources/Icons/stop_on.png</normalon> <activeoff>:/Resources/Icons/stop_on.png</activeoff> - <activeon>:/Resources/Icons/stop_on.png</activeon>:/Resources/Icons/stop_on.png - </iconset> + <activeon>:/Resources/Icons/stop_on.png</activeon>:/Resources/Icons/stop_on.png</iconset> </property> <property name="text"> <string>stop</string> @@ -189,8 +196,7 @@ <iconset resource="../MaraResources.qrc"> <normaloff>:/Resources/Icons/step_on.png</normaloff> <normalon>:/Resources/Icons/step_on.png</normalon> - <activeoff>:/Resources/Icons/step_on.png</activeoff>:/Resources/Icons/step_on.png - </iconset> + <activeoff>:/Resources/Icons/step_on.png</activeoff>:/Resources/Icons/step_on.png</iconset> </property> <property name="text"> <string>step</string> @@ -202,7 +208,7 @@ <string>Meta+Space</string> </property> </action> - <action name="actionShow_toolbar"> + <action name="showAnimationToolbar"> <property name="checkable"> <bool>true</bool> </property> @@ -210,10 +216,10 @@ <bool>true</bool> </property> <property name="text"> - <string>Show toolbar</string> + <string>Animation toolbar</string> </property> <property name="toolTip"> - <string>Show/hide the toolbar</string> + <string>Show/hide the animation toolbar</string> </property> </action> </widget> @@ -222,9 +228,9 @@ </resources> <connections> <connection> - <sender>actionShow_toolbar</sender> + <sender>showAnimationToolbar</sender> <signal>triggered(bool)</signal> - <receiver>toolBar</receiver> + <receiver>AnimationToolbar</receiver> <slot>setVisible(bool)</slot> <hints> <hint type="sourcelabel"> @@ -237,5 +243,21 @@ </hint> </hints> </connection> + <connection> + <sender>AnimationToolbar</sender> + <signal>visibilityChanged(bool)</signal> + <receiver>showAnimationToolbar</receiver> + <slot>setChecked(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>399</x> + <y>39</y> + </hint> + <hint type="destinationlabel"> + <x>-1</x> + <y>-1</y> + </hint> + </hints> + </connection> </connections> </ui>