diff --git a/graphics/icons.png b/graphics/icons.png index 77dbd89..b3e56b0 100644 Binary files a/graphics/icons.png and b/graphics/icons.png differ diff --git a/graphics/icons.svg b/graphics/icons.svg index d57fe81..ab65164 100644 --- a/graphics/icons.svg +++ b/graphics/icons.svg @@ -7,6 +7,7 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="210mm" @@ -27,18 +28,19 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="3.959798" - inkscape:cx="170.49504" - inkscape:cy="957.94588" + inkscape:zoom="1.979899" + inkscape:cx="468.77289" + inkscape:cy="831.55692" inkscape:document-units="px" - inkscape:current-layer="layer1" + inkscape:current-layer="g3986" showgrid="true" inkscape:window-width="1920" inkscape:window-height="1030" inkscape:window-x="1440" inkscape:window-y="25" inkscape:window-maximized="1" - showguides="true"> + showguides="true" + inkscape:snap-object-midpoints="false"> @@ -51,7 +53,7 @@ image/svg+xml - + @@ -95,5 +97,100 @@ id="path3807" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccccccccc" /> + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/definition/AtmosphereDefinition.cpp b/src/definition/AtmosphereDefinition.cpp index 0cbb27f..7e74e9c 100644 --- a/src/definition/AtmosphereDefinition.cpp +++ b/src/definition/AtmosphereDefinition.cpp @@ -105,6 +105,22 @@ void AtmosphereDefinition::validate() _daytime = (double)hour / 24.0 + (double)minute / 1440.0; } +void AtmosphereDefinition::setDaytime(double value) +{ + if (value >= 0.0) + { + value = fmod(value, 1.0); + } + else + { + value = 1.0 - fmod(-value, 1.0); + } + value *= 1440.0; + hour = value / 60.0; + minute = value - 60.0 * hour; + validate(); +} + void AtmosphereDefinition::applyPreset(AtmospherePreset preset) { sun_color.r = 1.0; diff --git a/src/definition/AtmosphereDefinition.h b/src/definition/AtmosphereDefinition.h index 0067ecf..0fbfa92 100644 --- a/src/definition/AtmosphereDefinition.h +++ b/src/definition/AtmosphereDefinition.h @@ -46,6 +46,11 @@ public: virtual void copy(BaseDefinition* destination) const override; virtual void validate() override; + /** + * Set the daytime from a 0.0-1.0 value. + */ + void setDaytime(double value); + void applyPreset(AtmospherePreset preset); void generateStars(int count); diff --git a/src/interface/modeler/quickapp/AtmosphereModeler.cpp b/src/interface/modeler/quickapp/AtmosphereModeler.cpp new file mode 100644 index 0000000..5dcf86d --- /dev/null +++ b/src/interface/modeler/quickapp/AtmosphereModeler.cpp @@ -0,0 +1,26 @@ +#include "AtmosphereModeler.h" + +#include "MainModelerWindow.h" +#include "Scenery.h" +#include "AtmosphereDefinition.h" +#include "OpenGLRenderer.h" +#include "OpenGLSkybox.h" + +AtmosphereModeler::AtmosphereModeler(MainModelerWindow *main): + main(main) +{ + QObject *item = main->findQmlObject("atmosphere_daytime"); + if (item) + { + connect(item, SIGNAL(changed(double)), this, SLOT(daytimeChanged(double))); + } +} + +void AtmosphereModeler::daytimeChanged(double value) +{ + main->getScenery()->getAtmosphere()->setDaytime(value); + + main->getRenderer()->getScenery()->setAtmosphere(main->getScenery()->getAtmosphere()); + + main->getRenderer()->getSkybox()->update(); +} diff --git a/src/interface/modeler/quickapp/AtmosphereModeler.h b/src/interface/modeler/quickapp/AtmosphereModeler.h new file mode 100644 index 0000000..1a5b32d --- /dev/null +++ b/src/interface/modeler/quickapp/AtmosphereModeler.h @@ -0,0 +1,27 @@ +#ifndef ATMOSPHEREMODELER_H +#define ATMOSPHEREMODELER_H + +#include "modeler_global.h" + +#include + +namespace paysages { +namespace modeler { + +class AtmosphereModeler : public QObject +{ + Q_OBJECT +public: + AtmosphereModeler(MainModelerWindow *main); + +public slots: + void daytimeChanged(double value); + +private: + MainModelerWindow *main; +}; + +} +} + +#endif // ATMOSPHEREMODELER_H diff --git a/src/interface/modeler/quickapp/MainModelerWindow.cpp b/src/interface/modeler/quickapp/MainModelerWindow.cpp index f8cca47..9148218 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.cpp +++ b/src/interface/modeler/quickapp/MainModelerWindow.cpp @@ -3,6 +3,8 @@ #include "OpenGLView.h" #include "Scenery.h" #include "OpenGLRenderer.h" +#include "AtmosphereModeler.h" +#include "WaterModeler.h" MainModelerWindow::MainModelerWindow() { @@ -15,10 +17,21 @@ MainModelerWindow::MainModelerWindow() setTitle(QObject::tr("Paysages 3D")); setResizeMode(QQuickView::SizeRootObjectToView); setSource(QUrl("qrc:///main.qml")); + + atmosphere = new AtmosphereModeler(this); + water = new WaterModeler(this); } MainModelerWindow::~MainModelerWindow() { + delete atmosphere; + delete water; + delete renderer; delete scenery; } + +QObject *MainModelerWindow::findQmlObject(const QString &objectName) +{ + return rootObject()->findChild(objectName); +} diff --git a/src/interface/modeler/quickapp/MainModelerWindow.h b/src/interface/modeler/quickapp/MainModelerWindow.h index f599381..5d7b5f2 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.h +++ b/src/interface/modeler/quickapp/MainModelerWindow.h @@ -15,11 +15,17 @@ public: MainModelerWindow(); virtual ~MainModelerWindow(); + QObject *findQmlObject(const QString& objectName); + + inline Scenery *getScenery() const {return scenery;} inline OpenGLRenderer *getRenderer() const {return renderer;} private: OpenGLRenderer *renderer; Scenery *scenery; + + AtmosphereModeler *atmosphere; + WaterModeler *water; }; } diff --git a/src/interface/modeler/quickapp/WaterModeler.cpp b/src/interface/modeler/quickapp/WaterModeler.cpp new file mode 100644 index 0000000..a0057db --- /dev/null +++ b/src/interface/modeler/quickapp/WaterModeler.cpp @@ -0,0 +1,19 @@ +#include "WaterModeler.h" + +#include "MainModelerWindow.h" + +WaterModeler::WaterModeler(MainModelerWindow *main): + main(main) +{ + QObject *item = main->findQmlObject("water_level"); + if (item) + { + connect(item, SIGNAL(changed(double)), this, SLOT(waterLevelChanged(double))); + } +} + +void WaterModeler::waterLevelChanged(double value) +{ + // TODO + //qDebug() << "water level : " << value; +} diff --git a/src/interface/modeler/quickapp/WaterModeler.h b/src/interface/modeler/quickapp/WaterModeler.h new file mode 100644 index 0000000..fac513e --- /dev/null +++ b/src/interface/modeler/quickapp/WaterModeler.h @@ -0,0 +1,27 @@ +#ifndef WATERMODELER_H +#define WATERMODELER_H + +#include "modeler_global.h" + +#include + +namespace paysages { +namespace modeler { + +class WaterModeler: public QObject +{ + Q_OBJECT +public: + WaterModeler(MainModelerWindow *main); + +public slots: + void waterLevelChanged(double value); + +private: + MainModelerWindow *main; +}; + +} +} + +#endif // WATERMODELER_H diff --git a/src/interface/modeler/quickapp/modeler_global.h b/src/interface/modeler/quickapp/modeler_global.h index f8088b8..d2be172 100644 --- a/src/interface/modeler/quickapp/modeler_global.h +++ b/src/interface/modeler/quickapp/modeler_global.h @@ -9,6 +9,9 @@ namespace paysages { namespace modeler { class MainModelerWindow; class OpenGLView; + + class AtmosphereModeler; + class WaterModeler; } } diff --git a/src/interface/modeler/quickapp/qml/BaseChoice.qml b/src/interface/modeler/quickapp/qml/BaseChoice.qml new file mode 100644 index 0000000..165164d --- /dev/null +++ b/src/interface/modeler/quickapp/qml/BaseChoice.qml @@ -0,0 +1,29 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 + +Item { + default property alias children : inner_layout.children + property int value + width: 100 + height: 32 + + ExclusiveGroup { + id: choice_group + + onCurrentChanged: value = current.value + } + + Row { + id: inner_layout + spacing: 5 + anchors.fill: parent + } + + onChildrenChanged: { + for (var i = 0; i < children.length; i++) + { + children[i].exclusiveGroup = choice_group; + } + } +} diff --git a/src/interface/modeler/quickapp/qml/BaseChoiceItem.qml b/src/interface/modeler/quickapp/qml/BaseChoiceItem.qml new file mode 100644 index 0000000..7e87197 --- /dev/null +++ b/src/interface/modeler/quickapp/qml/BaseChoiceItem.qml @@ -0,0 +1,50 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.1 + +Rectangle { + id: choice_item + property string icon + property bool checked: false + property ExclusiveGroup exclusiveGroup: null + property int value + + color: "#333333" + + signal toggled(bool value) + + width: 20 + height: 20 + + Image { + anchors.fill: parent + source: parent.icon + antialiasing: true + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: checked = true + } + + onExclusiveGroupChanged: { + if (exclusiveGroup) { + exclusiveGroup.bindCheckable(choice_item); + } + } + + onCheckedChanged: choice_item.toggled(checked) + + states: [ + State { + name: "Checked" + when: checked + + PropertyChanges { + target: choice_item + color: "#999999" + } + } + + ] +} diff --git a/src/interface/modeler/quickapp/qml/BasePanel.qml b/src/interface/modeler/quickapp/qml/BasePanel.qml index 82872d6..14ce20d 100644 --- a/src/interface/modeler/quickapp/qml/BasePanel.qml +++ b/src/interface/modeler/quickapp/qml/BasePanel.qml @@ -4,14 +4,21 @@ Rectangle { property ToolbarButton tool id: panel + opacity: 0 width: 200 height: parent.height - 100 - color: "red" + color: "#a0909090" enabled: visible anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter + Behavior on opacity { + PropertyAnimation { + duration: 200 + } + } + states: [ State { name: "Active" @@ -20,6 +27,7 @@ Rectangle { PropertyChanges { target: panel visible: true + opacity: 1 } } diff --git a/src/interface/modeler/quickapp/qml/BaseSlider.qml b/src/interface/modeler/quickapp/qml/BaseSlider.qml new file mode 100644 index 0000000..58cc14e --- /dev/null +++ b/src/interface/modeler/quickapp/qml/BaseSlider.qml @@ -0,0 +1,7 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 + +Slider { + signal changed(real value) + onValueChanged: changed(value) +} diff --git a/src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml b/src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml new file mode 100644 index 0000000..08dab9f --- /dev/null +++ b/src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml @@ -0,0 +1,46 @@ +import QtQuick 2.0 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 + +BasePanel { + width: 70 + + objectName: "atmosphere_daytime" + default property real value: day_night.value == 2 ? 1.0 : slider.value * 0.54 + 0.23; + signal changed(real value) + + onValueChanged: changed(value) + + ColumnLayout + { + anchors.fill: parent + anchors.margins: 10 + spacing: 20 + + BaseChoice { + id: day_night + width: parent.width + + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + + BaseChoiceItem { + icon: "images/icon_atmosphere_day.png" + value: 1 + checked: true + } + BaseChoiceItem { + icon: "images/icon_atmosphere_night.png" + value: 2 + } + } + + BaseSlider { + id: slider + orientation: Qt.Vertical + Layout.maximumWidth: 15 + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + visible: day_night.value == 1 + } + } +} diff --git a/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml b/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml index e84bd6e..444ae97 100644 --- a/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml +++ b/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml @@ -1,10 +1,10 @@ import QtQuick 2.2 -import QtQuick.Controls 1.2 BasePanel { width: 20 - Slider { + BaseSlider { + objectName: "water_level" orientation: Qt.Vertical anchors.fill: parent } diff --git a/src/interface/modeler/quickapp/qml/Toolbar.qml b/src/interface/modeler/quickapp/qml/Toolbar.qml index b8a1424..9abfbc2 100644 --- a/src/interface/modeler/quickapp/qml/Toolbar.qml +++ b/src/interface/modeler/quickapp/qml/Toolbar.qml @@ -19,4 +19,14 @@ Rectangle { duration: 200 } } + + onEnabledChanged: { + if (!enabled) + { + for (var i = 0; i < children.length; i++) + { + children[i].selected = false; + } + } + } } diff --git a/src/interface/modeler/quickapp/qml/app.qrc b/src/interface/modeler/quickapp/qml/app.qrc index a216b39..3c32d54 100644 --- a/src/interface/modeler/quickapp/qml/app.qrc +++ b/src/interface/modeler/quickapp/qml/app.qrc @@ -17,5 +17,13 @@ images/icon_water_level.png BasePanel.qml PanelWaterLevel.qml + images/icon_atmosphere.png + images/icon_atmosphere_daytime.png + BaseSlider.qml + PanelAtmosphereDaytime.qml + images/icon_atmosphere_day.png + images/icon_atmosphere_night.png + BaseChoice.qml + BaseChoiceItem.qml diff --git a/src/interface/modeler/quickapp/qml/images/icon_atmosphere.png b/src/interface/modeler/quickapp/qml/images/icon_atmosphere.png new file mode 100644 index 0000000..5514dfb Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_atmosphere.png differ diff --git a/src/interface/modeler/quickapp/qml/images/icon_atmosphere_day.png b/src/interface/modeler/quickapp/qml/images/icon_atmosphere_day.png new file mode 100644 index 0000000..90721c2 Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_atmosphere_day.png differ diff --git a/src/interface/modeler/quickapp/qml/images/icon_atmosphere_daytime.png b/src/interface/modeler/quickapp/qml/images/icon_atmosphere_daytime.png new file mode 100644 index 0000000..97bed42 Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_atmosphere_daytime.png differ diff --git a/src/interface/modeler/quickapp/qml/images/icon_atmosphere_night.png b/src/interface/modeler/quickapp/qml/images/icon_atmosphere_night.png new file mode 100644 index 0000000..6f0aaee Binary files /dev/null and b/src/interface/modeler/quickapp/qml/images/icon_atmosphere_night.png differ diff --git a/src/interface/modeler/quickapp/qml/main.qml b/src/interface/modeler/quickapp/qml/main.qml index 66dc103..422f7ca 100644 --- a/src/interface/modeler/quickapp/qml/main.qml +++ b/src/interface/modeler/quickapp/qml/main.qml @@ -41,7 +41,8 @@ OpenGLView { } ToolbarButton { id: tool_atmosphere - picture: "images/tab_atmosphere.png" + picture: "images/icon_atmosphere.png" + hovertext: "Atmosphere/weather tools" } ToolbarButton { id: tool_clouds @@ -78,11 +79,26 @@ OpenGLView { } } + Toolbar { + id: atmosphere_toolbar + opacity: 0 + anchors.left: primary_toolbar.right + + ToolbarButton { + id: tool_atmosphere_daytime + picture: "images/icon_atmosphere_daytime.png" + hovertext: qsTr("Change the time of day") + } + } + PanelWaterLevel { id: panel_water_level - visible: false tool: tool_water_level } + PanelAtmosphereDaytime { + id: panel_atmosphere_daytime + tool: tool_atmosphere_daytime + } states: [ State { @@ -102,6 +118,15 @@ OpenGLView { target: water_toolbar opacity: 1 } + }, + State { + name: "Atmosphere Mode" + when: tool_atmosphere.selected + + PropertyChanges { + target: atmosphere_toolbar + opacity: 1 + } } ] diff --git a/src/interface/modeler/quickapp/quickapp.pro b/src/interface/modeler/quickapp/quickapp.pro index ec7c6dc..d1502b4 100644 --- a/src/interface/modeler/quickapp/quickapp.pro +++ b/src/interface/modeler/quickapp/quickapp.pro @@ -6,7 +6,9 @@ include(../../../common.pri) SOURCES += main.cpp \ OpenGLView.cpp \ - MainModelerWindow.cpp + MainModelerWindow.cpp \ + WaterModeler.cpp \ + AtmosphereModeler.cpp RESOURCES += \ qml/app.qrc @@ -22,7 +24,9 @@ include(deployment.pri) HEADERS += \ OpenGLView.h \ modeler_global.h \ - MainModelerWindow.h + MainModelerWindow.h \ + WaterModeler.h \ + AtmosphereModeler.h win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../../system/release/ -lpaysages_system else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../../system/debug/ -lpaysages_system @@ -61,4 +65,8 @@ OTHER_FILES += \ qml/Toolbar.qml \ qml/Tooltip.qml \ qml/BasePanel.qml \ - qml/PanelWaterLevel.qml + qml/PanelWaterLevel.qml \ + qml/PanelAtmosphereDaytime.qml \ + qml/BaseSlider.qml \ + qml/BaseChoice.qml \ + qml/BaseChoiceItem.qml diff --git a/src/render/opengl/OpenGLRenderer.h b/src/render/opengl/OpenGLRenderer.h index 5a3e90c..57ef059 100644 --- a/src/render/opengl/OpenGLRenderer.h +++ b/src/render/opengl/OpenGLRenderer.h @@ -17,6 +17,10 @@ public: OpenGLRenderer(Scenery* scenery=0); virtual ~OpenGLRenderer(); + inline OpenGLSkybox *getSkybox() const {return skybox;} + inline OpenGLWater *getWater() const {return water;} + inline OpenGLTerrain *getTerrain() const {return terrain;} + void initialize(); void prepareOpenGLState(); void resize(int width, int height); diff --git a/src/tests/AtmosphereDefinition_Test.cpp b/src/tests/AtmosphereDefinition_Test.cpp new file mode 100644 index 0000000..5e151a0 --- /dev/null +++ b/src/tests/AtmosphereDefinition_Test.cpp @@ -0,0 +1,36 @@ +#include "BaseTestCase.h" + +#include "AtmosphereDefinition.h" + +TEST(AtmosphereDefinition, setDaytime) +{ + AtmosphereDefinition atmo(NULL); + + atmo.setDaytime(0.0); + EXPECT_EQ(atmo.hour, 0); + EXPECT_EQ(atmo.minute, 0); + + atmo.setDaytime(0.1); + EXPECT_EQ(atmo.hour, 2); + EXPECT_EQ(atmo.minute, 24); + + atmo.setDaytime(0.25); + EXPECT_EQ(atmo.hour, 6); + EXPECT_EQ(atmo.minute, 0); + + atmo.setDaytime(0.5); + EXPECT_EQ(atmo.hour, 12); + EXPECT_EQ(atmo.minute, 0); + + atmo.setDaytime(1.0); + EXPECT_EQ(atmo.hour, 0); + EXPECT_EQ(atmo.minute, 0); + + atmo.setDaytime(-0.5); + EXPECT_EQ(atmo.hour, 12); + EXPECT_EQ(atmo.minute, 0); + + atmo.setDaytime(1.5); + EXPECT_EQ(atmo.hour, 12); + EXPECT_EQ(atmo.minute, 0); +} diff --git a/src/tests/tests.pro b/src/tests/tests.pro index 863ddff..4668460 100644 --- a/src/tests/tests.pro +++ b/src/tests/tests.pro @@ -20,7 +20,8 @@ SOURCES += main.cpp \ FractalNoise_Test.cpp \ Canvas_Test.cpp \ CanvasPortion_Test.cpp \ - CanvasPreview_Test.cpp + CanvasPreview_Test.cpp \ + AtmosphereDefinition_Test.cpp HEADERS += \ BaseTestCase.h