diff --git a/src/interface/modeler/quickapp/MainModelerWindow.cpp b/src/interface/modeler/quickapp/MainModelerWindow.cpp index fcf8fd1..c0ac81f 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.cpp +++ b/src/interface/modeler/quickapp/MainModelerWindow.cpp @@ -37,6 +37,24 @@ MainModelerWindow::MainModelerWindow() water = new WaterModeler(this); render_process = new RenderProcess(this, render_preview_provider); + + // Bind file buttons + QObject *button_new = findQmlObject("tool_file_new"); + if (button_new) { + connect(button_new, SIGNAL(clicked()), this, SLOT(newFile())); + } + QObject *button_save = findQmlObject("tool_file_save"); + if (button_save) { + connect(button_save, SIGNAL(clicked()), this, SLOT(saveFile())); + } + QObject *button_load = findQmlObject("tool_file_load"); + if (button_load) { + connect(button_load, SIGNAL(clicked()), this, SLOT(loadFile())); + } + QObject *button_exit = findQmlObject("tool_file_exit"); + if (button_exit) { + connect(button_exit, SIGNAL(clicked()), this, SLOT(exit())); + } } MainModelerWindow::~MainModelerWindow() @@ -76,6 +94,32 @@ void MainModelerWindow::setState(const QString &stateName) rootObject()->setProperty("state", stateName); } +void MainModelerWindow::newFile() +{ + getScenery()->autoPreset(); + renderer->reset(); +} + +void MainModelerWindow::saveFile() +{ + getScenery()->saveGlobal("saved.p3d"); +} + +void MainModelerWindow::loadFile() +{ + Scenery loaded; + if (loaded.loadGlobal("saved.p3d") == Scenery::FILE_OPERATION_OK) + { + loaded.copy(scenery); + renderer->reset(); + } +} + +void MainModelerWindow::exit() +{ + QGuiApplication::instance()->exit(); +} + void MainModelerWindow::keyReleaseEvent(QKeyEvent *event) { if (getState() == "Render Dialog") @@ -113,30 +157,28 @@ void MainModelerWindow::keyReleaseEvent(QKeyEvent *event) { if (event->modifiers() & Qt::ControlModifier) { - QGuiApplication::instance()->exit(); + exit(); } } else if (event->key() == Qt::Key_N) { if (event->modifiers() & Qt::ControlModifier) { - getScenery()->autoPreset(); - renderer->reset(); + newFile(); } } else if (event->key() == Qt::Key_S) { if (event->modifiers() & Qt::ControlModifier) { - getScenery()->saveGlobal("saved.p3d"); + saveFile(); } } else if (event->key() == Qt::Key_L or event->key() == Qt::Key_O) { if (event->modifiers() & Qt::ControlModifier) { - getScenery()->loadGlobal("saved.p3d"); - renderer->reset(); + loadFile(); } } else if (event->key() == Qt::Key_Z) diff --git a/src/interface/modeler/quickapp/MainModelerWindow.h b/src/interface/modeler/quickapp/MainModelerWindow.h index a48cf26..6f37fcb 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.h +++ b/src/interface/modeler/quickapp/MainModelerWindow.h @@ -25,6 +25,12 @@ public: inline OpenGLRenderer *getRenderer() const {return renderer;} inline ModelerCameras *getCamera() const {return cameras;} +public slots: + void newFile(); + void saveFile(); + void loadFile(); + void exit(); + protected: virtual void keyReleaseEvent(QKeyEvent *event) override; diff --git a/src/interface/modeler/quickapp/qml/BaseChoice.qml b/src/interface/modeler/quickapp/qml/BaseChoice.qml index f0ec228..df650f5 100644 --- a/src/interface/modeler/quickapp/qml/BaseChoice.qml +++ b/src/interface/modeler/quickapp/qml/BaseChoice.qml @@ -4,9 +4,8 @@ import QtQuick.Layouts 1.1 Item { default property alias children : inner_layout.children + property alias spacing : inner_layout.spacing property int value - width: 100 - height: 32 ExclusiveGroup { id: choice_group diff --git a/src/interface/modeler/quickapp/qml/BaseChoiceItem.qml b/src/interface/modeler/quickapp/qml/BaseChoiceItem.qml index 7e87197..bafaf7b 100644 --- a/src/interface/modeler/quickapp/qml/BaseChoiceItem.qml +++ b/src/interface/modeler/quickapp/qml/BaseChoiceItem.qml @@ -7,18 +7,23 @@ Rectangle { property bool checked: false property ExclusiveGroup exclusiveGroup: null property int value + property int padding: 4 color: "#333333" + radius: padding * 2 signal toggled(bool value) - width: 20 - height: 20 + width: 40 + height: 40 Image { - anchors.fill: parent + id: icon_image source: parent.icon - antialiasing: true + width: parent.width - 2 * parent.padding + height: parent.height - 2 * parent.padding + anchors.centerIn: parent + antialiasing: true } MouseArea { @@ -35,6 +40,12 @@ Rectangle { onCheckedChanged: choice_item.toggled(checked) + Behavior on color { + PropertyAnimation { + duration: 200 + } + } + states: [ State { name: "Checked" @@ -42,7 +53,7 @@ Rectangle { PropertyChanges { target: choice_item - color: "#999999" + color: "#dddddd" } } diff --git a/src/interface/modeler/quickapp/qml/BasePanel.qml b/src/interface/modeler/quickapp/qml/BasePanel.qml index 36652ae..6250d04 100644 --- a/src/interface/modeler/quickapp/qml/BasePanel.qml +++ b/src/interface/modeler/quickapp/qml/BasePanel.qml @@ -4,22 +4,21 @@ BaseRectangle { property ToolbarButton tool id: panel - enabled: false width: 200 - height: parent.height - 100 - color: "#a0909090" + height: primary_toolbar.current ? primary_toolbar.current.height : 10 + color: "#40909090" - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter + anchors.left: primary_toolbar.current ? primary_toolbar.current.right : parent.left + anchors.top: primary_toolbar.current ? primary_toolbar.current.top : parent.top states: [ State { - name: "Active" - when: tool.selected + name: "hidden" + when: !tool.selected PropertyChanges { target: panel - enabled: true + enabled: false } } diff --git a/src/interface/modeler/quickapp/qml/BaseRectangle.qml b/src/interface/modeler/quickapp/qml/BaseRectangle.qml index 956ccbb..c074bb7 100644 --- a/src/interface/modeler/quickapp/qml/BaseRectangle.qml +++ b/src/interface/modeler/quickapp/qml/BaseRectangle.qml @@ -10,4 +10,3 @@ Rectangle { } } } - diff --git a/src/interface/modeler/quickapp/qml/BaseSecondaryToolbar.qml b/src/interface/modeler/quickapp/qml/BaseSecondaryToolbar.qml new file mode 100644 index 0000000..bd4670f --- /dev/null +++ b/src/interface/modeler/quickapp/qml/BaseSecondaryToolbar.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +Toolbar { + enabled: false + height: parent.height - primary_toolbar.height + anchors.left: primary_toolbar.left + anchors.top: primary_toolbar.bottom + + onEnabledChanged: primary_toolbar.current = this +} + diff --git a/src/interface/modeler/quickapp/qml/CameraChoice.qml b/src/interface/modeler/quickapp/qml/CameraChoice.qml index b8bdb57..ebbfbee 100644 --- a/src/interface/modeler/quickapp/qml/CameraChoice.qml +++ b/src/interface/modeler/quickapp/qml/CameraChoice.qml @@ -1,29 +1,22 @@ import QtQuick 2.0 -BaseRectangle { +Toolbar { id: camera_choice - width: 200 - height: 50 + horizontal: false color: "#90888888" objectName: "camera_choice" - Row { - id: inner_space - anchors.centerIn: parent - spacing: 15 + ToolbarButton { + id: camera_choice_render + picture: "images/tab_display.png" + hovertext: qsTr("Final render camera") + selected: true + } - ToolbarButton { - id: camera_choice_render - picture: "images/tab_display.png" - hovertext: qsTr("Switch to the final camera") - selected: true - } - - ToolbarButton { - id: camera_choice_topdown - picture: "images/display_topdown.png" - hovertext: qsTr("Switch to the top-down camera") - } + ToolbarButton { + id: camera_choice_topdown + picture: "images/display_topdown.png" + hovertext: qsTr("Top-down camera") } states: [ diff --git a/src/interface/modeler/quickapp/qml/ClickableImage.qml b/src/interface/modeler/quickapp/qml/ClickableImage.qml new file mode 100644 index 0000000..a8c9291 --- /dev/null +++ b/src/interface/modeler/quickapp/qml/ClickableImage.qml @@ -0,0 +1,15 @@ +import QtQuick 2.0 + +Image { + signal clicked() + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + + onClicked: { + parent.clicked(); + } + } +} + diff --git a/src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml b/src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml index 00f680b..74f188c 100644 --- a/src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml +++ b/src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml @@ -3,10 +3,11 @@ import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 BasePanel { - width: 70 + id: daytime + width: 100 objectName: "atmosphere_daytime" - default property real value: day_night.value == 2 ? 1.0 : slider.value * 0.54 + 0.23; + default property real value: day_night.value == 2 ? 0.0 : slider.value * 0.54 + 0.23; signal changed(real value) onValueChanged: { @@ -20,15 +21,19 @@ BasePanel { ColumnLayout { - anchors.fill: parent - anchors.margins: 10 + height: parent.height + anchors.horizontalCenter: parent.horizontalCenter spacing: 20 + Item {height: 1} + BaseChoice { id: day_night - width: parent.width - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + Layout.alignment: Qt.AlignHCenter + spacing: 10 + width: 90 + height: 40 BaseChoiceItem { icon: "images/icon_atmosphere_day.png" @@ -47,7 +52,97 @@ BasePanel { Layout.maximumWidth: 15 Layout.fillHeight: true Layout.alignment: Qt.AlignHCenter - visible: day_night.value == 1 } + + Grid { + id: clock + property int hour: daytime.value * 86400 / 3600 + property int minute: (daytime.value * 86400 - 3600 * hour) / 60 + property int second: daytime.value * 86400 - 3600 * hour - 60 * minute + rows: 3 + columns: 5 + rowSpacing: 4 + + ClickableImage { + width: 20 + height: 10 + source: "qrc:/images/arrow_up.png" + onClicked: slider.value += (1.0 / 24.0) / 0.54 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "qrc:/images/arrow_up.png" + onClicked: slider.value += (1.0 / 3600.0) / 0.54 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "qrc:/images/arrow_up.png" + onClicked: slider.value += (1.0 / 86400.0) / 0.54 + } + + Text { + text: (clock.hour > 9 ? "" : "0") + clock.hour.toString() + font.pixelSize: 14 + } + Text { + text: " : " + font.pixelSize: 14 + } + Text { + text: (clock.minute > 9 ? "" : "0") + clock.minute.toString() + font.pixelSize: 14 + } + Text { + text: " : " + font.pixelSize: 14 + } + Text { + text: (clock.second > 9 ? "" : "0") + clock.second.toString() + font.pixelSize: 14 + } + + ClickableImage { + width: 20 + height: 10 + source: "qrc:/images/arrow_down.png" + onClicked: slider.value -= (1.0 / 24.0) / 0.54 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "qrc:/images/arrow_down.png" + onClicked: slider.value -= (1.0 / 1440.0) / 0.54 + } + Item {width: 1; height: 1} + ClickableImage { + width: 20 + height: 10 + source: "qrc:/images/arrow_down.png" + onClicked: slider.value -= (1.0 / 86400.0) / 0.54 + } + } + + Item {height: 1} } + + states: [ + State { + name: "night" + when: day_night.value == 2 + PropertyChanges { + target: slider + enabled: false + } + PropertyChanges { + target: clock + enabled: false + } + } + + ] } diff --git a/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml b/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml index 90d4be0..74b084a 100644 --- a/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml +++ b/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml @@ -1,7 +1,7 @@ import QtQuick 2.2 BasePanel { - width: 20 + width: 40 BaseSlider { objectName: "water_height" @@ -9,5 +9,6 @@ BasePanel { maximumValue: 1 orientation: Qt.Vertical anchors.fill: parent + anchors.margins: 10 } } diff --git a/src/interface/modeler/quickapp/qml/Toolbar.qml b/src/interface/modeler/quickapp/qml/Toolbar.qml index 3e04d5e..ad5e73d 100644 --- a/src/interface/modeler/quickapp/qml/Toolbar.qml +++ b/src/interface/modeler/quickapp/qml/Toolbar.qml @@ -3,13 +3,16 @@ import QtQuick 2.0 BaseRectangle { default property alias children : inner_space.children - width: 70 - height: parent.height + property bool horizontal: false + width: horizontal ? parent.width : 60 + height: horizontal ? 60 : parent.height color: "#50888888" - Column { + Grid { id: inner_space - spacing: (parent.height - children.length * tool_terrain.height) / (children.length + 1) + columns: parent.horizontal ? children.length : 1 + rows: parent.horizontal ? 1 : children.length + spacing: (parent.horizontal ? (parent.width - children.length * tool_terrain.width) : (parent.height - children.length * tool_terrain.height)) / (children.length + 1) anchors.centerIn: parent } diff --git a/src/interface/modeler/quickapp/qml/ToolbarButton.qml b/src/interface/modeler/quickapp/qml/ToolbarButton.qml index ab7719f..cab0f34 100644 --- a/src/interface/modeler/quickapp/qml/ToolbarButton.qml +++ b/src/interface/modeler/quickapp/qml/ToolbarButton.qml @@ -59,6 +59,7 @@ Item { onEntered: { parent.hovered = true; tooltip_widget.hovertext = hovertext; + tooltip_widget.hovered = this; } onExited: { parent.hovered = false; diff --git a/src/interface/modeler/quickapp/qml/Tooltip.qml b/src/interface/modeler/quickapp/qml/Tooltip.qml index 05e1631..64b52c8 100644 --- a/src/interface/modeler/quickapp/qml/Tooltip.qml +++ b/src/interface/modeler/quickapp/qml/Tooltip.qml @@ -1,16 +1,31 @@ import QtQuick 2.0 BaseRectangle { + property var hovered property string helptext property string hovertext - width: content.width - height: content.height + width: content.width + 10 + height: content.height + 10 + enabled: content.deftext ? true : false + anchors.margins: 5 color: "#99000000" Text { id: content color: "white" - text: parent.helptext || parent.hovertext + font.bold: true + font.pixelSize: 12 + property string deftext: parent.helptext || parent.hovertext + property string oldtext + text: deftext || oldtext + anchors.centerIn: parent + + onDeftextChanged: { + if (deftext) + { + oldtext = deftext; + } + } } } diff --git a/src/interface/modeler/quickapp/qml/app.qrc b/src/interface/modeler/quickapp/qml/app.qrc index 3b20493..db80c69 100644 --- a/src/interface/modeler/quickapp/qml/app.qrc +++ b/src/interface/modeler/quickapp/qml/app.qrc @@ -28,5 +28,14 @@ RenderDialog.qml CameraChoice.qml BaseRectangle.qml + BaseSecondaryToolbar.qml + images/icon_exit.png + images/icon_file_load.png + images/icon_file_new.png + images/icon_file_save.png + images/tab_file.png + images/arrow_down.png + images/arrow_up.png + ClickableImage.qml diff --git a/src/interface/modeler/quickapp/qml/images/arrow_down.png b/src/interface/modeler/quickapp/qml/images/arrow_down.png new file mode 100644 index 0000000..8c1365e Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/arrow_down.png differ diff --git a/src/interface/modeler/quickapp/qml/images/arrow_up.png b/src/interface/modeler/quickapp/qml/images/arrow_up.png new file mode 100644 index 0000000..2f6c816 Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/arrow_up.png differ diff --git a/src/interface/modeler/quickapp/qml/images/icon_exit.png b/src/interface/modeler/quickapp/qml/images/icon_exit.png new file mode 100644 index 0000000..136c54e Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_exit.png differ diff --git a/src/interface/modeler/quickapp/qml/images/icon_file_load.png b/src/interface/modeler/quickapp/qml/images/icon_file_load.png new file mode 100644 index 0000000..0502784 Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_file_load.png differ diff --git a/src/interface/modeler/quickapp/qml/images/icon_file_new.png b/src/interface/modeler/quickapp/qml/images/icon_file_new.png new file mode 100644 index 0000000..661ed40 Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_file_new.png differ diff --git a/src/interface/modeler/quickapp/qml/images/icon_file_save.png b/src/interface/modeler/quickapp/qml/images/icon_file_save.png new file mode 100644 index 0000000..1fadb03 Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_file_save.png differ diff --git a/src/interface/modeler/quickapp/qml/images/tab_file.png b/src/interface/modeler/quickapp/qml/images/tab_file.png new file mode 100644 index 0000000..9730761 Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/tab_file.png differ diff --git a/src/interface/modeler/quickapp/qml/main.qml b/src/interface/modeler/quickapp/qml/main.qml index 951e286..337a7b1 100644 --- a/src/interface/modeler/quickapp/qml/main.qml +++ b/src/interface/modeler/quickapp/qml/main.qml @@ -11,66 +11,58 @@ OpenGLView { Tooltip { id: tooltip_widget - anchors.top: parent.top - anchors.right: parent.right + anchors.top: primary_toolbar.bottom + anchors.right: primary_toolbar.right } Toolbar { id: primary_toolbar + horizontal: true color: "#90888888" + property var current + anchors.top: parent.top anchors.left: parent.left - ToolbarButton { - id: tool_display - picture: "images/tab_display.png" - hovertext: qsTr("Display options") - } ToolbarButton { id: tool_terrain picture: "images/tab_terrain.png" + hovertext: qsTr("Terrain edition") } ToolbarButton { id: tool_textures picture: "images/tab_textures.png" + hovertext: qsTr("Terrain textures") } ToolbarButton { id: tool_water picture: "images/icon_water.png" - hovertext: "Water tools" + hovertext: qsTr("Water tools") } ToolbarButton { id: tool_atmosphere picture: "images/icon_atmosphere.png" - hovertext: "Atmosphere/weather tools" + hovertext: qsTr("Atmosphere/weather control") } ToolbarButton { id: tool_clouds picture: "images/tab_clouds.png" + hovertext: qsTr("Cloud layers") } ToolbarButton { id: tool_render picture: "images/tab_render.png" + hovertext: qsTr("Rendering") } - } - - Toolbar { - id: display_toolbar - enabled: false - anchors.left: primary_toolbar.right - ToolbarButton { - id: tool_display_topdown - picture: "images/display_topdown.png" - hovertext: qsTr("Top-down view") - helptext: qsTr("Drag the mouse on the map to change the viewpoint.") + id: tool_file + picture: "images/tab_file.png" + hovertext: qsTr("File") } } - Toolbar { + BaseSecondaryToolbar { id: water_toolbar - enabled: false - anchors.left: primary_toolbar.right ToolbarButton { id: tool_water_level @@ -79,10 +71,8 @@ OpenGLView { } } - Toolbar { + BaseSecondaryToolbar { id: atmosphere_toolbar - enabled: false - anchors.left: primary_toolbar.right ToolbarButton { id: tool_atmosphere_daytime @@ -91,10 +81,8 @@ OpenGLView { } } - Toolbar { + BaseSecondaryToolbar { id: render_toolbar - enabled: false - anchors.left: primary_toolbar.right ToolbarButton { id: tool_render_quick @@ -104,10 +92,43 @@ OpenGLView { } } + BaseSecondaryToolbar { + id: file_toolbar + + ToolbarButton { + id: tool_file_new + objectName: "tool_file_new" + picture: "images/icon_file_new.png" + hovertext: qsTr("Generate a new scene") + } + + ToolbarButton { + id: tool_file_save + objectName: "tool_file_save" + picture: "images/icon_file_save.png" + hovertext: qsTr("Save the current scene to a file") + } + + ToolbarButton { + id: tool_file_load + objectName: "tool_file_load" + picture: "images/icon_file_load.png" + hovertext: qsTr("Load a scene from a file") + } + + ToolbarButton { + id: tool_file_exit + objectName: "tool_file_exit" + picture: "images/icon_exit.png" + hovertext: qsTr("Exit the program") + } + } + CameraChoice { id: camera_choice - anchors.bottom: main_ui.bottom - anchors.horizontalCenter: main_ui.horizontalCenter + height: 150 + anchors.right: main_ui.right + anchors.verticalCenter: main_ui.verticalCenter } RenderDialog { @@ -126,15 +147,6 @@ OpenGLView { } states: [ - State { - name: "Display Mode" - when: tool_display.selected - - PropertyChanges { - target: display_toolbar - enabled: true - } - }, State { name: "Water Mode" when: tool_water.selected @@ -162,6 +174,15 @@ OpenGLView { enabled: true } }, + State { + name: "File Mode" + when: tool_file.selected + + PropertyChanges { + target: file_toolbar + enabled: true + } + }, State { name: "Render Dialog"