From 9f438a3f8419f1b593f2b74279361d5fa1f5a77f Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Tue, 19 Aug 2014 15:49:08 +0200 Subject: [PATCH 01/13] Prototype of experimental UI using Qt Quick --- src/interface/quick/OpenGLView.cpp | 44 ++++++++++++++++++++++++++ src/interface/quick/OpenGLView.h | 28 +++++++++++++++++ src/interface/quick/deployment.pri | 27 ++++++++++++++++ src/interface/quick/main.cpp | 19 ++++++++++++ src/interface/quick/main.qml | 11 +++++++ src/interface/quick/qml.qrc | 5 +++ src/interface/quick/quick.pro | 50 ++++++++++++++++++++++++++++++ src/interface/quick/quick_global.h | 16 ++++++++++ src/paysages.pro | 1 + 9 files changed, 201 insertions(+) create mode 100644 src/interface/quick/OpenGLView.cpp create mode 100644 src/interface/quick/OpenGLView.h create mode 100644 src/interface/quick/deployment.pri create mode 100644 src/interface/quick/main.cpp create mode 100644 src/interface/quick/main.qml create mode 100644 src/interface/quick/qml.qrc create mode 100644 src/interface/quick/quick.pro create mode 100644 src/interface/quick/quick_global.h diff --git a/src/interface/quick/OpenGLView.cpp b/src/interface/quick/OpenGLView.cpp new file mode 100644 index 0000000..6f35ec2 --- /dev/null +++ b/src/interface/quick/OpenGLView.cpp @@ -0,0 +1,44 @@ +#include "OpenGLView.h" + +#include + +// TEMP +#include "OpenGLRenderer.h" +#include "Scenery.h" +static OpenGLRenderer renderer; +static Scenery scenery; + +OpenGLView::OpenGLView(QQuickItem *parent) : + QQuickItem(parent) +{ + initialized = false; + + connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); + + scenery.autoPreset(); + renderer.setScenery(&scenery); +} + +void OpenGLView::handleWindowChanged(QQuickWindow *win) +{ + if (win) + { + connect(window(), SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); + + win->setClearBeforeRendering(false); + + initialized = false; + } +} + +void OpenGLView::paint() +{ + if (not initialized) + { + renderer.initialize(); + initialized = true; + } + + renderer.resize(window()->width(), window()->height()); + renderer.paint(); +} diff --git a/src/interface/quick/OpenGLView.h b/src/interface/quick/OpenGLView.h new file mode 100644 index 0000000..f741a44 --- /dev/null +++ b/src/interface/quick/OpenGLView.h @@ -0,0 +1,28 @@ +#ifndef OPENGLVIEW_H +#define OPENGLVIEW_H + +#include "quick_global.h" + +#include + +namespace paysages { +namespace quick { + +class OpenGLView : public QQuickItem +{ + Q_OBJECT +public: + explicit OpenGLView(QQuickItem *parent = 0); + +public slots: + void handleWindowChanged(QQuickWindow *win); + void paint(); + +private: + bool initialized; +}; + +} +} + +#endif // OPENGLVIEW_H diff --git a/src/interface/quick/deployment.pri b/src/interface/quick/deployment.pri new file mode 100644 index 0000000..5441b63 --- /dev/null +++ b/src/interface/quick/deployment.pri @@ -0,0 +1,27 @@ +android-no-sdk { + target.path = /data/user/qt + export(target.path) + INSTALLS += target +} else:android { + x86 { + target.path = /libs/x86 + } else: armeabi-v7a { + target.path = /libs/armeabi-v7a + } else { + target.path = /libs/armeabi + } + export(target.path) + INSTALLS += target +} else:unix { + isEmpty(target.path) { + qnx { + target.path = /tmp/$${TARGET}/bin + } else { + target.path = /opt/$${TARGET}/bin + } + export(target.path) + } + INSTALLS += target +} + +export(INSTALLS) diff --git a/src/interface/quick/main.cpp b/src/interface/quick/main.cpp new file mode 100644 index 0000000..6a8db3f --- /dev/null +++ b/src/interface/quick/main.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "OpenGLView.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + qmlRegisterType("Paysages", 1, 0, "OpenGLView"); + + QQuickView view; + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:///main.qml")); + view.show(); + + return app.exec(); +} diff --git a/src/interface/quick/main.qml b/src/interface/quick/main.qml new file mode 100644 index 0000000..55b587b --- /dev/null +++ b/src/interface/quick/main.qml @@ -0,0 +1,11 @@ +import QtQuick 2.2 +import Paysages 1.0 + +Item { + + width: 640 + height: 480 + + OpenGLView { + } +} diff --git a/src/interface/quick/qml.qrc b/src/interface/quick/qml.qrc new file mode 100644 index 0000000..5f6483a --- /dev/null +++ b/src/interface/quick/qml.qrc @@ -0,0 +1,5 @@ + + + main.qml + + diff --git a/src/interface/quick/quick.pro b/src/interface/quick/quick.pro new file mode 100644 index 0000000..6b90cf3 --- /dev/null +++ b/src/interface/quick/quick.pro @@ -0,0 +1,50 @@ +TEMPLATE = app + +QT += qml quick widgets + +include(../../common.pri) + +SOURCES += main.cpp \ + OpenGLView.cpp + +RESOURCES += qml.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Default rules for deployment. +include(deployment.pri) + +HEADERS += \ + quick_global.h \ + OpenGLView.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 +else:unix: LIBS += -L$$OUT_PWD/../../system/ -lpaysages_system +INCLUDEPATH += $$PWD/../../system +DEPENDPATH += $$PWD/../../system + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../basics/release/ -lpaysages_basics +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../basics/debug/ -lpaysages_basics +else:unix: LIBS += -L$$OUT_PWD/../../basics/ -lpaysages_basics +INCLUDEPATH += $$PWD/../../basics +DEPENDPATH += $$PWD/../../basics + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../definition/release/ -lpaysages_definition +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../definition/debug/ -lpaysages_definition +else:unix: LIBS += -L$$OUT_PWD/../../definition/ -lpaysages_definition +INCLUDEPATH += $$PWD/../../definition +DEPENDPATH += $$PWD/../../definition + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../render/software/release/ -lpaysages_render_software +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../render/software/debug/ -lpaysages_render_software +else:unix: LIBS += -L$$OUT_PWD/../../render/software/ -lpaysages_render_software +INCLUDEPATH += $$PWD/../../render/software +DEPENDPATH += $$PWD/../../render/software + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../render/opengl/release/ -lpaysages_render_opengl +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../render/opengl/debug/ -lpaysages_render_opengl +else:unix: LIBS += -L$$OUT_PWD/../../render/opengl/ -lpaysages_render_opengl +INCLUDEPATH += $$PWD/../../render/opengl +DEPENDPATH += $$PWD/../../render/opengl diff --git a/src/interface/quick/quick_global.h b/src/interface/quick/quick_global.h new file mode 100644 index 0000000..b92e58b --- /dev/null +++ b/src/interface/quick/quick_global.h @@ -0,0 +1,16 @@ +#ifndef QUICK_GLOBAL_H +#define QUICK_GLOBAL_H + +#include "definition_global.h" +#include "software_global.h" +#include "opengl_global.h" + +namespace paysages { +namespace quick { + class ItemOpenGLView; +} +} + +using namespace paysages::quick; + +#endif // QUICK_GLOBAL_H diff --git a/src/paysages.pro b/src/paysages.pro index bd05472..347045e 100644 --- a/src/paysages.pro +++ b/src/paysages.pro @@ -10,5 +10,6 @@ SUBDIRS = \ render/opengl \ interface/commandline \ interface/desktop \ + interface/quick \ tests/googletest \ tests From f7d84afb79896b5cf058786b3ce5acab142cc90b Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Tue, 19 Aug 2014 17:01:42 +0200 Subject: [PATCH 02/13] Added primary toolbar to qt quick prototype --- src/interface/quick/OpenGLView.cpp | 4 +- src/interface/quick/images.qrc | 10 +++ src/interface/quick/images/images.qrc | 10 +++ src/interface/quick/images/tab_atmosphere.png | Bin 0 -> 1778 bytes src/interface/quick/images/tab_clouds.png | Bin 0 -> 2403 bytes src/interface/quick/images/tab_render.png | Bin 0 -> 2289 bytes src/interface/quick/images/tab_terrain.png | Bin 0 -> 1132 bytes src/interface/quick/images/tab_textures.png | Bin 0 -> 2327 bytes src/interface/quick/images/tab_water.png | Bin 0 -> 2332 bytes src/interface/quick/main.qml | 76 +++++++++++++++++- src/interface/quick/quick.pro | 3 +- 11 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 src/interface/quick/images.qrc create mode 100644 src/interface/quick/images/images.qrc create mode 100644 src/interface/quick/images/tab_atmosphere.png create mode 100644 src/interface/quick/images/tab_clouds.png create mode 100644 src/interface/quick/images/tab_render.png create mode 100644 src/interface/quick/images/tab_terrain.png create mode 100644 src/interface/quick/images/tab_textures.png create mode 100644 src/interface/quick/images/tab_water.png diff --git a/src/interface/quick/OpenGLView.cpp b/src/interface/quick/OpenGLView.cpp index 6f35ec2..cf962fd 100644 --- a/src/interface/quick/OpenGLView.cpp +++ b/src/interface/quick/OpenGLView.cpp @@ -39,6 +39,8 @@ void OpenGLView::paint() initialized = true; } - renderer.resize(window()->width(), window()->height()); + renderer.resize(width(), height()); renderer.paint(); + + window()->resetOpenGLState(); } diff --git a/src/interface/quick/images.qrc b/src/interface/quick/images.qrc new file mode 100644 index 0000000..d8083b0 --- /dev/null +++ b/src/interface/quick/images.qrc @@ -0,0 +1,10 @@ + + + images/tab_atmosphere.png + images/tab_terrain.png + images/tab_textures.png + images/tab_water.png + images/tab_clouds.png + images/tab_render.png + + diff --git a/src/interface/quick/images/images.qrc b/src/interface/quick/images/images.qrc new file mode 100644 index 0000000..d3a2921 --- /dev/null +++ b/src/interface/quick/images/images.qrc @@ -0,0 +1,10 @@ + + + tab_water.png + tab_atmosphere.png + tab_clouds.png + tab_render.png + tab_terrain.png + tab_textures.png + + diff --git a/src/interface/quick/images/tab_atmosphere.png b/src/interface/quick/images/tab_atmosphere.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e31899e449dcdaf047e3ce26e88c19f18ef5fb GIT binary patch literal 1778 zcmV(K zjz=rYKG+KT;Q#+6+t&?+*3(^8d;mxvYDN+-6+{#snF$gUwXdq05>OEc0TBSmOiLq( z&qcb3ko??|Adm!03Iv&sKm08s$uw0}RYFd?;3J7ZAW+dW761{=OcD8G6aoSPP9OQ* zECN6vCV&8{_Is&kepQJeDUdS+NmT_25i$XY$eH28<@|owNm2mIQmFcwT>u4;IUyoy z3IrmB00hRQC_K}|R3tN06krM=ARG{7eq<5>U@9h}I01bwRRaLU$$;WR3rZ3wS|mRZ z04btmd=iXL7$2xj)kO6-3W)>&mgH}kQ%DF%s+9a7hXPQ9R1hixAo!^xKME#kVpT<{ zLIFw1B%lID$OpellAmo*T**u=#3@h#fDDL~07NoRbR?$~F{!JF5Fh1!c1?;DNdh2J zKmjuogcwK_0E7s^1dtNHIe%&l5d~mcs;Y_z&rTpR6OtemLM9j>2x{@jl!TDTla&O8 zq-X&N8U(5VB*~?E~CNe+@^K8MSs!%186bXQ2$pBPJ2nAXkK!A}6 zks=ZiX4e-$AjwQ-f+SfaBT^X5Boj=4!pclZ2O*4PN~R)6q5ves&XcF2AdxPjc6tc-r6oBxaRjBm>ey zGNWhl8O?Ky(MNCH`!V`)^wE4jdLQ1Wx83_TJ(e-jA9GIip2H)C%wEDhtCnetX0;TJ zQi_O*s_Nn_nGv+q~F-KJY%o)(X+=Ffd=&bvmW#?P z_4UR*mibb9TaWp4KiaX+$A0YlZY1xIdr|%R_3N^%fLN^p%sERb=gnBO5Yz&KlD;l= zvC@0*qpLz!gog=2=%Q_jms-YEk7pbQ?ayD|R8@+SbnlnNlf(EIoBCv=sv+`LifZn@=i-?)+`@XKLs?Isr^%CLt z`&~pzlpOy4{=P1YnMFivO-1_{WRi>s50W&Jz4zF*r7rt%tjlt}Ua!yB(T9S)b-7*7 zDf{dDd#yFYuh;9gy+`ER+Y6w*H6Z5nU%$UEOI@nfY9trI$S{)2vglGTmy2E3r>Eyq z6yYz=Pnj83RK(227?;Z$5nsN%M8vYJ+xAcu5(N9`BS+ zm-Uhnj4aC5+MKiZZf3`EkbK9sdAnXCV_jFPR%;cJ+wFGj`?{|8`~C5F0QmmD_kG_NTS)%r-~WAmeO=e} z{rz4_T^GBo21sT~qE_8Dx8A#|e*5;#%sisj^7g~qvMj0^5!<$%Q+$jO5y!EYViDP5 z|MABkZ%>zqSk|R3Hs^SGc{u?^#QE;}@R6S4DT^xns4zx?v;?d?rOGLwvb-}@Y-wl@3G?)Uru0YE_p UE=0-ifB*mh07*qoM6N<$g3o_Pe*gdg literal 0 HcmV?d00001 diff --git a/src/interface/quick/images/tab_clouds.png b/src/interface/quick/images/tab_clouds.png new file mode 100644 index 0000000000000000000000000000000000000000..0fe90b2d7d642ee816e7c7816cee38455a80085d GIT binary patch literal 2403 zcmV-p37qzcP)-fMNhbh2g(AFvki{pfo?xJN{WnVA(JB4&;v z?j}jA&Et`otl%4Y{Z{(Qtqu`AyU5zDR?C{xi{^!Eowx6u{ntmux859!ceAyBbeg3} z^wam2ofa2WsH?^TtSX{Ps>FO5z+_B<+t-t<2)lg*vGd$L_;@~BR(am^2l4HLk%an# z$K_XE+qrRl{dYe*`{rxgZ{M5DO7XrRXi*0R*nqzGgS!ARvtb4ifVh<;u_0JM4AWO$ z>Av*oPF943{I3qrr_0hcq1Wqt=Ei7eqnmauF=u%lTb!KbPfqF|{?Duv=`44uU}j59 zP*PPMG9**=)W4;B=YGYF*ZKQ@gNt zb>mOIy@;B=d<mv;j6>#yy+bkNGnqO9ciUmIC#A@1aS`Sff7=&%>;zkd5!R>CqVLjnN`0{!8eS2`{K-huc}2C4=E3BJmUsw{&iHPPp9?fv4T(g(4Z4~PtV)gb!gduO-y zC|{REw8;H@S>C)hs6F?)?MPfJrf8#me3C6ztFj8tsf{BmVYt!Di!#e9*Qg2)2Fc#I z{rt85(~J5tK)-amy|dMQbh4})bA6W|KXH|VVFSXu4~qxK;b50PHPUrn?~Xg`teQ*% zN2b@Zwa0W31{7sVh0xP^XhQhvXZjx=EklrheZRDT05o4Ud*iy-i?_&^m5Y+r-A}4J zx007`bX}m~u&yei<41qKJ&)vJPdC1wJ% zvBof z;=PCxRDbcY>$Pcroc{Wv+UU{gd1)yy>3Ec!o#(x7^7zR)k(PCs&GJ>=eBq_^_I~UB zQ4<6#2nv8yU;#CNwJf5MA?K7xh-~c|@9p2ebHO%w?_t^Rq8FpzwO6*HG_~_ZUOCOO zB8j=(O;(xxtABo0HDE)kB&=oKAd5nN`Tz*BJt(&N)!t5bQG{$={l`Obu#ihx@S6oD6=o2KNL2wa<5N4){+?wL z1&lSul7gB4KN^5)5Hl~$8^5)^nR2gfYDzcyNh>y&t}x+}NC3pJMnwpQnMt49wtIun zOXELybN|Dm>PP=J`<<6ZgD(Bk-9=tE8>wCAjR;-eZU5dE`C_{80UY7Q=j_#!VP5^(cZpy~iL_%v(o!d3y{d2Tx2|77FKVWX^_M@_UFUk^3U;@m zqltgx<<8_{)i^NG;iK8&3H3eEov4W_M-cT z)5WSdy~wX_rptAC=XToecHVzfjfVF6mJt`)7L)Te1W{xxt8-1-@~^zm8+0RM4Tu2V z*@(=YxBeJRMA}d7s9oh*vwJ12t8zSQO=cw#w)*kzm2NuH`F8&=sePVB?S zi`BYvLFy(nPA!8peDT)cm4hU;;lW8ThCe-qB`AT~F@O1Xba=c@5Qx!7Pis|6VJqp}I}Wtn!8?LoZCYNK|(C?~VBZd_0n@uYwfdGEbD{B;%C zVzfQj9{9%>G#*(?Kx9lOmIp^-G%+L*dGA9NJQ4F+^4tZ`b7MX(>l@dGP17{adsjOr zBBI2sT0%HAtf52@5V2*xw3vt@FfLn;lo`F0{|_1j VuecFrhHwA?002ovPDHLkV1mx3p}7D6 literal 0 HcmV?d00001 diff --git a/src/interface/quick/images/tab_render.png b/src/interface/quick/images/tab_render.png new file mode 100644 index 0000000000000000000000000000000000000000..071526555067499f22b2345e949106d17e9cdf93 GIT binary patch literal 2289 zcmVt62b+q- z{k%%0QtSJ{;hvs7KaM3*na+-m^;I?j%j4GX^tK_IB?>~vD@!jyXrZB z+g7dR(TyAa4SdGJL?Y1!-*v+N!C{e1n6p}&>xf69l^On+?gBxc{5$?<**!XlZGoudnZ{6h!WO z;5$37UV6g?6^iFKl9PY>PQyIxwodes$x`-6ubL6j|rR5Hf*fB2)jKl!Oe z>-&caR8?n0#j4=D65D~Y4X&qZlBMLhHLrboW^)zx1HFfRPeY5>xi#`>=ALu%^OHf?-pgs7P$ z5>0ZfuMa5_L?cOr(kNFf%C=7+L*hb#CJ+$=rI{2hpL{-#A9}&E2gFF=vN|uik6lrg7 zXK1(|&mCv##0j)ECdg%CphX!OEm5|7LfvG{RpfHDM4|zfU0}F4N~v5Slc~e;Tzs#B z7BR71r2%LFPi}rb5r#53ZN|B@O_@YnTRX9M6`|CzY)Q$o+0*rBq&>p4<}5V{NsKae zxi|?^($r8xbvA)z4deMX{eweDbgDDeG&R*TGB$)SJ)$v_lI0L8K{{6rfB}#QTvZB9 z<%bICm61w-22zCxOn{SI6n0K~xArM37PtNS$;%`7XfkUwn~Smwc8m3{eIMO`z)$oYDwOubj`( zBmKPk#$jAss?s?;sZl8Q5fvV@J;C($2J(HwSdK<4rjzjCMDI~r8*4GpNvBd&DixB+ z1VP}Vq$HH#y8x$7^@&c;6G3=JDTIb=J1qY6Ji5F0acrnW=j_R(Q&nVhSv)<)$>AcU zqRVUh4sm)g&t(f{^Xm591S*Li`VN% zZpo%naWNt$LxV$%jg4d5E=s90hbn_o*(O^PKLhaS#!bw;VpW(Q9UK4quOyXELsK=c z?>tB{m!#vo8Puhd3>GblQG;kIK|G=n6OyD6l5VJF=icMAPnk}{DB#*INJ|u^i1B^wU7DpW-^)|B?x^$Q79D9bwMl^Ln(<;5-BB0sdrNVpoBWA6A42B zhEjOGPpUeBD}7?7Mrg$GEf=S3;X5|I2fAnAhu|ugST4u@-d<8w^$1zUcO8VGQE@6v zo6>@=K@dnhDe*%ov}mS&#s*>jE$Yz zU$*iB5n@|q^iYy8BAgs7p`$1|f}*2Qwk56;QgOg?6^<8TRczvkI2tI|cSJlU{7WvL zA)V5oa2y-m&~O|}j2Dic=zinn@4dd`b^p$L9z635XUts0)@{E&VCK@xmM**M!lYT1 zJFtIu=f(3Etz@`l^quS#1KAEt;nQbJ!XU)=6?P@0>_{rMhw#UlJfVeDJRycpowAdu z)VlG}lkb!YSKPsqKYjSUTe7E~*}{$2Eu*8ovt#{(8xCl(33|~h zt7Cm57|E;{x4{Yoo@Wu4Ho0i1&Y#vUrnWV5=hxS4ees1~E&4!B>9bq5aP74>uw&=T zqls*EM{DcEB{iAaWYdJK2+KvH(jlz}RGX414H-3eR;P$+K2LAn^wOrE|KutlFw*r% z&-&j00QT>Hixs!8;PH)*^-gMT{-fu+8C_^IXPrBPmik&+8>(raIDyuNT5;s%UMeqGcsadq?|okp5brls3l=PjUVHuW&OLAT+|=CMc&Sv%jGJlMd*twz z=EnMGw{6?nyM6mB!Q8oX>FVnG{|_Md-v6!txPI%cD?ggjKAiGbcg$EC%XJoS00000 LNkvXXu0mjfuaZ(9 literal 0 HcmV?d00001 diff --git a/src/interface/quick/images/tab_terrain.png b/src/interface/quick/images/tab_terrain.png new file mode 100644 index 0000000000000000000000000000000000000000..343522da049f97e798dbcb306bc036fb2c4f0ed0 GIT binary patch literal 1132 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 Date: Tue, 19 Aug 2014 17:37:24 +0200 Subject: [PATCH 03/13] WIP on quick ui prototype --- src/interface/quick/OpenGLView.cpp | 1 + src/interface/quick/ToolbarButton.qml | 39 +++++++++++++++++++++++++++ src/interface/quick/main.qml | 32 +++++++++------------- src/interface/quick/qml.qrc | 1 + 4 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 src/interface/quick/ToolbarButton.qml diff --git a/src/interface/quick/OpenGLView.cpp b/src/interface/quick/OpenGLView.cpp index cf962fd..24dbac4 100644 --- a/src/interface/quick/OpenGLView.cpp +++ b/src/interface/quick/OpenGLView.cpp @@ -16,6 +16,7 @@ OpenGLView::OpenGLView(QQuickItem *parent) : connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); scenery.autoPreset(); + renderer.setScenery(&scenery); } diff --git a/src/interface/quick/ToolbarButton.qml b/src/interface/quick/ToolbarButton.qml new file mode 100644 index 0000000..512c87e --- /dev/null +++ b/src/interface/quick/ToolbarButton.qml @@ -0,0 +1,39 @@ +import QtQuick 2.0 + +Item { + property string code + property bool selected: false + property bool hovered: false + + width: image.width + 10 + height: image.height + 10 + + Rectangle { + id: glow + anchors.fill: parent + color: "white" + radius: 8 + + opacity: parent.selected ? 1.0 : (parent.hovered ? 0.5 : 0.0) + Behavior on opacity { + PropertyAnimation { + duration: 200 + } + } + } + + Image { + id: image + source: "qrc:///toolbar/primary/tab_" + parent.code + ".png" + anchors.centerIn: parent + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + + onEntered: parent.hovered = true + onExited: parent.hovered = false + onClicked: parent.selected = true + } +} diff --git a/src/interface/quick/main.qml b/src/interface/quick/main.qml index 95f641d..0aff8e8 100644 --- a/src/interface/quick/main.qml +++ b/src/interface/quick/main.qml @@ -32,35 +32,29 @@ OpenGLView { anchors.verticalCenter: parent.verticalCenter spacing: (parent.height - 6 * tool_terrain.height) / 7 - Image { + ToolbarButton { id: tool_terrain - opacity: 0.5 - source: "qrc:///toolbar/primary/tab_terrain.png" + code: "terrain" } - Image { + ToolbarButton { id: tool_textures - opacity: 0.5 - source: "qrc:///toolbar/primary/tab_textures.png" + code: "textures" } - Image { + ToolbarButton { id: tool_water - opacity: 0.5 - source: "qrc:///toolbar/primary/tab_water.png" + code: "water" } - Image { + ToolbarButton { id: tool_atmosphere - opacity: 0.5 - source: "qrc:///toolbar/primary/tab_atmosphere.png" + code: "atmosphere" } - Image { + ToolbarButton { id: tool_clouds - opacity: 0.5 - source: "qrc:///toolbar/primary/tab_clouds.png" + code: "clouds" } - Image { + ToolbarButton { id: tool_render - opacity: 0.5 - source: "qrc:///toolbar/primary/tab_render.png" + code: "render" } } } @@ -71,7 +65,7 @@ OpenGLView { anchors.left: primary_toolbar.right width: primary_toolbar.width height: primary_toolbar.height - color: "green" + color: "#8800FF00" SequentialAnimation on width { loops: Animation.Infinite diff --git a/src/interface/quick/qml.qrc b/src/interface/quick/qml.qrc index 5f6483a..7292848 100644 --- a/src/interface/quick/qml.qrc +++ b/src/interface/quick/qml.qrc @@ -1,5 +1,6 @@ main.qml + ToolbarButton.qml From 0e2e0a05eb0ea0fdb472706b3f2a85ced1d2af85 Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Wed, 27 Aug 2014 15:18:08 +0200 Subject: [PATCH 04/13] Refactored QtQuick UI to work in QtCreator --- src/interface/modeler/extension/extension.pro | 35 +++++++++++ .../modeler/extension/extension_plugin.cpp | 12 ++++ .../modeler/extension/extension_plugin.h | 16 +++++ src/interface/modeler/extension/paysages.cpp | 16 +++++ src/interface/modeler/extension/paysages.h | 17 ++++++ src/interface/modeler/extension/qmldir | 3 + src/interface/modeler/modeler.pro | 5 ++ .../quickapp}/OpenGLView.cpp | 0 .../{quick => modeler/quickapp}/OpenGLView.h | 4 +- .../quickapp}/deployment.pri | 0 .../{quick => modeler/quickapp}/images.qrc | 0 .../quickapp}/images/images.qrc | 0 .../{quick => modeler/quickapp}/main.cpp | 1 + .../quickapp/modeler_global.h} | 10 ++-- src/interface/modeler/quickapp/qml.qrc | 7 +++ .../modeler/quickapp/qml/OpenGLView.qml | 6 ++ .../quickapp/qml}/ToolbarButton.qml | 4 +- src/interface/modeler/quickapp/qml/app.qrc | 12 ++++ .../quickapp/qml}/images/tab_atmosphere.png | Bin .../quickapp/qml}/images/tab_clouds.png | Bin .../quickapp/qml}/images/tab_render.png | Bin .../quickapp/qml}/images/tab_terrain.png | Bin .../quickapp/qml}/images/tab_textures.png | Bin .../quickapp/qml}/images/tab_water.png | Bin .../{quick => modeler/quickapp/qml}/main.qml | 12 ++-- src/interface/modeler/quickapp/quickapp.pro | 56 ++++++++++++++++++ src/interface/quick/qml.qrc | 6 -- src/interface/quick/quick.pro | 51 ---------------- src/paysages.pro | 2 +- 29 files changed, 202 insertions(+), 73 deletions(-) create mode 100644 src/interface/modeler/extension/extension.pro create mode 100644 src/interface/modeler/extension/extension_plugin.cpp create mode 100644 src/interface/modeler/extension/extension_plugin.h create mode 100644 src/interface/modeler/extension/paysages.cpp create mode 100644 src/interface/modeler/extension/paysages.h create mode 100644 src/interface/modeler/extension/qmldir create mode 100644 src/interface/modeler/modeler.pro rename src/interface/{quick => modeler/quickapp}/OpenGLView.cpp (100%) rename src/interface/{quick => modeler/quickapp}/OpenGLView.h (87%) rename src/interface/{quick => modeler/quickapp}/deployment.pri (100%) rename src/interface/{quick => modeler/quickapp}/images.qrc (100%) rename src/interface/{quick => modeler/quickapp}/images/images.qrc (100%) rename src/interface/{quick => modeler/quickapp}/main.cpp (89%) rename src/interface/{quick/quick_global.h => modeler/quickapp/modeler_global.h} (51%) create mode 100644 src/interface/modeler/quickapp/qml.qrc create mode 100644 src/interface/modeler/quickapp/qml/OpenGLView.qml rename src/interface/{quick => modeler/quickapp/qml}/ToolbarButton.qml (88%) create mode 100644 src/interface/modeler/quickapp/qml/app.qrc rename src/interface/{quick => modeler/quickapp/qml}/images/tab_atmosphere.png (100%) rename src/interface/{quick => modeler/quickapp/qml}/images/tab_clouds.png (100%) rename src/interface/{quick => modeler/quickapp/qml}/images/tab_render.png (100%) rename src/interface/{quick => modeler/quickapp/qml}/images/tab_terrain.png (100%) rename src/interface/{quick => modeler/quickapp/qml}/images/tab_textures.png (100%) rename src/interface/{quick => modeler/quickapp/qml}/images/tab_water.png (100%) rename src/interface/{quick => modeler/quickapp/qml}/main.qml (85%) create mode 100644 src/interface/modeler/quickapp/quickapp.pro delete mode 100644 src/interface/quick/qml.qrc delete mode 100644 src/interface/quick/quick.pro diff --git a/src/interface/modeler/extension/extension.pro b/src/interface/modeler/extension/extension.pro new file mode 100644 index 0000000..03da2cd --- /dev/null +++ b/src/interface/modeler/extension/extension.pro @@ -0,0 +1,35 @@ +TEMPLATE = lib +TARGET = extension +QT += qml quick +CONFIG += qt plugin + +TARGET = $$qtLibraryTarget($$TARGET) +uri = Paysages + +# Input +SOURCES += \ + extension_plugin.cpp \ + paysages.cpp + +HEADERS += \ + extension_plugin.h \ + paysages.h + +OTHER_FILES = qmldir + +!equals(_PRO_FILE_PWD_, $$OUT_PWD) { + copy_qmldir.target = $$OUT_PWD/qmldir + copy_qmldir.depends = $$_PRO_FILE_PWD_/qmldir + copy_qmldir.commands = $(COPY_FILE) \"$$replace(copy_qmldir.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_qmldir.target, /, $$QMAKE_DIR_SEP)\" + QMAKE_EXTRA_TARGETS += copy_qmldir + PRE_TARGETDEPS += $$copy_qmldir.target +} + +qmldir.files = qmldir +unix { + installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /) + qmldir.path = $$installPath + target.path = $$installPath + INSTALLS += target qmldir +} + diff --git a/src/interface/modeler/extension/extension_plugin.cpp b/src/interface/modeler/extension/extension_plugin.cpp new file mode 100644 index 0000000..ded9382 --- /dev/null +++ b/src/interface/modeler/extension/extension_plugin.cpp @@ -0,0 +1,12 @@ +#include "extension_plugin.h" +#include "paysages.h" + +#include + +void ExtensionPlugin::registerTypes(const char *uri) +{ + // @uri Paysages + qmlRegisterType(uri, 1, 0, "Paysages"); +} + + diff --git a/src/interface/modeler/extension/extension_plugin.h b/src/interface/modeler/extension/extension_plugin.h new file mode 100644 index 0000000..9471ff3 --- /dev/null +++ b/src/interface/modeler/extension/extension_plugin.h @@ -0,0 +1,16 @@ +#ifndef EXTENSION_PLUGIN_H +#define EXTENSION_PLUGIN_H + +#include + +class ExtensionPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + void registerTypes(const char *uri); +}; + +#endif // EXTENSION_PLUGIN_H + diff --git a/src/interface/modeler/extension/paysages.cpp b/src/interface/modeler/extension/paysages.cpp new file mode 100644 index 0000000..ad88921 --- /dev/null +++ b/src/interface/modeler/extension/paysages.cpp @@ -0,0 +1,16 @@ +#include "paysages.h" + +Paysages::Paysages(QQuickItem *parent): + QQuickItem(parent) +{ + // By default, QQuickItem does not draw anything. If you subclass + // QQuickItem to create a visual item, you will need to uncomment the + // following line and re-implement updatePaintNode() + + // setFlag(ItemHasContents, true); +} + +Paysages::~Paysages() +{ +} + diff --git a/src/interface/modeler/extension/paysages.h b/src/interface/modeler/extension/paysages.h new file mode 100644 index 0000000..0f55ef5 --- /dev/null +++ b/src/interface/modeler/extension/paysages.h @@ -0,0 +1,17 @@ +#ifndef PAYSAGES_H +#define PAYSAGES_H + +#include + +class Paysages : public QQuickItem +{ + Q_OBJECT + Q_DISABLE_COPY(Paysages) + +public: + Paysages(QQuickItem *parent = 0); + ~Paysages(); +}; + +#endif // PAYSAGES_H + diff --git a/src/interface/modeler/extension/qmldir b/src/interface/modeler/extension/qmldir new file mode 100644 index 0000000..f7a7af9 --- /dev/null +++ b/src/interface/modeler/extension/qmldir @@ -0,0 +1,3 @@ +module Paysages +plugin extension + diff --git a/src/interface/modeler/modeler.pro b/src/interface/modeler/modeler.pro new file mode 100644 index 0000000..711f598 --- /dev/null +++ b/src/interface/modeler/modeler.pro @@ -0,0 +1,5 @@ +TEMPLATE = subdirs + +SUBDIRS = \ + quickapp \ + extension diff --git a/src/interface/quick/OpenGLView.cpp b/src/interface/modeler/quickapp/OpenGLView.cpp similarity index 100% rename from src/interface/quick/OpenGLView.cpp rename to src/interface/modeler/quickapp/OpenGLView.cpp diff --git a/src/interface/quick/OpenGLView.h b/src/interface/modeler/quickapp/OpenGLView.h similarity index 87% rename from src/interface/quick/OpenGLView.h rename to src/interface/modeler/quickapp/OpenGLView.h index f741a44..cdd41ae 100644 --- a/src/interface/quick/OpenGLView.h +++ b/src/interface/modeler/quickapp/OpenGLView.h @@ -1,12 +1,12 @@ #ifndef OPENGLVIEW_H #define OPENGLVIEW_H -#include "quick_global.h" +#include "modeler_global.h" #include namespace paysages { -namespace quick { +namespace modeler { class OpenGLView : public QQuickItem { diff --git a/src/interface/quick/deployment.pri b/src/interface/modeler/quickapp/deployment.pri similarity index 100% rename from src/interface/quick/deployment.pri rename to src/interface/modeler/quickapp/deployment.pri diff --git a/src/interface/quick/images.qrc b/src/interface/modeler/quickapp/images.qrc similarity index 100% rename from src/interface/quick/images.qrc rename to src/interface/modeler/quickapp/images.qrc diff --git a/src/interface/quick/images/images.qrc b/src/interface/modeler/quickapp/images/images.qrc similarity index 100% rename from src/interface/quick/images/images.qrc rename to src/interface/modeler/quickapp/images/images.qrc diff --git a/src/interface/quick/main.cpp b/src/interface/modeler/quickapp/main.cpp similarity index 89% rename from src/interface/quick/main.cpp rename to src/interface/modeler/quickapp/main.cpp index 6a8db3f..ad89df8 100644 --- a/src/interface/quick/main.cpp +++ b/src/interface/modeler/quickapp/main.cpp @@ -11,6 +11,7 @@ int main(int argc, char *argv[]) qmlRegisterType("Paysages", 1, 0, "OpenGLView"); QQuickView view; + view.setTitle(QObject::tr("Paysages 3D")); view.setResizeMode(QQuickView::SizeRootObjectToView); view.setSource(QUrl("qrc:///main.qml")); view.show(); diff --git a/src/interface/quick/quick_global.h b/src/interface/modeler/quickapp/modeler_global.h similarity index 51% rename from src/interface/quick/quick_global.h rename to src/interface/modeler/quickapp/modeler_global.h index b92e58b..39ab8cb 100644 --- a/src/interface/quick/quick_global.h +++ b/src/interface/modeler/quickapp/modeler_global.h @@ -1,16 +1,16 @@ -#ifndef QUICK_GLOBAL_H -#define QUICK_GLOBAL_H +#ifndef MODELER_GLOBAL_H +#define MODELER_GLOBAL_H #include "definition_global.h" #include "software_global.h" #include "opengl_global.h" namespace paysages { -namespace quick { +namespace modeler { class ItemOpenGLView; } } -using namespace paysages::quick; +using namespace paysages::modeler; -#endif // QUICK_GLOBAL_H +#endif // MODELER_GLOBAL_H diff --git a/src/interface/modeler/quickapp/qml.qrc b/src/interface/modeler/quickapp/qml.qrc new file mode 100644 index 0000000..787b561 --- /dev/null +++ b/src/interface/modeler/quickapp/qml.qrc @@ -0,0 +1,7 @@ + + + qml/main.qml + qml/ToolbarButton.qml + qml/OpenGLView.qml + + diff --git a/src/interface/modeler/quickapp/qml/OpenGLView.qml b/src/interface/modeler/quickapp/qml/OpenGLView.qml new file mode 100644 index 0000000..af5804e --- /dev/null +++ b/src/interface/modeler/quickapp/qml/OpenGLView.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Rectangle { + width: 100 + height: 62 +} diff --git a/src/interface/quick/ToolbarButton.qml b/src/interface/modeler/quickapp/qml/ToolbarButton.qml similarity index 88% rename from src/interface/quick/ToolbarButton.qml rename to src/interface/modeler/quickapp/qml/ToolbarButton.qml index 512c87e..ae703b5 100644 --- a/src/interface/quick/ToolbarButton.qml +++ b/src/interface/modeler/quickapp/qml/ToolbarButton.qml @@ -1,7 +1,7 @@ import QtQuick 2.0 Item { - property string code + property string picture property bool selected: false property bool hovered: false @@ -24,7 +24,7 @@ Item { Image { id: image - source: "qrc:///toolbar/primary/tab_" + parent.code + ".png" + source: parent.picture anchors.centerIn: parent } diff --git a/src/interface/modeler/quickapp/qml/app.qrc b/src/interface/modeler/quickapp/qml/app.qrc new file mode 100644 index 0000000..86302af --- /dev/null +++ b/src/interface/modeler/quickapp/qml/app.qrc @@ -0,0 +1,12 @@ + + + ToolbarButton.qml + main.qml + images/tab_atmosphere.png + images/tab_clouds.png + images/tab_render.png + images/tab_terrain.png + images/tab_textures.png + images/tab_water.png + + diff --git a/src/interface/quick/images/tab_atmosphere.png b/src/interface/modeler/quickapp/qml/images/tab_atmosphere.png similarity index 100% rename from src/interface/quick/images/tab_atmosphere.png rename to src/interface/modeler/quickapp/qml/images/tab_atmosphere.png diff --git a/src/interface/quick/images/tab_clouds.png b/src/interface/modeler/quickapp/qml/images/tab_clouds.png similarity index 100% rename from src/interface/quick/images/tab_clouds.png rename to src/interface/modeler/quickapp/qml/images/tab_clouds.png diff --git a/src/interface/quick/images/tab_render.png b/src/interface/modeler/quickapp/qml/images/tab_render.png similarity index 100% rename from src/interface/quick/images/tab_render.png rename to src/interface/modeler/quickapp/qml/images/tab_render.png diff --git a/src/interface/quick/images/tab_terrain.png b/src/interface/modeler/quickapp/qml/images/tab_terrain.png similarity index 100% rename from src/interface/quick/images/tab_terrain.png rename to src/interface/modeler/quickapp/qml/images/tab_terrain.png diff --git a/src/interface/quick/images/tab_textures.png b/src/interface/modeler/quickapp/qml/images/tab_textures.png similarity index 100% rename from src/interface/quick/images/tab_textures.png rename to src/interface/modeler/quickapp/qml/images/tab_textures.png diff --git a/src/interface/quick/images/tab_water.png b/src/interface/modeler/quickapp/qml/images/tab_water.png similarity index 100% rename from src/interface/quick/images/tab_water.png rename to src/interface/modeler/quickapp/qml/images/tab_water.png diff --git a/src/interface/quick/main.qml b/src/interface/modeler/quickapp/qml/main.qml similarity index 85% rename from src/interface/quick/main.qml rename to src/interface/modeler/quickapp/qml/main.qml index 0aff8e8..2087bd4 100644 --- a/src/interface/quick/main.qml +++ b/src/interface/modeler/quickapp/qml/main.qml @@ -34,27 +34,27 @@ OpenGLView { ToolbarButton { id: tool_terrain - code: "terrain" + picture: "images/tab_terrain.png" } ToolbarButton { id: tool_textures - code: "textures" + picture: "images/tab_textures.png" } ToolbarButton { id: tool_water - code: "water" + picture: "images/tab_water.png" } ToolbarButton { id: tool_atmosphere - code: "atmosphere" + picture: "images/tab_atmosphere.png" } ToolbarButton { id: tool_clouds - code: "clouds" + picture: "images/tab_clouds.png" } ToolbarButton { id: tool_render - code: "render" + picture: "images/tab_render.png" } } } diff --git a/src/interface/modeler/quickapp/quickapp.pro b/src/interface/modeler/quickapp/quickapp.pro new file mode 100644 index 0000000..61ee72a --- /dev/null +++ b/src/interface/modeler/quickapp/quickapp.pro @@ -0,0 +1,56 @@ +TEMPLATE = app + +QT += qml quick widgets + +include(../../../common.pri) + +SOURCES += main.cpp \ + OpenGLView.cpp + +RESOURCES += \ + qml/app.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = ../extension + +# Default rules for deployment. +include(deployment.pri) + +HEADERS += \ + OpenGLView.h \ + modeler_global.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 +else:unix: LIBS += -L$$OUT_PWD/../../../system/ -lpaysages_system +INCLUDEPATH += $$PWD/../../../system +DEPENDPATH += $$PWD/../../../system + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../../basics/release/ -lpaysages_basics +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../../basics/debug/ -lpaysages_basics +else:unix: LIBS += -L$$OUT_PWD/../../../basics/ -lpaysages_basics +INCLUDEPATH += $$PWD/../../../basics +DEPENDPATH += $$PWD/../../../basics + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../../definition/release/ -lpaysages_definition +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../../definition/debug/ -lpaysages_definition +else:unix: LIBS += -L$$OUT_PWD/../../../definition/ -lpaysages_definition +INCLUDEPATH += $$PWD/../../../definition +DEPENDPATH += $$PWD/../../../definition + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../../render/software/release/ -lpaysages_render_software +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../../render/software/debug/ -lpaysages_render_software +else:unix: LIBS += -L$$OUT_PWD/../../../render/software/ -lpaysages_render_software +INCLUDEPATH += $$PWD/../../../render/software +DEPENDPATH += $$PWD/../../../render/software + +win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../../render/opengl/release/ -lpaysages_render_opengl +else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../../render/opengl/debug/ -lpaysages_render_opengl +else:unix: LIBS += -L$$OUT_PWD/../../../render/opengl/ -lpaysages_render_opengl +INCLUDEPATH += $$PWD/../../../render/opengl +DEPENDPATH += $$PWD/../../../render/opengl + +OTHER_FILES += \ + qml/main.qml \ + qml/ToolbarButton.qml \ + qml/OpenGLView.qml diff --git a/src/interface/quick/qml.qrc b/src/interface/quick/qml.qrc deleted file mode 100644 index 7292848..0000000 --- a/src/interface/quick/qml.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - main.qml - ToolbarButton.qml - - diff --git a/src/interface/quick/quick.pro b/src/interface/quick/quick.pro deleted file mode 100644 index fb2c7a0..0000000 --- a/src/interface/quick/quick.pro +++ /dev/null @@ -1,51 +0,0 @@ -TEMPLATE = app - -QT += qml quick widgets - -include(../../common.pri) - -SOURCES += main.cpp \ - OpenGLView.cpp - -RESOURCES += qml.qrc \ - images/images.qrc - -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = - -# Default rules for deployment. -include(deployment.pri) - -HEADERS += \ - quick_global.h \ - OpenGLView.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 -else:unix: LIBS += -L$$OUT_PWD/../../system/ -lpaysages_system -INCLUDEPATH += $$PWD/../../system -DEPENDPATH += $$PWD/../../system - -win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../basics/release/ -lpaysages_basics -else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../basics/debug/ -lpaysages_basics -else:unix: LIBS += -L$$OUT_PWD/../../basics/ -lpaysages_basics -INCLUDEPATH += $$PWD/../../basics -DEPENDPATH += $$PWD/../../basics - -win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../definition/release/ -lpaysages_definition -else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../definition/debug/ -lpaysages_definition -else:unix: LIBS += -L$$OUT_PWD/../../definition/ -lpaysages_definition -INCLUDEPATH += $$PWD/../../definition -DEPENDPATH += $$PWD/../../definition - -win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../render/software/release/ -lpaysages_render_software -else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../render/software/debug/ -lpaysages_render_software -else:unix: LIBS += -L$$OUT_PWD/../../render/software/ -lpaysages_render_software -INCLUDEPATH += $$PWD/../../render/software -DEPENDPATH += $$PWD/../../render/software - -win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../render/opengl/release/ -lpaysages_render_opengl -else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../render/opengl/debug/ -lpaysages_render_opengl -else:unix: LIBS += -L$$OUT_PWD/../../render/opengl/ -lpaysages_render_opengl -INCLUDEPATH += $$PWD/../../render/opengl -DEPENDPATH += $$PWD/../../render/opengl diff --git a/src/paysages.pro b/src/paysages.pro index 81fe961..2deeb5a 100644 --- a/src/paysages.pro +++ b/src/paysages.pro @@ -10,7 +10,7 @@ SUBDIRS = \ render/opengl \ interface/commandline \ interface/desktop \ - interface/quick + interface/modeler exists( tests/googletest/sources/src/gtest-all.cc ) { SUBDIRS += \ From 3814f63ac041f71acbaf0de9146c0f1267266222 Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Wed, 27 Aug 2014 17:23:59 +0200 Subject: [PATCH 05/13] Experiments on toolbars --- .gitignore | 1 + .../modeler/quickapp/images/images.qrc | 10 -- .../modeler/quickapp/qml/Toolbar.qml | 21 +++ .../modeler/quickapp/qml/ToolbarButton.qml | 36 +++++- .../modeler/quickapp/qml/Tooltip.qml | 16 +++ src/interface/modeler/quickapp/qml/app.qrc | 5 + .../quickapp/qml/images/display_topdown.png | Bin 0 -> 7781 bytes .../modeler/quickapp/qml/images/help.png | Bin 0 -> 13448 bytes .../quickapp/qml/images/tab_display.png | Bin 0 -> 6077 bytes src/interface/modeler/quickapp/qml/main.qml | 121 +++++++++--------- src/interface/modeler/quickapp/quickapp.pro | 4 +- 11 files changed, 141 insertions(+), 73 deletions(-) delete mode 100644 src/interface/modeler/quickapp/images/images.qrc create mode 100644 src/interface/modeler/quickapp/qml/Toolbar.qml create mode 100644 src/interface/modeler/quickapp/qml/Tooltip.qml create mode 100644 src/interface/modeler/quickapp/qml/images/display_topdown.png create mode 100644 src/interface/modeler/quickapp/qml/images/help.png create mode 100644 src/interface/modeler/quickapp/qml/images/tab_display.png diff --git a/.gitignore b/.gitignore index 8d7a6b3..df7cc34 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ ui_*.h /paysages3d-linux/ /paysages3d-linux.tar.bz2 /config.vim +/callgrind.out.* diff --git a/src/interface/modeler/quickapp/images/images.qrc b/src/interface/modeler/quickapp/images/images.qrc deleted file mode 100644 index d3a2921..0000000 --- a/src/interface/modeler/quickapp/images/images.qrc +++ /dev/null @@ -1,10 +0,0 @@ - - - tab_water.png - tab_atmosphere.png - tab_clouds.png - tab_render.png - tab_terrain.png - tab_textures.png - - diff --git a/src/interface/modeler/quickapp/qml/Toolbar.qml b/src/interface/modeler/quickapp/qml/Toolbar.qml new file mode 100644 index 0000000..46838d6 --- /dev/null +++ b/src/interface/modeler/quickapp/qml/Toolbar.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 + +Rectangle { + + default property alias children : inner_space.children + width: 70 + height: parent.height + color: "#50000000" + + Column { + id: inner_space + spacing: (parent.height - children.length * tool_terrain.height) / (children.length + 1) + anchors.centerIn: parent + } + + Behavior on opacity { + PropertyAnimation { + duration: 200 + } + } +} diff --git a/src/interface/modeler/quickapp/qml/ToolbarButton.qml b/src/interface/modeler/quickapp/qml/ToolbarButton.qml index ae703b5..23c8edb 100644 --- a/src/interface/modeler/quickapp/qml/ToolbarButton.qml +++ b/src/interface/modeler/quickapp/qml/ToolbarButton.qml @@ -4,6 +4,8 @@ Item { property string picture property bool selected: false property bool hovered: false + property string helptext + property string hovertext width: image.width + 10 height: image.height + 10 @@ -26,14 +28,42 @@ Item { id: image source: parent.picture anchors.centerIn: parent + width: 32 + height: 32 } MouseArea { anchors.fill: parent hoverEnabled: true + cursorShape: Qt.PointingHandCursor - onEntered: parent.hovered = true - onExited: parent.hovered = false - onClicked: parent.selected = true + onEntered: { + parent.hovered = true; + tooltip_widget.hovertext = hovertext; + } + onExited: { + parent.hovered = false; + tooltip_widget.hovertext = ""; + } + onClicked: { + parent.selected = !parent.selected; + if (parent.selected) + { + var toolbar = parent.parent; + for (var i = 0; i < toolbar.children.length; ++i) + { + var child = toolbar.children[i] + if (child !== parent) + { + child.selected = false; + } + } + tooltip_widget.helptext = helptext; + } + else + { + tooltip_widget.helptext = ""; + } + } } } diff --git a/src/interface/modeler/quickapp/qml/Tooltip.qml b/src/interface/modeler/quickapp/qml/Tooltip.qml new file mode 100644 index 0000000..0ec4c3c --- /dev/null +++ b/src/interface/modeler/quickapp/qml/Tooltip.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +Rectangle { + property string helptext + property string hovertext + width: content.width + height: content.height + + color: "#99000000" + + Text { + id: content + color: "white" + text: parent.helptext || parent.hovertext + } +} diff --git a/src/interface/modeler/quickapp/qml/app.qrc b/src/interface/modeler/quickapp/qml/app.qrc index 86302af..aa09ee8 100644 --- a/src/interface/modeler/quickapp/qml/app.qrc +++ b/src/interface/modeler/quickapp/qml/app.qrc @@ -8,5 +8,10 @@ images/tab_terrain.png images/tab_textures.png images/tab_water.png + images/tab_display.png + Toolbar.qml + images/display_topdown.png + images/help.png + Tooltip.qml diff --git a/src/interface/modeler/quickapp/qml/images/display_topdown.png b/src/interface/modeler/quickapp/qml/images/display_topdown.png new file mode 100644 index 0000000000000000000000000000000000000000..442706b510185d2523c42cacefd6685bc484f7b9 GIT binary patch literal 7781 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 literal 0 HcmV?d00001 diff --git a/src/interface/modeler/quickapp/qml/images/help.png b/src/interface/modeler/quickapp/qml/images/help.png new file mode 100644 index 0000000000000000000000000000000000000000..fa42c5aae2f7cf7f2e81c2de0b686b7a1e304012 GIT binary patch literal 13448 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 PmIt&o4AeiX+K2x?98wP9 literal 0 HcmV?d00001 diff --git a/src/interface/modeler/quickapp/qml/main.qml b/src/interface/modeler/quickapp/qml/main.qml index 2087bd4..ceee3b9 100644 --- a/src/interface/modeler/quickapp/qml/main.qml +++ b/src/interface/modeler/quickapp/qml/main.qml @@ -2,76 +2,79 @@ import QtQuick 2.2 import Paysages 1.0 OpenGLView { + id: main_ui + state: "Init" - width: 640 - height: 480 + width: 800 + height: 600 - Item { + Tooltip { + id: tooltip_widget + + anchors.top: parent.top + anchors.right: parent.right + } + + Toolbar { id: primary_toolbar - x: 0 - y: 0 - width: 70 - height: parent.height + color: "#90000000" - Rectangle { - width: parent.height - height: parent.width - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - transformOrigin: Item.Center - rotation: -90 - gradient: Gradient { - GradientStop { position: 0.0; color: "#605055FF" } - GradientStop { position: 1.0; color: "#005055FF" } - } + anchors.left: parent.left + + ToolbarButton { + id: tool_display + picture: "images/tab_display.png" + hovertext: qsTr("Display options") } - - Column { - - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - spacing: (parent.height - 6 * tool_terrain.height) / 7 - - ToolbarButton { - id: tool_terrain - picture: "images/tab_terrain.png" - } - ToolbarButton { - id: tool_textures - picture: "images/tab_textures.png" - } - ToolbarButton { - id: tool_water - picture: "images/tab_water.png" - } - ToolbarButton { - id: tool_atmosphere - picture: "images/tab_atmosphere.png" - } - ToolbarButton { - id: tool_clouds - picture: "images/tab_clouds.png" - } - ToolbarButton { - id: tool_render - picture: "images/tab_render.png" - } + ToolbarButton { + id: tool_terrain + picture: "images/tab_terrain.png" + } + ToolbarButton { + id: tool_textures + picture: "images/tab_textures.png" + } + ToolbarButton { + id: tool_water + picture: "images/tab_water.png" + } + ToolbarButton { + id: tool_atmosphere + picture: "images/tab_atmosphere.png" + } + ToolbarButton { + id: tool_clouds + picture: "images/tab_clouds.png" + } + ToolbarButton { + id: tool_render + picture: "images/tab_render.png" } } - Rectangle { - id: toolbar_render - anchors.top: primary_toolbar.top + Toolbar { + id: display_toolbar + opacity: 0 anchors.left: primary_toolbar.right - width: primary_toolbar.width - height: primary_toolbar.height - color: "#8800FF00" - SequentialAnimation on width { - loops: Animation.Infinite - PropertyAnimation { to: 0; duration: 1000 } - PropertyAnimation { to: primary_toolbar.width; duration: 1000 } + 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.") } } + states: [ + State { + name: "Display Mode" + when: tool_display.selected + + PropertyChanges { + target: display_toolbar + opacity: 1 + } + } + ] + } diff --git a/src/interface/modeler/quickapp/quickapp.pro b/src/interface/modeler/quickapp/quickapp.pro index 61ee72a..2b227cf 100644 --- a/src/interface/modeler/quickapp/quickapp.pro +++ b/src/interface/modeler/quickapp/quickapp.pro @@ -53,4 +53,6 @@ DEPENDPATH += $$PWD/../../../render/opengl OTHER_FILES += \ qml/main.qml \ qml/ToolbarButton.qml \ - qml/OpenGLView.qml + qml/OpenGLView.qml \ + qml/Toolbar.qml \ + qml/Tooltip.qml From d909ff380f571c6ca26b0cc7d96932567859ad38 Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Wed, 27 Aug 2014 18:19:48 +0200 Subject: [PATCH 06/13] Fixed opengl drawing in qtquick window --- Makefile | 3 + src/interface/modeler/quickapp/OpenGLView.cpp | 49 +++++++++++++-- src/interface/modeler/quickapp/OpenGLView.h | 5 ++ src/interface/modeler/quickapp/quickapp.pro | 2 + src/render/opengl/OpenGLRenderer.cpp | 61 +++++++++++-------- src/render/opengl/OpenGLRenderer.h | 3 + 6 files changed, 94 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index f3cb8b7..d3b49be 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,9 @@ endif run_cli:build LD_LIBRARY_PATH=$(LIBRARY_PATH) ${RUNNER} ${BUILDPATH}/interface/commandline/paysages-cli $(ARGS) +run_modeler:build + LD_LIBRARY_PATH=$(LIBRARY_PATH) ${RUNNER} ${BUILDPATH}/interface/modeler/quickapp/paysages-modeler $(ARGS) + run:build LD_LIBRARY_PATH=$(LIBRARY_PATH) ${RUNNER} ${BUILDPATH}/interface/desktop/paysages-gui $(ARGS) diff --git a/src/interface/modeler/quickapp/OpenGLView.cpp b/src/interface/modeler/quickapp/OpenGLView.cpp index 24dbac4..a9953df 100644 --- a/src/interface/modeler/quickapp/OpenGLView.cpp +++ b/src/interface/modeler/quickapp/OpenGLView.cpp @@ -1,10 +1,12 @@ #include "OpenGLView.h" #include +#include // TEMP #include "OpenGLRenderer.h" #include "Scenery.h" +#include "CameraDefinition.h" static OpenGLRenderer renderer; static Scenery scenery; @@ -12,19 +14,26 @@ OpenGLView::OpenGLView(QQuickItem *parent) : QQuickItem(parent) { initialized = false; + window = NULL; - connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); + setAcceptedMouseButtons(Qt::AllButtons); + setAcceptHoverEvents(true); + setKeepMouseGrab(true); scenery.autoPreset(); - renderer.setScenery(&scenery); + + connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); + startTimer(250); } void OpenGLView::handleWindowChanged(QQuickWindow *win) { if (win) { - connect(window(), SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); + window = win; + + connect(window, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); win->setClearBeforeRendering(false); @@ -41,7 +50,39 @@ void OpenGLView::paint() } renderer.resize(width(), height()); + renderer.prepareOpenGLState(); renderer.paint(); - window()->resetOpenGLState(); + if (window) + { + window->resetOpenGLState(); + } +} + +void OpenGLView::hoverMoveEvent(QHoverEvent *event) +{ + CameraDefinition camera; + renderer.getScenery()->getCamera(&camera); + + QPointF diff = event->posF() - event->oldPosF(); + camera.strafeRight(diff.x() * 0.1); + camera.strafeUp(diff.y() * 0.1); + camera.validate(); + + camera.copy(renderer.render_camera); + renderer.getScenery()->setCamera(&camera); + renderer.getScenery()->getCamera(&camera); + renderer.cameraChangeEvent(&camera); + if (window) + { + window->update(); + } +} + +void OpenGLView::timerEvent(QTimerEvent *) +{ + if (window) + { + window->update(); + } } diff --git a/src/interface/modeler/quickapp/OpenGLView.h b/src/interface/modeler/quickapp/OpenGLView.h index cdd41ae..5675818 100644 --- a/src/interface/modeler/quickapp/OpenGLView.h +++ b/src/interface/modeler/quickapp/OpenGLView.h @@ -18,8 +18,13 @@ public slots: void handleWindowChanged(QQuickWindow *win); void paint(); +protected: + virtual void hoverMoveEvent(QHoverEvent *event) override; + virtual void timerEvent(QTimerEvent *event) override; + private: bool initialized; + QQuickWindow *window; }; } diff --git a/src/interface/modeler/quickapp/quickapp.pro b/src/interface/modeler/quickapp/quickapp.pro index 2b227cf..0416b57 100644 --- a/src/interface/modeler/quickapp/quickapp.pro +++ b/src/interface/modeler/quickapp/quickapp.pro @@ -10,6 +10,8 @@ SOURCES += main.cpp \ RESOURCES += \ qml/app.qrc +TARGET = paysages-modeler + # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = ../extension diff --git a/src/render/opengl/OpenGLRenderer.cpp b/src/render/opengl/OpenGLRenderer.cpp index 8eb2424..1361795 100644 --- a/src/render/opengl/OpenGLRenderer.cpp +++ b/src/render/opengl/OpenGLRenderer.cpp @@ -16,6 +16,8 @@ OpenGLRenderer::OpenGLRenderer(Scenery* scenery): SoftwareRenderer(scenery) { ready = false; + vp_width = 1; + vp_height = 1; render_quality = 3; @@ -50,25 +52,7 @@ void OpenGLRenderer::initialize() if (ready) { - functions->glClearColor(0.0, 0.0, 0.0, 0.0); - - functions->glDisable(GL_LIGHTING); - - functions->glFrontFace(GL_CCW); - functions->glCullFace(GL_BACK); - functions->glEnable(GL_CULL_FACE); - - functions->glDepthFunc(GL_LESS); - functions->glDepthMask(1); - functions->glEnable(GL_DEPTH_TEST); - - functions->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - functions->glEnable(GL_LINE_SMOOTH); - functions->glLineWidth(1.0); - - functions->glDisable(GL_FOG); - - functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + prepareOpenGLState(); prepare(); @@ -92,28 +76,55 @@ void OpenGLRenderer::initialize() } } -void OpenGLRenderer::resize(int width, int height) +void OpenGLRenderer::prepareOpenGLState() { if (ready) { - functions->glViewport(0, 0, width, height); + functions->glDisable(GL_LIGHTING); + + functions->glFrontFace(GL_CCW); + functions->glCullFace(GL_BACK); + functions->glEnable(GL_CULL_FACE); + + functions->glDepthFunc(GL_LESS); + functions->glDepthMask(1); + functions->glEnable(GL_DEPTH_TEST); + + functions->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + functions->glEnable(GL_LINE_SMOOTH); + functions->glLineWidth(1.0); + + functions->glDisable(GL_FOG); + + functions->glEnable(GL_BLEND); + functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + functions->glClearColor(0.0, 0.0, 0.0, 0.0); + functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + functions->glViewport(0, 0, vp_width, vp_height); } +} + +void OpenGLRenderer::resize(int width, int height) +{ + vp_width = width; + vp_height = height; + getScenery()->getCamera()->setRenderSize(width, height); render_camera->setRenderSize(width, height); cameraChangeEvent(getScenery()->getCamera()); + + prepareOpenGLState(); } void OpenGLRenderer::paint() { if (ready) { - functions->glClearColor(0.0, 0.0, 0.0, 0.0); functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - functions->glEnable(GL_BLEND); - functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - skybox->render(); terrain->render(); water->render(); diff --git a/src/render/opengl/OpenGLRenderer.h b/src/render/opengl/OpenGLRenderer.h index d4daeab..5a3e90c 100644 --- a/src/render/opengl/OpenGLRenderer.h +++ b/src/render/opengl/OpenGLRenderer.h @@ -18,6 +18,7 @@ public: virtual ~OpenGLRenderer(); void initialize(); + void prepareOpenGLState(); void resize(int width, int height); void paint(); @@ -31,6 +32,8 @@ public: private: bool ready; + int vp_width; + int vp_height; OpenGLFunctions* functions; OpenGLSharedState* shared_state; From 2251db361c657abd5dfb671aacb843f23deb61ec Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Thu, 28 Aug 2014 10:29:12 +0200 Subject: [PATCH 07/13] WIP on QtQuick toolbars --- graphics/icons.png | Bin 0 -> 12060 bytes graphics/icons.svg | 99 ++++++++++++++++++ {data/images => graphics}/logo.svg | 0 .../modeler/quickapp/MainModelerWindow.cpp | 24 +++++ .../modeler/quickapp/MainModelerWindow.h | 28 +++++ src/interface/modeler/quickapp/OpenGLView.cpp | 46 ++++---- src/interface/modeler/quickapp/OpenGLView.h | 3 +- src/interface/modeler/quickapp/main.cpp | 11 +- .../modeler/quickapp/modeler_global.h | 3 +- .../modeler/quickapp/qml/BasePanel.qml | 27 +++++ .../modeler/quickapp/qml/PanelWaterLevel.qml | 11 ++ .../modeler/quickapp/qml/Toolbar.qml | 3 +- .../modeler/quickapp/qml/ToolbarButton.qml | 20 +++- src/interface/modeler/quickapp/qml/app.qrc | 4 + .../quickapp/qml/images/icon_water.png | Bin 0 -> 875 bytes .../quickapp/qml/images/icon_water_level.png | Bin 0 -> 1562 bytes src/interface/modeler/quickapp/qml/main.qml | 32 +++++- src/interface/modeler/quickapp/quickapp.pro | 10 +- 18 files changed, 282 insertions(+), 39 deletions(-) create mode 100644 graphics/icons.png create mode 100644 graphics/icons.svg rename {data/images => graphics}/logo.svg (100%) create mode 100644 src/interface/modeler/quickapp/MainModelerWindow.cpp create mode 100644 src/interface/modeler/quickapp/MainModelerWindow.h create mode 100644 src/interface/modeler/quickapp/qml/BasePanel.qml create mode 100644 src/interface/modeler/quickapp/qml/PanelWaterLevel.qml create mode 100644 src/interface/modeler/quickapp/qml/images/icon_water.png create mode 100644 src/interface/modeler/quickapp/qml/images/icon_water_level.png diff --git a/graphics/icons.png b/graphics/icons.png new file mode 100644 index 0000000000000000000000000000000000000000..77dbd8967a040a47d6d5efc661f6f7e4c18c44f7 GIT binary patch literal 12060 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 SxBw+PNLSN9 + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/data/images/logo.svg b/graphics/logo.svg similarity index 100% rename from data/images/logo.svg rename to graphics/logo.svg diff --git a/src/interface/modeler/quickapp/MainModelerWindow.cpp b/src/interface/modeler/quickapp/MainModelerWindow.cpp new file mode 100644 index 0000000..f8cca47 --- /dev/null +++ b/src/interface/modeler/quickapp/MainModelerWindow.cpp @@ -0,0 +1,24 @@ +#include "MainModelerWindow.h" + +#include "OpenGLView.h" +#include "Scenery.h" +#include "OpenGLRenderer.h" + +MainModelerWindow::MainModelerWindow() +{ + scenery = new Scenery(); + scenery->autoPreset(); + renderer = new OpenGLRenderer(scenery); + + qmlRegisterType("Paysages", 1, 0, "OpenGLView"); + + setTitle(QObject::tr("Paysages 3D")); + setResizeMode(QQuickView::SizeRootObjectToView); + setSource(QUrl("qrc:///main.qml")); +} + +MainModelerWindow::~MainModelerWindow() +{ + delete renderer; + delete scenery; +} diff --git a/src/interface/modeler/quickapp/MainModelerWindow.h b/src/interface/modeler/quickapp/MainModelerWindow.h new file mode 100644 index 0000000..f599381 --- /dev/null +++ b/src/interface/modeler/quickapp/MainModelerWindow.h @@ -0,0 +1,28 @@ +#ifndef MAINMODELERWINDOW_H +#define MAINMODELERWINDOW_H + +#include "modeler_global.h" + +#include + +namespace paysages { +namespace modeler { + +class MainModelerWindow: public QQuickView +{ + Q_OBJECT +public: + MainModelerWindow(); + virtual ~MainModelerWindow(); + + inline OpenGLRenderer *getRenderer() const {return renderer;} + +private: + OpenGLRenderer *renderer; + Scenery *scenery; +}; + +} +} + +#endif // MAINMODELERWINDOW_H diff --git a/src/interface/modeler/quickapp/OpenGLView.cpp b/src/interface/modeler/quickapp/OpenGLView.cpp index a9953df..23f0211 100644 --- a/src/interface/modeler/quickapp/OpenGLView.cpp +++ b/src/interface/modeler/quickapp/OpenGLView.cpp @@ -2,27 +2,22 @@ #include #include - -// TEMP +#include "MainModelerWindow.h" +#include "CameraDefinition.h" #include "OpenGLRenderer.h" #include "Scenery.h" -#include "CameraDefinition.h" -static OpenGLRenderer renderer; -static Scenery scenery; OpenGLView::OpenGLView(QQuickItem *parent) : QQuickItem(parent) { initialized = false; window = NULL; + renderer = NULL; setAcceptedMouseButtons(Qt::AllButtons); setAcceptHoverEvents(true); setKeepMouseGrab(true); - scenery.autoPreset(); - renderer.setScenery(&scenery); - connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); startTimer(250); } @@ -31,13 +26,17 @@ void OpenGLView::handleWindowChanged(QQuickWindow *win) { if (win) { - window = win; + window = qobject_cast(win); + if (window) + { + renderer = window->getRenderer(); - connect(window, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); + connect(win, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); - win->setClearBeforeRendering(false); + win->setClearBeforeRendering(false); - initialized = false; + initialized = false; + } } } @@ -45,13 +44,13 @@ void OpenGLView::paint() { if (not initialized) { - renderer.initialize(); + renderer->initialize(); initialized = true; } - renderer.resize(width(), height()); - renderer.prepareOpenGLState(); - renderer.paint(); + renderer->resize(width(), height()); + renderer->prepareOpenGLState(); + renderer->paint(); if (window) { @@ -61,18 +60,23 @@ void OpenGLView::paint() void OpenGLView::hoverMoveEvent(QHoverEvent *event) { + if (!renderer) + { + return; + } + CameraDefinition camera; - renderer.getScenery()->getCamera(&camera); + renderer->getScenery()->getCamera(&camera); QPointF diff = event->posF() - event->oldPosF(); camera.strafeRight(diff.x() * 0.1); camera.strafeUp(diff.y() * 0.1); camera.validate(); - camera.copy(renderer.render_camera); - renderer.getScenery()->setCamera(&camera); - renderer.getScenery()->getCamera(&camera); - renderer.cameraChangeEvent(&camera); + camera.copy(renderer->render_camera); + renderer->getScenery()->setCamera(&camera); + renderer->getScenery()->getCamera(&camera); + renderer->cameraChangeEvent(&camera); if (window) { window->update(); diff --git a/src/interface/modeler/quickapp/OpenGLView.h b/src/interface/modeler/quickapp/OpenGLView.h index 5675818..e59c379 100644 --- a/src/interface/modeler/quickapp/OpenGLView.h +++ b/src/interface/modeler/quickapp/OpenGLView.h @@ -24,7 +24,8 @@ protected: private: bool initialized; - QQuickWindow *window; + MainModelerWindow *window; + OpenGLRenderer *renderer; }; } diff --git a/src/interface/modeler/quickapp/main.cpp b/src/interface/modeler/quickapp/main.cpp index ad89df8..3d9237a 100644 --- a/src/interface/modeler/quickapp/main.cpp +++ b/src/interface/modeler/quickapp/main.cpp @@ -1,19 +1,12 @@ #include -#include -#include -#include "OpenGLView.h" +#include "MainModelerWindow.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); - qmlRegisterType("Paysages", 1, 0, "OpenGLView"); - - QQuickView view; - view.setTitle(QObject::tr("Paysages 3D")); - view.setResizeMode(QQuickView::SizeRootObjectToView); - view.setSource(QUrl("qrc:///main.qml")); + MainModelerWindow view; view.show(); return app.exec(); diff --git a/src/interface/modeler/quickapp/modeler_global.h b/src/interface/modeler/quickapp/modeler_global.h index 39ab8cb..f8088b8 100644 --- a/src/interface/modeler/quickapp/modeler_global.h +++ b/src/interface/modeler/quickapp/modeler_global.h @@ -7,7 +7,8 @@ namespace paysages { namespace modeler { - class ItemOpenGLView; + class MainModelerWindow; + class OpenGLView; } } diff --git a/src/interface/modeler/quickapp/qml/BasePanel.qml b/src/interface/modeler/quickapp/qml/BasePanel.qml new file mode 100644 index 0000000..82872d6 --- /dev/null +++ b/src/interface/modeler/quickapp/qml/BasePanel.qml @@ -0,0 +1,27 @@ +import QtQuick 2.0 + +Rectangle { + property ToolbarButton tool + id: panel + + width: 200 + height: parent.height - 100 + color: "red" + enabled: visible + + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + + states: [ + State { + name: "Active" + when: tool.selected + + PropertyChanges { + target: panel + visible: true + } + } + + ] +} diff --git a/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml b/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml new file mode 100644 index 0000000..e84bd6e --- /dev/null +++ b/src/interface/modeler/quickapp/qml/PanelWaterLevel.qml @@ -0,0 +1,11 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 + +BasePanel { + width: 20 + + Slider { + 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 46838d6..b8a1424 100644 --- a/src/interface/modeler/quickapp/qml/Toolbar.qml +++ b/src/interface/modeler/quickapp/qml/Toolbar.qml @@ -5,7 +5,8 @@ Rectangle { default property alias children : inner_space.children width: 70 height: parent.height - color: "#50000000" + color: "#50888888" + enabled: opacity > 0 Column { id: inner_space diff --git a/src/interface/modeler/quickapp/qml/ToolbarButton.qml b/src/interface/modeler/quickapp/qml/ToolbarButton.qml index 23c8edb..727c408 100644 --- a/src/interface/modeler/quickapp/qml/ToolbarButton.qml +++ b/src/interface/modeler/quickapp/qml/ToolbarButton.qml @@ -1,4 +1,5 @@ import QtQuick 2.0 +import QtGraphicalEffects 1.0 Item { property string picture @@ -13,7 +14,7 @@ Item { Rectangle { id: glow anchors.fill: parent - color: "white" + color: "#cccccc" radius: 8 opacity: parent.selected ? 1.0 : (parent.hovered ? 0.5 : 0.0) @@ -22,6 +23,13 @@ Item { duration: 200 } } + RectangularGlow { + anchors.fill: glow + glowRadius: 8 + spread: 0.2 + color: "white" + cornerRadius: glow.radius + glowRadius + } } Image { @@ -30,6 +38,16 @@ Item { anchors.centerIn: parent width: 32 height: 32 + antialiasing: true + } + DropShadow { + anchors.fill: image + horizontalOffset: 2 + verticalOffset: 2 + radius: 4.0 + samples: 16 + color: "#80000000" + source: image } MouseArea { diff --git a/src/interface/modeler/quickapp/qml/app.qrc b/src/interface/modeler/quickapp/qml/app.qrc index aa09ee8..a216b39 100644 --- a/src/interface/modeler/quickapp/qml/app.qrc +++ b/src/interface/modeler/quickapp/qml/app.qrc @@ -13,5 +13,9 @@ images/display_topdown.png images/help.png Tooltip.qml + images/icon_water.png + images/icon_water_level.png + BasePanel.qml + PanelWaterLevel.qml diff --git a/src/interface/modeler/quickapp/qml/images/icon_water.png b/src/interface/modeler/quickapp/qml/images/icon_water.png new file mode 100644 index 0000000000000000000000000000000000000000..b87e23c7aea4ce4c18f2298f998ba6b6302259cb GIT binary patch literal 875 zcmV-x1C;!UP)2}hMJ@4}OO>Zrt>4yo$g7ED!-Ea`__!D)olZ+I7;II- zBP+rCfEPxEj*gB>y{xXTir?>VRl>Yg1Y9*LaAage8f9r|N#gN%s{+cvG1c&zQE`2J zeNrlw>cVF-8S(ji?M{d`%p-`v^KQ}jL#^UG|uvLYCz177;B9XdxKNgFbA>bphOND@#Q9*-) zgEBlkEHg7R|G}qHDYKTxYrqZ_0-}2JvSx9iP)HUQ7DPlO91fc$prFr3T~8SJ)TlsB z(rm^;9-a0Cx9*3G-JS1;4{q~ffe|7$P(&CQ?nb{4IBlM z`V4*$*sot((>GOl;2Cfac&CeS;q000HKNkl9LGOrcXPAl zFr2vBCWR{k9ays!tv8%lL_|gr^a{QIF{2lag3MK11AS-tF|qz7PBHaCdg^-EF&fJ3lx)_dMsE=lA@6&-eGbK}<2l6jMww z#Z({)M!BEVRH^YQU^_5d_lc<>e7VN^fD^#4KtFKKR6@d=KuQPzcoqnOnWES@Ja{6(Oz#zKeKXtMs_2 zbNDDEltn~^w2Gb}i!~a61Nt3~@a{mdDIkp4RH$n(OI{B0gT;h^vZ>y{nDPoJ&%$;C z1Np%S`^_iP_#VH|JjSGe5SXDj9siblmwN_M90)Y|iV&FAp ze+Pg+f!~35fL3!-L5`_xxxPIEcpBIV90c|Qe*r%MF9R(``10{cmz^LLs@Os$CXWJ_ z0*iqTU>`%Rt~F8;z-_>eh_z?ybQ^SkFYu3eY*q)UP3t|b`F?ej7GXY{06K9t^?+J<~2t`eXMuy*ZfHuuLu4W;?}7qI8&(m+bH}Huw0d7 zz2OmfzU%?uBG1gTigtA#%-Uu9q0-%IFTd|riktQj(GRRQ?=IAdh731M9iP>j|B&G} zx}zth7*~r}MC=1LdKK&GLSiVh%qG#xSOB@P4cG(B^5$2H$sg(uxD9pdq~Furw=$)q z?iYLEZ=>edd4kl-`8prbtXA59QMOae9-s->Bn2H6LM?Ry8^+RnaS*BiwuWwG7c}{`IAQA8u_4JV{(Tz zU#ES%rDuJ>5>NOg@>%zcwSnR`b(dETR|3y_s0dB(V2d1J!U(uV&pyu~(VA%lb?c|} zI|V!{nEo zHx_4@ivlubf~U&1YxTQUFf3I2%dTVj%<@8bP7RSl*B!@Ad(53qp^Bc+@JT6}1YX?| zPNV`{12jDjd%$AFLIy^GE)>y(3klVy^UtAdlj`xNP4gUU=Q z*`-d-c_zWB)KxKx2~?V^+T;(e*)iS`DenYhlk9$3o||^*=LQLXL$M2=iSE?qAIhUc z8~~rHlwDAYVbh)9g;K&Rrpyc?@^#k-*saoeMk(hZZqp6&;M*0#7$L*~T%uFoI)Z7H zEG49X9)^1TWf@v)w+JnrlQENY-5l5MzRXk3YSRrWNDW@BD1hPrCh1Vd_kk+E=2GxN2hP?|YaCF=Z&2pk6~!D Date: Thu, 28 Aug 2014 15:09:47 +0200 Subject: [PATCH 08/13] Added daytime control to QtQuick UI --- graphics/icons.png | Bin 12060 -> 43833 bytes graphics/icons.svg | 109 +++++++++++++++++- src/definition/AtmosphereDefinition.cpp | 16 +++ src/definition/AtmosphereDefinition.h | 5 + .../modeler/quickapp/AtmosphereModeler.cpp | 26 +++++ .../modeler/quickapp/AtmosphereModeler.h | 27 +++++ .../modeler/quickapp/MainModelerWindow.cpp | 13 +++ .../modeler/quickapp/MainModelerWindow.h | 6 + .../modeler/quickapp/WaterModeler.cpp | 19 +++ src/interface/modeler/quickapp/WaterModeler.h | 27 +++++ .../modeler/quickapp/modeler_global.h | 3 + .../modeler/quickapp/qml/BaseChoice.qml | 29 +++++ .../modeler/quickapp/qml/BaseChoiceItem.qml | 50 ++++++++ .../modeler/quickapp/qml/BasePanel.qml | 10 +- .../modeler/quickapp/qml/BaseSlider.qml | 7 ++ .../quickapp/qml/PanelAtmosphereDaytime.qml | 46 ++++++++ .../modeler/quickapp/qml/PanelWaterLevel.qml | 4 +- .../modeler/quickapp/qml/Toolbar.qml | 10 ++ src/interface/modeler/quickapp/qml/app.qrc | 8 ++ .../quickapp/qml/images/icon_atmosphere.png | Bin 0 -> 1322 bytes .../qml/images/icon_atmosphere_day.png | Bin 0 -> 927 bytes .../qml/images/icon_atmosphere_daytime.png | Bin 0 -> 1238 bytes .../qml/images/icon_atmosphere_night.png | Bin 0 -> 871 bytes src/interface/modeler/quickapp/qml/main.qml | 29 ++++- src/interface/modeler/quickapp/quickapp.pro | 14 ++- src/render/opengl/OpenGLRenderer.h | 4 + src/tests/AtmosphereDefinition_Test.cpp | 36 ++++++ src/tests/tests.pro | 3 +- 28 files changed, 486 insertions(+), 15 deletions(-) create mode 100644 src/interface/modeler/quickapp/AtmosphereModeler.cpp create mode 100644 src/interface/modeler/quickapp/AtmosphereModeler.h create mode 100644 src/interface/modeler/quickapp/WaterModeler.cpp create mode 100644 src/interface/modeler/quickapp/WaterModeler.h create mode 100644 src/interface/modeler/quickapp/qml/BaseChoice.qml create mode 100644 src/interface/modeler/quickapp/qml/BaseChoiceItem.qml create mode 100644 src/interface/modeler/quickapp/qml/BaseSlider.qml create mode 100644 src/interface/modeler/quickapp/qml/PanelAtmosphereDaytime.qml create mode 100644 src/interface/modeler/quickapp/qml/images/icon_atmosphere.png create mode 100644 src/interface/modeler/quickapp/qml/images/icon_atmosphere_day.png create mode 100644 src/interface/modeler/quickapp/qml/images/icon_atmosphere_daytime.png create mode 100644 src/interface/modeler/quickapp/qml/images/icon_atmosphere_night.png create mode 100644 src/tests/AtmosphereDefinition_Test.cpp diff --git a/graphics/icons.png b/graphics/icons.png index 77dbd8967a040a47d6d5efc661f6f7e4c18c44f7..b3e56b06a8e6f9b7bfd35afeda059b9ab6038dae 100644 GIT binary patch literal 43833 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 MN50eZm(6#xJL literal 12060 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 SxBw+PNLSN9 + 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 0000000000000000000000000000000000000000..5514dfb6bdb9491b23c3ccd9b8214760320982ab GIT binary patch literal 1322 zcmV+_1=aeAP)^#lPvpdi8{9)L==bpKD{%7w!_nb4cP(>A0Bt#7` zuu{nn1bzTssbm8j1is8Ofr>`e096Ad$ACN=GK~k{4SZI~t7t$u5V#6xjj4YsFauZ* z90ELD2Y|J}6ku?Saq56+z_7kHz$rkt$ZP>ljL>~p=f2m=wNFM3!xg~K(p}LXRzWN9 zp&sZk@F;Mc>8}M|jX^wkJsy~+1$b9|-9Sfw+d>xszZn7}B!A<7koT|U8e^f6ZH~E3 z`UHc41;8%geEsevxDEs70_{32Cg;gP4oOJfzjo#|4w#zKJWasmc{IRHDb96W33*Ke zW~DLE?+=lApXng`mD=+i`h$RL^|Ry#*pk8a{X}DT zNVZ(<9Uf;v2oUUVYneC`IDeyYrtcZtb0ltqxetpC^HOdIP0_k!ThO74Iucik5 zp*-N4mT25bd30V{!VMU1o9)EuHpc6;>j3nW{u_L`7; zo&_Fpj5A-WFg4Ve<&{-w{CSbxWXfqC@Q+qP5Psq1n^F~2H#$mRX<@V>d%8K&_JyR^ z^}rvhZ?=}g09n5ry;}yjKcZN(#K?9@_Hrrf30c1#ZVs8(_X~?9J45Y~zNzl3*W*uy zq}U_n?E#*a&X965KodR1*5(MEL-GeFCn<>);|#OHBw&tt)+WUOZNPUS(c!1kUk2>Y zdIfZ*Sng^t;Wr9cx>cHMjA?McDDqLMmgMkaN=y+rM#k(?{toc9$gB*x=R${UsiMZA zM*Y#zb$;Ce!n9f6UM* z!+50krAnV-4u#s@B1hj)mjjP%g(>ErqYnT$$qrj;{UrMUT32kM`~n*&hS@ ze2l5)_yN!Oaw9)V1rLv&vUd=pjqey$ZU&gZk(J%3W3!zK#C;t38BFTv@BiuH`+$qJ gRjR0>iYijYf0u(9JEWRBPyhe`07*qoM6N<$f=SeF%K!iX literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..90721c203f4c63d42cdc1ace8bb976577731fd14 GIT binary patch literal 927 zcmV;Q17Q4#P)WQK>l1lh+SA);GR(X}8tbtn%(L{JcT%DNO~ViKiEAD1Xd zq?FR6(tI7>EDXyo?YjH+Kd|$MfqDCO{vW@Y`R~l^f}AV@-U7qGVp1r_ft)JGq?{-g z1W>NktI`O-2(bVx01LnZumCIo87cCqrv|`)Rv$|12;2>{V8x7in1oaT&A>)rmHJ%* zOaUXnAn-u#62)X4&<&gd%3{!02J8d+wB6tT$^>v4SP_H$jEbcjXb94v-{nl>97jqq zus=l5e&r@mImgkx!=>wGkcPKBoEQn&8yR3MhTxs@2iP9M{&L`phn}vWY;d4L2{%n zf#98T#nn-tJnnf0)WrF8*a}R#jI?XLFrFZQ9I!>%ZgpM%32ZCm(z!z!`mSB?O*nWb zF;*!16YAR0q?Y$3+T5!V2;M2zG@s^4Eu4k~0px&XlDomIN`8`ZK+^b0;oi>yUnK#& zG5|m>%HuBT6sR|3SG!XJz*>X0_4N_}Y77FfR06;Pg8)=W0GKuiz>EZdaf1L%N&px( z2*3vk0HX#07?3i2*N}x!k;Di9xNbo2KU5Gzq|$)iZ<6kT^Mb+8AoOB&p*j?S{MTO7 zLI8FtA4;PvhQdfGa6xmxk%I!kf7a~Js%saOj|GvvdRp3%~-f04x9*`KHw;(+Izs{6T6jA&;!$lz$ZZ7oGDzw?_Z~002ovPDHLkV1fq$ BrZNBk literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..97bed429a4a473c81324f533d041400f35143adc GIT binary patch literal 1238 zcmV;{1S$K8P)}Hxz!G$oJ==u$uo~~w$_ci|qCa7CPDuC~pJE$M z!`Qe#4s&pE$htO-fK#y?J41bvumE@BX3W5BT!pFl6@R6STZ;3sF^H=NcE@SIi|^2l zb4s3%!@|(`50fT11K;2)tiVZSUjNasr~ZU%KR&??WhONTFX3lAn9cV2Y7#qKR z5Q3Lp+k?0luoCATW8ZLH!XA6^%#j9;4He#6B?0|G-mC_ze5DY%Az_c3!F}~7ufHPV{|?+*@@#Gt8b=cTRZNO8lkiH|+WSFDqf_C_L)A<7Scvref4DF< z`$TkA$}tg7N2OQ@4|*sj-4rQvlFDC-^>}L_^J)+lM0HwzNIjv|iRc)_#GRNQ8ge71 z*Rl0hZI^0f9Nx+Z!=-}vh48a$vDoM+losX4(_auJdryMO@5M)zD!^(nJ?!Y=oCx2J zFXEK)=0Hi=mlFaG;HL0n6XMi+@Z~_VQxDs0IYR2$7Rgk9gJS)b zXuxEum$Q_Z2P>qyr{iwLK4ZOca)j@xN7FE<7JuMP#pYurm7FD8*SQ)j3ZK++tn4ps z;du`4%GPV$Q4#uD_@He6AQdFySX+ZEs0 ztx>xkVMhqQI_A$k+Jfkg8q75lXV-FbjVM)nqbPddC~JZ_>hP|iQMLLmTq|3feE?%3 zhSLm(yG*XxUvzOX*3Foo!OPRKjlC3@p$-*A&C~nm#^Ct zKVK=ww5TZC4PlIkim|nfn68qDF)YxHtK;_)#XeqFqZZG@E9~)jQnBSe1Fvb|XSjK2 zBy>cw(}&mNP7Q} AO8@`> literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..6f0aaee86b33cbe46f8f59b7a69a62cdcb7caee9 GIT binary patch literal 871 zcmV-t1DO1YP)#S2l?(Px&H%qNZ{V&|GUp~?>P~EmI89XLLd#)x$ph}Wmk&8r28&7 zixSq`4DyQ6LZWxzDn;4XAjQ0&v8QoJb8op8f1AU%o9_wL}i^E@R-0PYsa$J&$ZY9Rr*?^(b4IwcFh!nx^G1~6>UMw>E# zX@fQzl>y+qLmz8W2jKfsTu}y4F>uZ%lmRR{9N1U-6@=;?vlK&-ADQ*l#fR-viBx;+ui52EBhwwfBbMM?_g4(WPazUdJlCwk z<&G+fziK4@mYVQ-;F6K}2WsNi5C<<fM2Q__6Q@EI8v!eUJ-~V5NG;2hnYXh%yx`L676W&HZ^penyVsjS9_r`jLG+~a z3_BF&`aMJ8W5m(p8n`+f< xoS!^#NZd>)y=g%| Date: Tue, 9 Sep 2014 17:56:52 +0200 Subject: [PATCH 09/13] Added quick render to QtQuick UI --- .../modeler/quickapp/MainModelerWindow.cpp | 38 +++++- .../modeler/quickapp/MainModelerWindow.h | 6 + .../quickapp/RenderPreviewProvider.cpp | 85 ++++++++++++++ .../modeler/quickapp/RenderPreviewProvider.h | 53 +++++++++ .../modeler/quickapp/RenderProcess.cpp | 111 ++++++++++++++++++ .../modeler/quickapp/RenderProcess.h | 47 ++++++++ .../modeler/quickapp/modeler_global.h | 3 + .../modeler/quickapp/qml/RenderDialog.qml | 27 +++++ src/interface/modeler/quickapp/qml/app.qrc | 1 + src/interface/modeler/quickapp/qml/main.qml | 19 +++ src/interface/modeler/quickapp/quickapp.pro | 11 +- .../software/SoftwareCanvasRenderer.cpp | 2 + src/render/software/SoftwareCanvasRenderer.h | 2 + 13 files changed, 401 insertions(+), 4 deletions(-) create mode 100644 src/interface/modeler/quickapp/RenderPreviewProvider.cpp create mode 100644 src/interface/modeler/quickapp/RenderPreviewProvider.h create mode 100644 src/interface/modeler/quickapp/RenderProcess.cpp create mode 100644 src/interface/modeler/quickapp/RenderProcess.h create mode 100644 src/interface/modeler/quickapp/qml/RenderDialog.qml diff --git a/src/interface/modeler/quickapp/MainModelerWindow.cpp b/src/interface/modeler/quickapp/MainModelerWindow.cpp index 9148218..c82ceaf 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.cpp +++ b/src/interface/modeler/quickapp/MainModelerWindow.cpp @@ -5,6 +5,11 @@ #include "OpenGLRenderer.h" #include "AtmosphereModeler.h" #include "WaterModeler.h" +#include "RenderPreviewProvider.h" +#include "RenderProcess.h" +#include "RenderConfig.h" + +#include MainModelerWindow::MainModelerWindow() { @@ -12,8 +17,13 @@ MainModelerWindow::MainModelerWindow() scenery->autoPreset(); renderer = new OpenGLRenderer(scenery); - qmlRegisterType("Paysages", 1, 0, "OpenGLView"); + render_preview_provider = new RenderPreviewProvider(); + render_process = new RenderProcess(render_preview_provider); + qmlRegisterType("Paysages", 1, 0, "OpenGLView"); + engine()->addImageProvider("renderpreviewprovider", render_preview_provider); + + setMinimumSize(QSize(1000, 800)); setTitle(QObject::tr("Paysages 3D")); setResizeMode(QQuickView::SizeRootObjectToView); setSource(QUrl("qrc:///main.qml")); @@ -27,6 +37,9 @@ MainModelerWindow::~MainModelerWindow() delete atmosphere; delete water; + delete render_preview_provider; + delete render_process; + delete renderer; delete scenery; } @@ -35,3 +48,26 @@ QObject *MainModelerWindow::findQmlObject(const QString &objectName) { return rootObject()->findChild(objectName); } + +void MainModelerWindow::keyReleaseEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_F5) + { + // Start render in a thread + render_process->startRender(scenery, RenderConfig(400, 300, 1, 3)); + + // Resize preview + QSize preview_size = render_process->getPreviewSize(); + findQmlObject("preview_image")->setProperty("width", preview_size.width()); + findQmlObject("preview_image")->setProperty("height", preview_size.height()); + + // Show render dialog + rootObject()->setProperty("state", QString("Render Dialog")); + } + else if (event->key() == Qt::Key_Escape) + { + render_process->stopRender(); + + rootObject()->setProperty("state", QString("Init")); + } +} diff --git a/src/interface/modeler/quickapp/MainModelerWindow.h b/src/interface/modeler/quickapp/MainModelerWindow.h index 5d7b5f2..bc159c2 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.h +++ b/src/interface/modeler/quickapp/MainModelerWindow.h @@ -20,12 +20,18 @@ public: inline Scenery *getScenery() const {return scenery;} inline OpenGLRenderer *getRenderer() const {return renderer;} +protected: + virtual void keyReleaseEvent(QKeyEvent *event) override; + private: OpenGLRenderer *renderer; Scenery *scenery; AtmosphereModeler *atmosphere; WaterModeler *water; + + RenderPreviewProvider *render_preview_provider; + RenderProcess *render_process; }; } diff --git a/src/interface/modeler/quickapp/RenderPreviewProvider.cpp b/src/interface/modeler/quickapp/RenderPreviewProvider.cpp new file mode 100644 index 0000000..b6b5151 --- /dev/null +++ b/src/interface/modeler/quickapp/RenderPreviewProvider.cpp @@ -0,0 +1,85 @@ +#include "RenderPreviewProvider.h" + +#include "Canvas.h" +#include "CanvasPreview.h" +#include "Color.h" + +static inline QColor colorToQColor(Color color) +{ + color.normalize(); + return QColor(color.r * 255.0, color.g * 255.0, color.b * 255.0, color.a * 255.0); +} + +RenderPreviewProvider::RenderPreviewProvider() : + QQuickImageProvider(QQuickImageProvider::Image) +{ + canvas = NULL; + pixbuf = new QImage(1, 1, QImage::Format_ARGB32); +} + +RenderPreviewProvider::~RenderPreviewProvider() +{ + delete pixbuf; +} + +QImage RenderPreviewProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) +{ + if (canvas) + { + canvas->getPreview()->updateLive(this); + } + + if (size) + { + *size = pixbuf->size(); + } + + return *pixbuf; +} + +void RenderPreviewProvider::setCanvas(const Canvas *canvas) +{ + if (not this->canvas) + { + this->canvas = canvas; + canvas->getPreview()->initLive(this); + } +} + +void RenderPreviewProvider::releaseCanvas() +{ + if (canvas) + { + canvas->getPreview()->updateLive(this); + canvas = NULL; + } +} + +void RenderPreviewProvider::setToneMapping(const ColorProfile &profile) +{ + if (canvas) + { + canvas->getPreview()->setToneMapping(profile); + canvas->getPreview()->updateLive(this); + } +} + +void RenderPreviewProvider::canvasResized(int width, int height) +{ + if (QSize(width, height) != pixbuf->size()) + { + delete pixbuf; + pixbuf = new QImage(width, height, QImage::Format_ARGB32); + pixbuf->fill(Qt::black); + } +} + +void RenderPreviewProvider::canvasCleared(const Color &col) +{ + pixbuf->fill(colorToQColor(col)); +} + +void RenderPreviewProvider::canvasPainted(int x, int y, const Color &col) +{ + pixbuf->setPixel(x, pixbuf->height() - 1 - y, colorToQColor(col).rgb()); +} diff --git a/src/interface/modeler/quickapp/RenderPreviewProvider.h b/src/interface/modeler/quickapp/RenderPreviewProvider.h new file mode 100644 index 0000000..d11708c --- /dev/null +++ b/src/interface/modeler/quickapp/RenderPreviewProvider.h @@ -0,0 +1,53 @@ +#ifndef RENDERPREVIEWPROVIDER_H +#define RENDERPREVIEWPROVIDER_H + +#include "modeler_global.h" + +#include +#include "CanvasLiveClient.h" + +namespace paysages { +namespace modeler { + +/** + * Provider for a Qml Image content, filled from a canvas rendering. + */ +class RenderPreviewProvider : public QQuickImageProvider, public CanvasLiveClient +{ +public: + RenderPreviewProvider(); + virtual ~RenderPreviewProvider(); + + /** + * Set the canvas to watch and display, null to stop watching. + * + * This function must be called from the graphics thread. + */ + void setCanvas(const Canvas *canvas); + + /** + * Release the bound canvas. + */ + void releaseCanvas(); + + /** + * Set the tone mapping to apply to pixel colors. + */ + void setToneMapping(const ColorProfile &profile); + +protected: + virtual QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; + + virtual void canvasResized(int width, int height) override; + virtual void canvasCleared(const Color &col) override; + virtual void canvasPainted(int x, int y, const Color &col) override; + +private: + QImage* pixbuf; + const Canvas *canvas; +}; + +} +} + +#endif // RENDERPREVIEWPROVIDER_H diff --git a/src/interface/modeler/quickapp/RenderProcess.cpp b/src/interface/modeler/quickapp/RenderProcess.cpp new file mode 100644 index 0000000..4a8589a --- /dev/null +++ b/src/interface/modeler/quickapp/RenderProcess.cpp @@ -0,0 +1,111 @@ +#include "RenderProcess.h" + +#include +#include "SoftwareCanvasRenderer.h" +#include "RenderPreviewProvider.h" +#include "RenderConfig.h" +#include "Thread.h" +#include "Canvas.h" +#include "CanvasPreview.h" + +class RenderThread: public Thread +{ +public: + RenderThread(SoftwareCanvasRenderer *renderer): renderer(renderer) + { + } + virtual void run() override + { + renderer->render(); + } +private: + SoftwareCanvasRenderer *renderer; +}; + +RenderProcess::RenderProcess(RenderPreviewProvider *destination): + destination(destination) +{ + rendering = false; + renderer = NULL; + render_thread = NULL; + + startTimer(100); +} + +RenderProcess::~RenderProcess() +{ + if (rendering) + { + renderer->interrupt(); + } + + rendering = false; + + if (render_thread) + { + render_thread->join(); + delete render_thread; + } + + if (renderer) + { + delete renderer; + } +} + +void RenderProcess::startRender(Scenery *scenery, const RenderConfig &config) +{ + if (rendering) + { + return; + } + + rendering = true; + + if (renderer) + { + delete renderer; + } + + renderer = new SoftwareCanvasRenderer(); + renderer->setScenery(scenery); + renderer->setConfig(config); + + destination->setCanvas(renderer->getCanvas()); + + render_thread = new RenderThread(renderer); + render_thread->start(); +} + +void RenderProcess::stopRender() +{ + if (rendering) + { + renderer->interrupt(); + } +} + +const QSize RenderProcess::getPreviewSize() +{ + if (renderer) + { + return QSize(renderer->getCanvas()->getPreview()->getWidth(), renderer->getCanvas()->getPreview()->getHeight()); + } + else + { + return QSize(10, 10); + } +} + +void RenderProcess::timerEvent(QTimerEvent *) +{ + if (rendering and renderer->isFinished()) + { + destination->releaseCanvas(); + rendering = false; + + render_thread->join(); + delete render_thread; + render_thread = NULL; + } +} diff --git a/src/interface/modeler/quickapp/RenderProcess.h b/src/interface/modeler/quickapp/RenderProcess.h new file mode 100644 index 0000000..366eb51 --- /dev/null +++ b/src/interface/modeler/quickapp/RenderProcess.h @@ -0,0 +1,47 @@ +#ifndef RENDERPROCESS_H +#define RENDERPROCESS_H + +#include "modeler_global.h" + +#include + +namespace paysages { +namespace modeler { + +class RenderProcess: public QObject +{ + Q_OBJECT + +public: + RenderProcess(RenderPreviewProvider *destination); + virtual ~RenderProcess(); + + /** + * Start the rendering process in a separate thread. + */ + void startRender(Scenery *scenery, const RenderConfig &config); + + /** + * Stop any currently running render. + */ + void stopRender(); + + /** + * Get the size of the preview image. + */ + const QSize getPreviewSize(); + +protected: + virtual void timerEvent(QTimerEvent *event) override; + +private: + RenderPreviewProvider *destination; + bool rendering; + SoftwareCanvasRenderer *renderer; + Thread *render_thread; +}; + +} +} + +#endif // RENDERPROCESS_H diff --git a/src/interface/modeler/quickapp/modeler_global.h b/src/interface/modeler/quickapp/modeler_global.h index d2be172..d2749ac 100644 --- a/src/interface/modeler/quickapp/modeler_global.h +++ b/src/interface/modeler/quickapp/modeler_global.h @@ -12,6 +12,9 @@ namespace modeler { class AtmosphereModeler; class WaterModeler; + + class RenderPreviewProvider; + class RenderProcess; } } diff --git a/src/interface/modeler/quickapp/qml/RenderDialog.qml b/src/interface/modeler/quickapp/qml/RenderDialog.qml new file mode 100644 index 0000000..7f465ad --- /dev/null +++ b/src/interface/modeler/quickapp/qml/RenderDialog.qml @@ -0,0 +1,27 @@ +import QtQuick 2.2 + +Rectangle { + width: 400 + height: 300 + + Image { + id: preview_image + objectName: "preview_image" + anchors.centerIn: parent + width: 100 + height: 100 + source: "" + cache: false + } + + Timer { + interval: 500 + running: true + repeat: true + + onTriggered: { + preview_image.source = ""; + preview_image.source = "image://renderpreviewprovider/live"; + } + } +} diff --git a/src/interface/modeler/quickapp/qml/app.qrc b/src/interface/modeler/quickapp/qml/app.qrc index 3c32d54..6abd781 100644 --- a/src/interface/modeler/quickapp/qml/app.qrc +++ b/src/interface/modeler/quickapp/qml/app.qrc @@ -25,5 +25,6 @@ images/icon_atmosphere_night.png BaseChoice.qml BaseChoiceItem.qml + RenderDialog.qml diff --git a/src/interface/modeler/quickapp/qml/main.qml b/src/interface/modeler/quickapp/qml/main.qml index 422f7ca..38048fd 100644 --- a/src/interface/modeler/quickapp/qml/main.qml +++ b/src/interface/modeler/quickapp/qml/main.qml @@ -91,6 +91,12 @@ OpenGLView { } } + RenderDialog { + id: render_dialog + opacity: 0 + anchors.fill: parent + } + PanelWaterLevel { id: panel_water_level tool: tool_water_level @@ -127,6 +133,19 @@ OpenGLView { target: atmosphere_toolbar opacity: 1 } + }, + State { + name: "Render Dialog" + when: tool_display.selected + + PropertyChanges { + target: primary_toolbar + opacity: 0 + } + PropertyChanges { + target: render_dialog + opacity: 1 + } } ] diff --git a/src/interface/modeler/quickapp/quickapp.pro b/src/interface/modeler/quickapp/quickapp.pro index d1502b4..989f285 100644 --- a/src/interface/modeler/quickapp/quickapp.pro +++ b/src/interface/modeler/quickapp/quickapp.pro @@ -8,7 +8,9 @@ SOURCES += main.cpp \ OpenGLView.cpp \ MainModelerWindow.cpp \ WaterModeler.cpp \ - AtmosphereModeler.cpp + AtmosphereModeler.cpp \ + RenderPreviewProvider.cpp \ + RenderProcess.cpp RESOURCES += \ qml/app.qrc @@ -26,7 +28,9 @@ HEADERS += \ modeler_global.h \ MainModelerWindow.h \ WaterModeler.h \ - AtmosphereModeler.h + AtmosphereModeler.h \ + RenderPreviewProvider.h \ + RenderProcess.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 @@ -69,4 +73,5 @@ OTHER_FILES += \ qml/PanelAtmosphereDaytime.qml \ qml/BaseSlider.qml \ qml/BaseChoice.qml \ - qml/BaseChoiceItem.qml + qml/BaseChoiceItem.qml \ + qml/RenderDialog.qml diff --git a/src/render/software/SoftwareCanvasRenderer.cpp b/src/render/software/SoftwareCanvasRenderer.cpp index 922b12d..edc48d0 100644 --- a/src/render/software/SoftwareCanvasRenderer.cpp +++ b/src/render/software/SoftwareCanvasRenderer.cpp @@ -17,6 +17,7 @@ SoftwareCanvasRenderer::SoftwareCanvasRenderer() { started = false; + finished = false; interrupted = false; canvas = new Canvas(); progress = 0.0; @@ -95,6 +96,7 @@ void SoftwareCanvasRenderer::render() progress = (double)i / (double)n; } } + finished = true; } void SoftwareCanvasRenderer::interrupt() diff --git a/src/render/software/SoftwareCanvasRenderer.h b/src/render/software/SoftwareCanvasRenderer.h index e157248..605a138 100644 --- a/src/render/software/SoftwareCanvasRenderer.h +++ b/src/render/software/SoftwareCanvasRenderer.h @@ -24,6 +24,7 @@ public: inline const Canvas *getCanvas() const {return canvas;} inline double getProgress() const {return progress;} + inline bool isFinished() const {return finished;} /** * Set the renderer configuration. @@ -78,6 +79,7 @@ private: int samples; std::vector rasterizers; bool started; + bool finished; bool interrupted; ParallelWork *current_work; From 57b90af13266eb18a8f21ad4b8a83c6d457df247 Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Thu, 18 Sep 2014 17:38:37 +0200 Subject: [PATCH 10/13] Added progressive camera change to opengl view --- .../modeler/quickapp/MainModelerWindow.cpp | 3 ++ .../modeler/quickapp/MainModelerWindow.h | 2 + .../modeler/quickapp/ModelerCameras.cpp | 53 +++++++++++++++++++ .../modeler/quickapp/ModelerCameras.h | 39 ++++++++++++++ src/interface/modeler/quickapp/OpenGLView.cpp | 6 +-- .../modeler/quickapp/modeler_global.h | 2 + .../modeler/quickapp/qml/CameraChoice.qml | 39 ++++++++++++++ src/interface/modeler/quickapp/qml/app.qrc | 1 + src/interface/modeler/quickapp/qml/main.qml | 6 +++ src/interface/modeler/quickapp/quickapp.pro | 9 ++-- src/render/opengl/OpenGLRenderer.cpp | 8 +++ src/render/opengl/OpenGLRenderer.h | 6 +++ 12 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 src/interface/modeler/quickapp/ModelerCameras.cpp create mode 100644 src/interface/modeler/quickapp/ModelerCameras.h create mode 100644 src/interface/modeler/quickapp/qml/CameraChoice.qml diff --git a/src/interface/modeler/quickapp/MainModelerWindow.cpp b/src/interface/modeler/quickapp/MainModelerWindow.cpp index c82ceaf..c21b459 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.cpp +++ b/src/interface/modeler/quickapp/MainModelerWindow.cpp @@ -5,6 +5,7 @@ #include "OpenGLRenderer.h" #include "AtmosphereModeler.h" #include "WaterModeler.h" +#include "ModelerCameras.h" #include "RenderPreviewProvider.h" #include "RenderProcess.h" #include "RenderConfig.h" @@ -28,6 +29,7 @@ MainModelerWindow::MainModelerWindow() setResizeMode(QQuickView::SizeRootObjectToView); setSource(QUrl("qrc:///main.qml")); + cameras = new ModelerCameras(this); atmosphere = new AtmosphereModeler(this); water = new WaterModeler(this); } @@ -36,6 +38,7 @@ MainModelerWindow::~MainModelerWindow() { delete atmosphere; delete water; + delete cameras; delete render_preview_provider; delete render_process; diff --git a/src/interface/modeler/quickapp/MainModelerWindow.h b/src/interface/modeler/quickapp/MainModelerWindow.h index bc159c2..841d230 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.h +++ b/src/interface/modeler/quickapp/MainModelerWindow.h @@ -30,6 +30,8 @@ private: AtmosphereModeler *atmosphere; WaterModeler *water; + ModelerCameras *cameras; + RenderPreviewProvider *render_preview_provider; RenderProcess *render_process; }; diff --git a/src/interface/modeler/quickapp/ModelerCameras.cpp b/src/interface/modeler/quickapp/ModelerCameras.cpp new file mode 100644 index 0000000..90ecc47 --- /dev/null +++ b/src/interface/modeler/quickapp/ModelerCameras.cpp @@ -0,0 +1,53 @@ +#include "ModelerCameras.h" + +#include "MainModelerWindow.h" +#include "OpenGLRenderer.h" +#include "Scenery.h" +#include "CameraDefinition.h" + +ModelerCameras::ModelerCameras(MainModelerWindow *parent): + QObject(parent), parent(parent) +{ + render = new CameraDefinition(); + topdown = new CameraDefinition(); + current = new CameraDefinition(); + active = render; + + topdown->strafeForward(-10.0); + topdown->strafeUp(25.0); + topdown->rotatePitch(-0.8); + + // Watch GUI choice + QObject *widget = parent->findQmlObject("camera_choice"); + connect(widget, SIGNAL(stateChanged(QString)), this, SLOT(changeActiveCamera(QString))); + + // Start update timer + startTimer(50); +} + +ModelerCameras::~ModelerCameras() +{ + delete current; + delete render; + delete topdown; +} + +void ModelerCameras::timerEvent(QTimerEvent *) +{ + OpenGLRenderer *renderer = parent->getRenderer(); + + current->transitionToAnother(active, 0.1); + renderer->setCamera(current); +} + +void ModelerCameras::changeActiveCamera(const QString &name) +{ + if (name == "Render camera") + { + active = render; + } + else if (name == "Top-down camera") + { + active = topdown; + } +} diff --git a/src/interface/modeler/quickapp/ModelerCameras.h b/src/interface/modeler/quickapp/ModelerCameras.h new file mode 100644 index 0000000..dffaf81 --- /dev/null +++ b/src/interface/modeler/quickapp/ModelerCameras.h @@ -0,0 +1,39 @@ +#ifndef MODELERCAMERAS_H +#define MODELERCAMERAS_H + +#include "modeler_global.h" + +#include + +namespace paysages { +namespace modeler { + +/** + * Storage for modeler cameras. + */ +class ModelerCameras: public QObject +{ + Q_OBJECT + +public: + ModelerCameras(MainModelerWindow *parent); + ~ModelerCameras(); + +protected: + void timerEvent(QTimerEvent *event); + +public slots: + void changeActiveCamera(const QString &name); + +private: + MainModelerWindow *parent; + CameraDefinition *active; + CameraDefinition *current; + CameraDefinition *render; + CameraDefinition *topdown; +}; + +} +} + +#endif // MODELERCAMERAS_H diff --git a/src/interface/modeler/quickapp/OpenGLView.cpp b/src/interface/modeler/quickapp/OpenGLView.cpp index 23f0211..6d8c960 100644 --- a/src/interface/modeler/quickapp/OpenGLView.cpp +++ b/src/interface/modeler/quickapp/OpenGLView.cpp @@ -19,7 +19,7 @@ OpenGLView::OpenGLView(QQuickItem *parent) : setKeepMouseGrab(true); connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); - startTimer(250); + startTimer(50); } void OpenGLView::handleWindowChanged(QQuickWindow *win) @@ -65,7 +65,7 @@ void OpenGLView::hoverMoveEvent(QHoverEvent *event) return; } - CameraDefinition camera; + /*CameraDefinition camera; renderer->getScenery()->getCamera(&camera); QPointF diff = event->posF() - event->oldPosF(); @@ -80,7 +80,7 @@ void OpenGLView::hoverMoveEvent(QHoverEvent *event) if (window) { window->update(); - } + }*/ } void OpenGLView::timerEvent(QTimerEvent *) diff --git a/src/interface/modeler/quickapp/modeler_global.h b/src/interface/modeler/quickapp/modeler_global.h index d2749ac..135e12b 100644 --- a/src/interface/modeler/quickapp/modeler_global.h +++ b/src/interface/modeler/quickapp/modeler_global.h @@ -15,6 +15,8 @@ namespace modeler { class RenderPreviewProvider; class RenderProcess; + + class ModelerCameras; } } diff --git a/src/interface/modeler/quickapp/qml/CameraChoice.qml b/src/interface/modeler/quickapp/qml/CameraChoice.qml new file mode 100644 index 0000000..8df3ae4 --- /dev/null +++ b/src/interface/modeler/quickapp/qml/CameraChoice.qml @@ -0,0 +1,39 @@ +import QtQuick 2.0 + +Rectangle { + id: camera_choice + width: 200 + height: 50 + 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("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") + } + } + + states: [ + State { + name: "Render camera" + when: camera_choice_render.selected + }, + State { + name: "Top-down camera" + when: camera_choice_topdown.selected + } + ] +} diff --git a/src/interface/modeler/quickapp/qml/app.qrc b/src/interface/modeler/quickapp/qml/app.qrc index 6abd781..dc6d8a4 100644 --- a/src/interface/modeler/quickapp/qml/app.qrc +++ b/src/interface/modeler/quickapp/qml/app.qrc @@ -26,5 +26,6 @@ BaseChoice.qml BaseChoiceItem.qml RenderDialog.qml + CameraChoice.qml diff --git a/src/interface/modeler/quickapp/qml/main.qml b/src/interface/modeler/quickapp/qml/main.qml index 38048fd..bc18a73 100644 --- a/src/interface/modeler/quickapp/qml/main.qml +++ b/src/interface/modeler/quickapp/qml/main.qml @@ -91,6 +91,12 @@ OpenGLView { } } + CameraChoice { + id: camera_choice + anchors.bottom: main_ui.bottom + anchors.horizontalCenter: main_ui.horizontalCenter + } + RenderDialog { id: render_dialog opacity: 0 diff --git a/src/interface/modeler/quickapp/quickapp.pro b/src/interface/modeler/quickapp/quickapp.pro index 989f285..9257aecc 100644 --- a/src/interface/modeler/quickapp/quickapp.pro +++ b/src/interface/modeler/quickapp/quickapp.pro @@ -10,7 +10,8 @@ SOURCES += main.cpp \ WaterModeler.cpp \ AtmosphereModeler.cpp \ RenderPreviewProvider.cpp \ - RenderProcess.cpp + RenderProcess.cpp \ + ModelerCameras.cpp RESOURCES += \ qml/app.qrc @@ -30,7 +31,8 @@ HEADERS += \ WaterModeler.h \ AtmosphereModeler.h \ RenderPreviewProvider.h \ - RenderProcess.h + RenderProcess.h \ + ModelerCameras.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 @@ -74,4 +76,5 @@ OTHER_FILES += \ qml/BaseSlider.qml \ qml/BaseChoice.qml \ qml/BaseChoiceItem.qml \ - qml/RenderDialog.qml + qml/RenderDialog.qml \ + qml/CameraChoice.qml diff --git a/src/render/opengl/OpenGLRenderer.cpp b/src/render/opengl/OpenGLRenderer.cpp index 1361795..00a80bb 100644 --- a/src/render/opengl/OpenGLRenderer.cpp +++ b/src/render/opengl/OpenGLRenderer.cpp @@ -106,6 +106,14 @@ void OpenGLRenderer::prepareOpenGLState() } } +void OpenGLRenderer::setCamera(CameraDefinition *camera) +{ + camera->copy(render_camera); + getScenery()->setCamera(camera); + getScenery()->getCamera(camera); + cameraChangeEvent(camera); +} + void OpenGLRenderer::resize(int width, int height) { vp_width = width; diff --git a/src/render/opengl/OpenGLRenderer.h b/src/render/opengl/OpenGLRenderer.h index 57ef059..9954d5e 100644 --- a/src/render/opengl/OpenGLRenderer.h +++ b/src/render/opengl/OpenGLRenderer.h @@ -26,6 +26,12 @@ public: void resize(int width, int height); void paint(); + /** + * Change the camera location. + * + * This may change the camera passed as argument (to stay above ground for example). + */ + void setCamera(CameraDefinition *camera); void cameraChangeEvent(CameraDefinition* camera); inline OpenGLFunctions* getOpenGlFunctions() const {return functions;} From 1cc3a4d625eab744839df08b0ada3eb21017bc48 Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Fri, 26 Sep 2014 17:46:39 +0200 Subject: [PATCH 11/13] quick ui : Added basic camera controls --- .../modeler/quickapp/MainModelerWindow.h | 1 + .../modeler/quickapp/ModelerCameras.cpp | 13 ++++- .../modeler/quickapp/ModelerCameras.h | 10 ++++ src/interface/modeler/quickapp/OpenGLView.cpp | 50 +++++++++---------- src/interface/modeler/quickapp/OpenGLView.h | 8 ++- 5 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/interface/modeler/quickapp/MainModelerWindow.h b/src/interface/modeler/quickapp/MainModelerWindow.h index 841d230..da676d9 100644 --- a/src/interface/modeler/quickapp/MainModelerWindow.h +++ b/src/interface/modeler/quickapp/MainModelerWindow.h @@ -19,6 +19,7 @@ public: inline Scenery *getScenery() const {return scenery;} inline OpenGLRenderer *getRenderer() const {return renderer;} + inline ModelerCameras *getCamera() const {return cameras;} protected: virtual void keyReleaseEvent(QKeyEvent *event) override; diff --git a/src/interface/modeler/quickapp/ModelerCameras.cpp b/src/interface/modeler/quickapp/ModelerCameras.cpp index 90ecc47..8e4104f 100644 --- a/src/interface/modeler/quickapp/ModelerCameras.cpp +++ b/src/interface/modeler/quickapp/ModelerCameras.cpp @@ -32,11 +32,22 @@ ModelerCameras::~ModelerCameras() delete topdown; } +void ModelerCameras::processZoom(double value) +{ + active->strafeForward(value); +} + +void ModelerCameras::processScroll(double xvalue, double yvalue) +{ + active->strafeRight(xvalue); + active->strafeUp(yvalue); +} + void ModelerCameras::timerEvent(QTimerEvent *) { OpenGLRenderer *renderer = parent->getRenderer(); - current->transitionToAnother(active, 0.1); + current->transitionToAnother(active, 0.3); renderer->setCamera(current); } diff --git a/src/interface/modeler/quickapp/ModelerCameras.h b/src/interface/modeler/quickapp/ModelerCameras.h index dffaf81..5621203 100644 --- a/src/interface/modeler/quickapp/ModelerCameras.h +++ b/src/interface/modeler/quickapp/ModelerCameras.h @@ -19,6 +19,16 @@ public: ModelerCameras(MainModelerWindow *parent); ~ModelerCameras(); + /** + * Process a zoom request. + */ + void processZoom(double value); + + /** + * Process a scroll request. + */ + void processScroll(double xvalue, double yvalue); + protected: void timerEvent(QTimerEvent *event); diff --git a/src/interface/modeler/quickapp/OpenGLView.cpp b/src/interface/modeler/quickapp/OpenGLView.cpp index 6d8c960..ad3a12b 100644 --- a/src/interface/modeler/quickapp/OpenGLView.cpp +++ b/src/interface/modeler/quickapp/OpenGLView.cpp @@ -3,9 +3,8 @@ #include #include #include "MainModelerWindow.h" -#include "CameraDefinition.h" #include "OpenGLRenderer.h" -#include "Scenery.h" +#include "ModelerCameras.h" OpenGLView::OpenGLView(QQuickItem *parent) : QQuickItem(parent) @@ -15,8 +14,8 @@ OpenGLView::OpenGLView(QQuickItem *parent) : renderer = NULL; setAcceptedMouseButtons(Qt::AllButtons); - setAcceptHoverEvents(true); - setKeepMouseGrab(true); + + mouse_button = Qt::NoButton; connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); startTimer(50); @@ -42,7 +41,7 @@ void OpenGLView::handleWindowChanged(QQuickWindow *win) void OpenGLView::paint() { - if (not initialized) + if (not initialized or not renderer) { renderer->initialize(); initialized = true; @@ -58,29 +57,30 @@ void OpenGLView::paint() } } -void OpenGLView::hoverMoveEvent(QHoverEvent *event) +void OpenGLView::wheelEvent(QWheelEvent *event) { - if (!renderer) + window->getCamera()->processZoom(0.1 * (double)event->angleDelta().y()); +} + +void OpenGLView::mousePressEvent(QMouseEvent *event) +{ + mouse_button = event->button(); + mouse_pos = event->windowPos(); +} + +void OpenGLView::mouseReleaseEvent(QMouseEvent *) +{ + mouse_button = Qt::NoButton; +} + +void OpenGLView::mouseMoveEvent(QMouseEvent *event) +{ + QPointF diff = event->windowPos() - mouse_pos; + if (mouse_button == Qt::MidButton) { - return; + window->getCamera()->processScroll(-0.1 * diff.x(), 0.1 * diff.y()); } - - /*CameraDefinition camera; - renderer->getScenery()->getCamera(&camera); - - QPointF diff = event->posF() - event->oldPosF(); - camera.strafeRight(diff.x() * 0.1); - camera.strafeUp(diff.y() * 0.1); - camera.validate(); - - camera.copy(renderer->render_camera); - renderer->getScenery()->setCamera(&camera); - renderer->getScenery()->getCamera(&camera); - renderer->cameraChangeEvent(&camera); - if (window) - { - window->update(); - }*/ + mouse_pos = event->windowPos(); } void OpenGLView::timerEvent(QTimerEvent *) diff --git a/src/interface/modeler/quickapp/OpenGLView.h b/src/interface/modeler/quickapp/OpenGLView.h index e59c379..31fcc5c 100644 --- a/src/interface/modeler/quickapp/OpenGLView.h +++ b/src/interface/modeler/quickapp/OpenGLView.h @@ -19,13 +19,19 @@ public slots: void paint(); protected: - virtual void hoverMoveEvent(QHoverEvent *event) override; + virtual void wheelEvent(QWheelEvent *event) override; + virtual void mousePressEvent(QMouseEvent *event) override; + virtual void mouseReleaseEvent(QMouseEvent *event) override; + virtual void mouseMoveEvent(QMouseEvent *event) override; virtual void timerEvent(QTimerEvent *event) override; private: bool initialized; MainModelerWindow *window; OpenGLRenderer *renderer; + + Qt::MouseButton mouse_button; + QPointF mouse_pos; }; } From f7715b612e884c6b2d16aa98c936f826c7a788b1 Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Fri, 21 Nov 2014 09:45:19 +0100 Subject: [PATCH 12/13] Changed some old int-bools to true booleans --- src/definition/Scenery.cpp | 2 +- src/definition/TerrainDefinition.cpp | 4 ++-- src/definition/TerrainDefinition.h | 4 ++-- .../desktop/terrain/paintingbrush.cpp | 2 +- .../desktop/terrain/widgetheightmap.cpp | 2 +- src/render/opengl/ExplorerChunkTerrain.cpp | 2 +- .../preview/SceneryTopDownPreviewRenderer.cpp | 2 +- .../preview/TerrainShapePreviewRenderer.cpp | 2 +- .../TextureLayerCoveragePreviewRenderer.cpp | 2 +- .../preview/TexturesMixPreviewRenderer.cpp | 2 +- src/render/software/TerrainRasterizer.cpp | 24 +++++++++---------- src/render/software/TerrainRasterizer.h | 2 +- src/render/software/TerrainRenderer.cpp | 6 ++--- src/render/software/TerrainRenderer.h | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/definition/Scenery.cpp b/src/definition/Scenery.cpp index 1515b9e..7ced63c 100644 --- a/src/definition/Scenery.cpp +++ b/src/definition/Scenery.cpp @@ -182,7 +182,7 @@ void Scenery::getWater(WaterDefinition* water) void Scenery::checkCameraAboveGround() { Vector3 camera_location = camera->getLocation(); - double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, 1, 1) + 2.0; + double terrain_height = terrain->getInterpolatedHeight(camera_location.x, camera_location.z, true, true) + 2.0; double water_height = 1.5; if (camera_location.y < water_height || camera_location.y < terrain_height) { diff --git a/src/definition/TerrainDefinition.cpp b/src/definition/TerrainDefinition.cpp index 8ec30a3..45c5a18 100644 --- a/src/definition/TerrainDefinition.cpp +++ b/src/definition/TerrainDefinition.cpp @@ -82,7 +82,7 @@ void TerrainDefinition::load(PackStream* stream) validate(); } -double TerrainDefinition::getGridHeight(int x, int z, int with_painting) +double TerrainDefinition::getGridHeight(int x, int z, bool with_painting) { double h; @@ -94,7 +94,7 @@ double TerrainDefinition::getGridHeight(int x, int z, int with_painting) return h; } -double TerrainDefinition::getInterpolatedHeight(double x, double z, int scaled, int with_painting) +double TerrainDefinition::getInterpolatedHeight(double x, double z, bool scaled, bool with_painting) { double h; x /= scaling; diff --git a/src/definition/TerrainDefinition.h b/src/definition/TerrainDefinition.h index 560c7f0..c67fac7 100644 --- a/src/definition/TerrainDefinition.h +++ b/src/definition/TerrainDefinition.h @@ -27,8 +27,8 @@ public: virtual void copy(BaseDefinition* destination) const override; virtual void validate() override; - double getGridHeight(int x, int z, int with_painting); - double getInterpolatedHeight(double x, double z, int scaled, int with_painting); + double getGridHeight(int x, int z, bool with_painting); + double getInterpolatedHeight(double x, double z, bool scaled, bool with_painting); unsigned long getMemoryStats(); HeightInfo getHeightInfo(); diff --git a/src/interface/desktop/terrain/paintingbrush.cpp b/src/interface/desktop/terrain/paintingbrush.cpp index a6e8c7c..3ab10df 100644 --- a/src/interface/desktop/terrain/paintingbrush.cpp +++ b/src/interface/desktop/terrain/paintingbrush.cpp @@ -135,7 +135,7 @@ void PaintingBrush::applyToTerrain(TerrainDefinition* terrain, double x, double case PAINTING_BRUSH_FLATTEN: if (reverse) { - _height = terrain->getInterpolatedHeight(x * terrain->scaling, z * terrain->scaling, 0, 1); + _height = terrain->getInterpolatedHeight(x * terrain->scaling, z * terrain->scaling, false, true); } else { diff --git a/src/interface/desktop/terrain/widgetheightmap.cpp b/src/interface/desktop/terrain/widgetheightmap.cpp index 5d26e7f..a115012 100644 --- a/src/interface/desktop/terrain/widgetheightmap.cpp +++ b/src/interface/desktop/terrain/widgetheightmap.cpp @@ -218,7 +218,7 @@ void WidgetHeightMap::timerEvent(QTimerEvent*) _last_time = new_time; // Update top camera - Vector3 target = {_target_x, _terrain->getInterpolatedHeight(_target_x, _target_z, 1, 1), _target_z}; + Vector3 target = {_target_x, _terrain->getInterpolatedHeight(_target_x, _target_z, true, true), _target_z}; _top_camera->setLocationCoords(target.x, target.y + 1.0, target.z + 0.1); _top_camera->setTarget(target); _top_camera->setZoomToTarget(_zoom); diff --git a/src/render/opengl/ExplorerChunkTerrain.cpp b/src/render/opengl/ExplorerChunkTerrain.cpp index 3310814..9e9636f 100644 --- a/src/render/opengl/ExplorerChunkTerrain.cpp +++ b/src/render/opengl/ExplorerChunkTerrain.cpp @@ -85,7 +85,7 @@ bool ExplorerChunkTerrain::maintain() double x = _startx + _tessellation_step * (float)i; double z = _startz + _tessellation_step * (float)j; - double height = _renderer->getTerrainRenderer()->getHeight(x, z, 1); + double height = _renderer->getTerrainRenderer()->getHeight(x, z, true); if (height >= _water_height) { overwater = true; diff --git a/src/render/preview/SceneryTopDownPreviewRenderer.cpp b/src/render/preview/SceneryTopDownPreviewRenderer.cpp index 62199b2..a5b71a6 100644 --- a/src/render/preview/SceneryTopDownPreviewRenderer.cpp +++ b/src/render/preview/SceneryTopDownPreviewRenderer.cpp @@ -46,7 +46,7 @@ void SceneryTopDownPreviewRenderer::updateEvent() Color SceneryTopDownPreviewRenderer::getColor2D(double x, double y, double scaling) { Vector3 location; - double height = getTerrainRenderer()->getHeight(x, y, 1); + double height = getTerrainRenderer()->getHeight(x, y, true); if (height < getWaterRenderer()->getHeightInfo().max_height) { diff --git a/src/render/preview/TerrainShapePreviewRenderer.cpp b/src/render/preview/TerrainShapePreviewRenderer.cpp index f053550..9e5c940 100644 --- a/src/render/preview/TerrainShapePreviewRenderer.cpp +++ b/src/render/preview/TerrainShapePreviewRenderer.cpp @@ -57,7 +57,7 @@ Color TerrainShapePreviewRenderer::getColor2D(double x, double y, double scaling { double height; - height = getTerrainRenderer()->getHeight(x, y, 1); + height = getTerrainRenderer()->getHeight(x, y, true); if (height > 0.0) { return getTerrainRenderer()->getFinalColor(Vector3(x, height, y), 0.000001); diff --git a/src/render/preview/TextureLayerCoveragePreviewRenderer.cpp b/src/render/preview/TextureLayerCoveragePreviewRenderer.cpp index 305a422..217b62b 100644 --- a/src/render/preview/TextureLayerCoveragePreviewRenderer.cpp +++ b/src/render/preview/TextureLayerCoveragePreviewRenderer.cpp @@ -53,7 +53,7 @@ Color TextureLayerCoveragePreviewRenderer::getColor2D(double x, double y, double TexturesRenderer* textures_renderer = getTexturesRenderer(); TerrainRenderer* terrain_renderer = getTerrainRenderer(); - double presence = textures_renderer->getBasePresence(layer, terrain_renderer->getResult(x, y, 1, 0)); + double presence = textures_renderer->getBasePresence(layer, terrain_renderer->getResult(x, y, true, false)); return Color(presence, presence, presence); } diff --git a/src/render/preview/TexturesMixPreviewRenderer.cpp b/src/render/preview/TexturesMixPreviewRenderer.cpp index a030da8..9802c4d 100644 --- a/src/render/preview/TexturesMixPreviewRenderer.cpp +++ b/src/render/preview/TexturesMixPreviewRenderer.cpp @@ -53,6 +53,6 @@ void TexturesMixPreviewRenderer::updateEvent() Color TexturesMixPreviewRenderer::getColor2D(double x, double y, double scaling) { TerrainRenderer* terrain_renderer = getTerrainRenderer(); - Vector3 location(x, terrain_renderer->getHeight(x, y, 1), y); + Vector3 location(x, terrain_renderer->getHeight(x, y, true), y); return terrain_renderer->getFinalColor(location, scaling); } diff --git a/src/render/software/TerrainRasterizer.cpp b/src/render/software/TerrainRasterizer.cpp index 14e7b55..f836dd3 100644 --- a/src/render/software/TerrainRasterizer.cpp +++ b/src/render/software/TerrainRasterizer.cpp @@ -17,7 +17,7 @@ TerrainRasterizer::TerrainRasterizer(SoftwareRenderer* renderer, int client_id): static inline Vector3 _getPoint(SoftwareRenderer* renderer, double x, double z) { - return Vector3(x, renderer->getTerrainRenderer()->getHeight(x, z, 1), z); + return Vector3(x, renderer->getTerrainRenderer()->getHeight(x, z, true), z); } void TerrainRasterizer::tessellateChunk(CanvasPortion* canvas, TerrainChunkInfo* chunk, int detail) @@ -52,19 +52,19 @@ void TerrainRasterizer::renderQuad(CanvasPortion *canvas, double x, double z, do ov1.x = x; ov1.z = z; - dv1 = renderer->getTerrainRenderer()->getResult(x, z, 1, 1).location; + dv1 = renderer->getTerrainRenderer()->getResult(x, z, true, true).location; ov2.x = x; ov2.z = z + size; - dv2 = renderer->getTerrainRenderer()->getResult(x, z + size, 1, 1).location; + dv2 = renderer->getTerrainRenderer()->getResult(x, z + size, true, true).location; ov3.x = x + size; ov3.z = z + size; - dv3 = renderer->getTerrainRenderer()->getResult(x + size, z + size, 1, 1).location; + dv3 = renderer->getTerrainRenderer()->getResult(x + size, z + size, true, true).location; ov4.x = x + size; ov4.z = z; - dv4 = renderer->getTerrainRenderer()->getResult(x + size, z, 1, 1).location; + dv4 = renderer->getTerrainRenderer()->getResult(x + size, z, true, true).location; if (dv1.y > water_height || dv2.y > water_height || dv3.y > water_height || dv4.y > water_height) { @@ -72,12 +72,12 @@ void TerrainRasterizer::renderQuad(CanvasPortion *canvas, double x, double z, do } } -static void _getChunk(SoftwareRenderer* renderer, TerrainRasterizer::TerrainChunkInfo* chunk, double x, double z, double size, int displaced) +static void _getChunk(SoftwareRenderer* renderer, TerrainRasterizer::TerrainChunkInfo* chunk, double x, double z, double size, bool displaced) { - chunk->point_nw = renderer->getTerrainRenderer()->getResult(x, z, 1, displaced).location; - chunk->point_sw = renderer->getTerrainRenderer()->getResult(x, z + size, 1, displaced).location; - chunk->point_se = renderer->getTerrainRenderer()->getResult(x + size, z + size, 1, displaced).location; - chunk->point_ne = renderer->getTerrainRenderer()->getResult(x + size, z, 1, displaced).location; + chunk->point_nw = renderer->getTerrainRenderer()->getResult(x, z, true, displaced).location; + chunk->point_sw = renderer->getTerrainRenderer()->getResult(x, z + size, true, displaced).location; + chunk->point_se = renderer->getTerrainRenderer()->getResult(x + size, z + size, true, displaced).location; + chunk->point_ne = renderer->getTerrainRenderer()->getResult(x + size, z, true, displaced).location; double displacement_power; if (displaced) @@ -125,7 +125,7 @@ static void _getChunk(SoftwareRenderer* renderer, TerrainRasterizer::TerrainChun } } -void TerrainRasterizer::getTessellationInfo(CanvasPortion* canvas, int displaced) +void TerrainRasterizer::getTessellationInfo(CanvasPortion* canvas, bool displaced) { TerrainChunkInfo chunk; int chunk_factor, chunk_count, i; @@ -199,7 +199,7 @@ void TerrainRasterizer::processChunk(CanvasPortion* canvas, TerrainChunkInfo* ch void TerrainRasterizer::rasterizeToCanvas(CanvasPortion *canvas) { - getTessellationInfo(canvas, 0); + getTessellationInfo(canvas, false); } Color TerrainRasterizer::shadeFragment(const CanvasFragment &fragment) const diff --git a/src/render/software/TerrainRasterizer.h b/src/render/software/TerrainRasterizer.h index 379c046..5958355 100644 --- a/src/render/software/TerrainRasterizer.h +++ b/src/render/software/TerrainRasterizer.h @@ -34,7 +34,7 @@ public: * * The terrain will be broken in chunks, most detailed near the camera. */ - void getTessellationInfo(CanvasPortion* canvas, int displaced); + void getTessellationInfo(CanvasPortion* canvas, bool displaced); /** * Tessellate a terrain chunk, pushing the quads in the render area. diff --git a/src/render/software/TerrainRenderer.cpp b/src/render/software/TerrainRenderer.cpp index e3361fd..a087b36 100644 --- a/src/render/software/TerrainRenderer.cpp +++ b/src/render/software/TerrainRenderer.cpp @@ -23,9 +23,9 @@ void TerrainRenderer::update() walker->update(); } -double TerrainRenderer::getHeight(double x, double z, int with_painting) +double TerrainRenderer::getHeight(double x, double z, bool with_painting) { - return parent->getScenery()->getTerrain()->getInterpolatedHeight(x, z, 1, with_painting); + return parent->getScenery()->getTerrain()->getInterpolatedHeight(x, z, true, with_painting); } static inline Vector3 _getNormal4(Vector3 center, Vector3 north, Vector3 east, Vector3 south, Vector3 west) @@ -50,7 +50,7 @@ static inline Vector3 _getNormal2(Vector3 center, Vector3 east, Vector3 south) return south.sub(center).crossProduct(east.sub(center)).normalize(); } -TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, int with_painting, int with_textures) +TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bool with_painting, bool with_textures) { TerrainResult result; double detail = 0.001; /* TODO */ diff --git a/src/render/software/TerrainRenderer.h b/src/render/software/TerrainRenderer.h index fba3301..529e1ed 100644 --- a/src/render/software/TerrainRenderer.h +++ b/src/render/software/TerrainRenderer.h @@ -27,8 +27,8 @@ public: virtual void update(); virtual RayCastingResult castRay(const Vector3 &start, const Vector3 &direction); - virtual double getHeight(double x, double z, int with_painting); - virtual TerrainResult getResult(double x, double z, int with_painting, int with_textures); + virtual double getHeight(double x, double z, bool with_painting); + virtual TerrainResult getResult(double x, double z, bool with_painting, bool with_textures); virtual Color getFinalColor(const Vector3 &location, double precision); virtual bool applyLightFilter(LightComponent &light, const Vector3 &at) override; From 261eb5a67417c6c1bbbb57495261f72cf0922ecb Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Fri, 21 Nov 2014 11:40:47 +0100 Subject: [PATCH 13/13] opengl: Replaced temp lighting with sun transmission lighting --- src/render/opengl/OpenGLSkybox.cpp | 2 +- src/render/opengl/OpenGLTerrain.cpp | 2 +- src/render/opengl/OpenGLWater.cpp | 2 +- .../{bruneton.frag => atmosphere.frag} | 50 +++++++++++++++++++ src/render/opengl/shaders/resources.qrc | 2 +- src/render/opengl/shaders/water.frag | 23 +-------- 6 files changed, 55 insertions(+), 26 deletions(-) rename src/render/opengl/shaders/{bruneton.frag => atmosphere.frag} (84%) diff --git a/src/render/opengl/OpenGLSkybox.cpp b/src/render/opengl/OpenGLSkybox.cpp index bdf3139..6b6e879 100644 --- a/src/render/opengl/OpenGLSkybox.cpp +++ b/src/render/opengl/OpenGLSkybox.cpp @@ -25,7 +25,7 @@ void OpenGLSkybox::initialize() { program = createShader("skybox"); program->addVertexSource("skybox"); - program->addFragmentSource("bruneton"); + program->addFragmentSource("atmosphere"); program->addFragmentSource("tonemapping"); program->addFragmentSource("skybox"); diff --git a/src/render/opengl/OpenGLTerrain.cpp b/src/render/opengl/OpenGLTerrain.cpp index b5ecfa2..bfe7a44 100644 --- a/src/render/opengl/OpenGLTerrain.cpp +++ b/src/render/opengl/OpenGLTerrain.cpp @@ -52,7 +52,7 @@ void OpenGLTerrain::initialize() // Prepare shader programs program = createShader("terrain"); program->addVertexSource("terrain"); - program->addFragmentSource("bruneton"); + program->addFragmentSource("atmosphere"); program->addFragmentSource("tonemapping"); program->addFragmentSource("fadeout"); program->addFragmentSource("terrain"); diff --git a/src/render/opengl/OpenGLWater.cpp b/src/render/opengl/OpenGLWater.cpp index fa57d2c..88f6a00 100644 --- a/src/render/opengl/OpenGLWater.cpp +++ b/src/render/opengl/OpenGLWater.cpp @@ -24,7 +24,7 @@ void OpenGLWater::initialize() { program = createShader("water"); program->addVertexSource("water"); - program->addFragmentSource("bruneton"); + program->addFragmentSource("atmosphere"); program->addFragmentSource("tonemapping"); program->addFragmentSource("fadeout"); program->addFragmentSource("noise"); diff --git a/src/render/opengl/shaders/bruneton.frag b/src/render/opengl/shaders/atmosphere.frag similarity index 84% rename from src/render/opengl/shaders/bruneton.frag rename to src/render/opengl/shaders/atmosphere.frag index c9096d9..f486dda 100644 --- a/src/render/opengl/shaders/bruneton.frag +++ b/src/render/opengl/shaders/atmosphere.frag @@ -224,3 +224,53 @@ vec4 getSkyColor(vec3 location, vec3 direction) result += sunTransmittance + vec4(inscattering, 0.0); return result; } + +vec4 applyLighting(vec3 location, vec3 normal, vec4 color, float shininess) +{ + float material_hardness = 0.3; + float material_reflection = 1.0; + + float r0 = Rg + location.y * WORLD_SCALING; + vec3 sun_position = sunDirection * SUN_DISTANCE; + float muS = dot(vec3(0.0, 1.0, 0.0), normalize(sun_position - vec3(0.0, r0, 0.0))); + + vec4 light_color = _transmittanceWithShadow(r0, muS); + + vec4 result = vec4(0.0, 0.0, 0.0, 1.0); + + /* diffused light */ + float diffuse = dot(sunDirection, normal); + float sign = (diffuse < 0.0) ? -1.0 : 1.0; + if (material_hardness <= 0.5) + { + float hardness = material_hardness * 2.0; + diffuse = (1.0 - hardness) * (diffuse * diffuse) * sign + hardness * diffuse; + } + else if (diffuse != 0.0) + { + float hardness = (material_hardness - 0.5) * 2.0; + diffuse = (1.0 - hardness) * diffuse + hardness * sign * sqrt(abs(diffuse)); + } + if (diffuse > 0.0) + { + result += diffuse * color * light_color; + } + + /* specular reflection */ + if (shininess > 0.0 && material_reflection > 0.0) + { + vec3 view = normalize(location - cameraLocation); + vec3 reflect = sunDirection - normal * 2.0 * dot(sunDirection, normal); + float specular = dot(reflect, view); + if (specular > 0.0) + { + specular = pow(specular, shininess) * material_reflection; + if (specular > 0.0) + { + result += specular * light_color; + } + } + } + + return result; +} diff --git a/src/render/opengl/shaders/resources.qrc b/src/render/opengl/shaders/resources.qrc index 72a4bb6..ed4c445 100644 --- a/src/render/opengl/shaders/resources.qrc +++ b/src/render/opengl/shaders/resources.qrc @@ -4,7 +4,7 @@ skybox.vert water.frag water.vert - bruneton.frag + atmosphere.frag tonemapping.frag terrain.frag terrain.vert diff --git a/src/render/opengl/shaders/water.frag b/src/render/opengl/shaders/water.frag index 1f5a9d7..d6b5279 100644 --- a/src/render/opengl/shaders/water.frag +++ b/src/render/opengl/shaders/water.frag @@ -1,32 +1,11 @@ uniform vec4 waterColor; uniform float waterReflection; -vec4 applyLighting(vec3 location, vec3 normal, vec4 color, float shininess) -{ - // TEMP phong lighting implementation for testing - vec3 N = normalize(normal); - vec3 L = sunDirection; - vec3 E = normalize(cameraLocation - location); - vec3 R = normalize(-reflect(L, N)); - - //calculate Ambient Term: - vec4 Iamb = vec4(0.1, 0.1, 0.1, 1.0); - - //calculate Diffuse Term: - vec4 Idiff = vec4(3.0, 3.0, 3.0, 1.0) * color * max(dot(N, L), 0.0); - - // calculate Specular Term: - vec4 Ispec = vec4(3.0, 3.0, 3.0, 1.0) * pow(max(dot(R,E),0.0),0.3*shininess); - - // write Total Color: - return Iamb + Idiff + Ispec; -} - void main(void) { vec3 normal = noiseNormal2d(unprojected.xz, 0.001); - gl_FragColor = applyLighting(unprojected, normal, waterColor, 100.0); + gl_FragColor = applyLighting(unprojected, normal, waterColor, 16.0); vec3 reflected = reflect(unprojected - cameraLocation, normal); reflected.y = max(reflected.y, 0.0);