From 93dae1ecd18fc3f7c8ddc014a0f2a65aca63cb71 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 2 Dec 2011 07:55:24 -0600 Subject: [PATCH 001/220] Changed: Added the basic UI structure of the new Tile Editor plugin. --- .../src/plugins/CMakeLists.txt | 1 + .../src/plugins/tile_editor/CMakeLists.txt | 47 ++ .../plugins/tile_editor/images/add_tile.png | Bin 0 -> 7305 bytes .../tile_editor/images/delete_image.png | Bin 0 -> 4144 bytes .../tile_editor/images/delete_tile.png | Bin 0 -> 7561 bytes .../src/plugins/tile_editor/images/down.png | Bin 0 -> 4286 bytes .../tile_editor/images/empty_image.png | Bin 0 -> 2235 bytes .../tile_editor/images/ic_nel_add_item.png | Bin 0 -> 3270 bytes .../tile_editor/images/ic_nel_delete_item.png | Bin 0 -> 1496 bytes .../plugins/tile_editor/images/ic_nel_new.png | Bin 0 -> 4035 bytes .../tile_editor/images/ic_nel_open.png | Bin 0 -> 4310 bytes .../tile_editor/images/ic_nel_save.png | Bin 0 -> 6462 bytes .../tile_editor/images/ic_nel_save_as.png | Bin 0 -> 7748 bytes .../src/plugins/tile_editor/images/left.png | Bin 0 -> 4377 bytes .../src/plugins/tile_editor/images/nel.png | Bin 0 -> 15587 bytes .../tile_editor/images/replace_image.png | Bin 0 -> 4157 bytes .../src/plugins/tile_editor/images/reset.png | Bin 0 -> 2157 bytes .../src/plugins/tile_editor/images/right.png | Bin 0 -> 4395 bytes .../plugins/tile_editor/images/rotation0.png | Bin 0 -> 3643 bytes .../tile_editor/images/rotation180.png | Bin 0 -> 4492 bytes .../tile_editor/images/rotation270.png | Bin 0 -> 4516 bytes .../plugins/tile_editor/images/rotation90.png | Bin 0 -> 4548 bytes .../src/plugins/tile_editor/images/up.png | Bin 0 -> 4654 bytes .../tile_editor/ovqt_plugin_tile_editor.xml | 10 + .../src/plugins/tile_editor/tile_editor.qrc | 29 + .../tile_editor/tile_editor_main_window.cpp | 171 +++++ .../tile_editor/tile_editor_main_window.h | 63 ++ .../tile_editor/tile_editor_main_window.ui | 663 ++++++++++++++++++ .../tile_editor/tile_editor_plugin.cpp | 75 ++ .../plugins/tile_editor/tile_editor_plugin.h | 109 +++ .../src/plugins/tile_editor/tile_item.cpp | 138 ++++ .../src/plugins/tile_editor/tile_item.h | 66 ++ .../src/plugins/tile_editor/tile_model.cpp | 123 ++++ .../src/plugins/tile_editor/tile_model.h | 54 ++ 34 files changed, 1549 insertions(+) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_image.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_tile.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save_as.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/left.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation0.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation270.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation90.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/up.png create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt index 426d3aa61..51d44137a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt @@ -7,6 +7,7 @@ ADD_SUBDIRECTORY(disp_sheet_id) ADD_SUBDIRECTORY(object_viewer) ADD_SUBDIRECTORY(georges_editor) ADD_SUBDIRECTORY(translation_manager) +ADD_SUBDIRECTORY(tile_editor) # Note: Temporarily disabled until development continues. #ADD_SUBDIRECTORY(zone_painter) # Ryzom Specific Plugins diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt new file mode 100644 index 000000000..f3458c909 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt @@ -0,0 +1,47 @@ +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_TILE_EDITOR_PLUGIN_HDR + tile_model.h + tile_editor_main_window.h + tile_editor_plugin.h) + +SET(OVQT_TILE_EDITOR_PLUGIN_UIS + tile_editor_main_window.ui) + +SET(OVQT_PLUG_TILE_EDITOR_RCS tile_editor.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_WRAP_CPP(OVQT_TILE_EDITOR_PLUGIN_MOC_SRC ${OVQT_TILE_EDITOR_PLUGIN_HDR}) +QT4_ADD_RESOURCES( OVQT_PLUG_TILE_EDITOR_RC_SRCS ${OVQT_PLUG_TILE_EDITOR_RCS}) +QT4_WRAP_UI(OVQT_TILE_EDITOR_PLUGIN_UI_HDRS ${OVQT_TILE_EDITOR_PLUGIN_UIS}) + +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS}) +SOURCE_GROUP("Tile Editor Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) + +TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ovqt_plugin_core nelmisc ${QT_LIBRARIES}) + +IF(WITH_STLPORT) + TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) +ENDIF(WITH_STLPORT) + +NL_DEFAULT_PROPS(ovqt_plugin_tile_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Tile Editor") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_tile_editor) +NL_ADD_LIB_SUFFIX(ovqt_plugin_tile_editor) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +INSTALL(TARGETS ovqt_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..a9de8f51de04f3d0f475bd0fbc9f277069244385 GIT binary patch literal 7305 zcmV;49CqW0P)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000U( 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 f|J(gM7T00000NkvXXu0mjfQx9E& literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png new file mode 100644 index 0000000000000000000000000000000000000000..b0033cf64a712b8ce4be8d7af939c9a3d6be088e GIT binary patch literal 4286 zcmV;v5JB&WP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000H)Nkl1LnoK1 zny#9fy7xQZcOLh&U}oIS!y3FHgoypm=dM5c7=R)mj_RM_&JTL$&OI&zyn5;6ueajP zr!%$~ycrk3JJ%jr&ZQUDAGq&f4;?AM^&6f>Q$^CP)e(BMkIeU-Zn+5iWW_l#8=^>EwgK5<*+dg%X;T4|MW? zQauUjnP6=#1fDSiObn?4NagRac#R`7cVUDK%v3^t2tbGtKET5u?j#@Z0~fB>gfPsW z7YIXB6Gdgj?J%sAKU)BjB&1RhN{yGC=0Z|1+b~K>fhn4%I=;Z#l}ABH6@X}l)u^Hn zz+lkfu@tl!P(GM2I|-2vKnx9aKHdRQNP>tFrw^c8r=)#w;?tKGmjRrCrmX2N*|?7Z zo{)j=u1-lX@zUwbi#PidUF27I+G?+<7NakO^#k{0BP$lsQ}?FwRnLMV{^C2AGEkUb z%;v!;M4g@^jQLK0R@E&7xH1+1F@uQVHM~es6R9*ci`_{^TA4H8+;)fm-pSPMdxmMi zFa?M?uY0#KL~B5+z7rskN`Qz%iBJeCJg9rG{~$H`&^}MpedpjD-RGELB~7$yZWV-* z4uG~Z_rk?PH?s%R1ptt~(py-FvC0{#q=7lRm)zTU3IM5`jrxBrsDO%JpRcUN@60hy zG%Br)xx=|7(_%6s`$-??X^*F9N8Ov{=&jM z1j+{%GDibXf)tOAN-_4s0|91`k_ahwIsva0z;F4bZ{Mq~Ox@gl?)<@HLSSS5-dx^o z`XI$SuT{hgpTlJIE)wYkSP`1rPU-6VwUu3Wr%#>BA2ThZoIRL^*Ytaq5|inFq-^@u zZ`om0+t_x?*DlqL$LUTR<0ia%vAQXJRczH=P@n#A3ngYEV@*+Hm;#BUg?h!Qf^l^HgWI)H-N2~< z0KoEF2foV8C5vXl?1Gre3Hlt`Fa=Us8})x%RZ?8Ie!0H6Q#*54007|GH*+_$`BZ_K z5qJs{d?PiKk%b6jePi1N1+?_tM~%&K{n&|pKr>D>wwGd3EP zFxHP-{H}eVe?0R>b{@c1b|IbjouC(9V{IqHt5nVoW4$Ab-+$a%i`x<369544^x4cY z(-Irmd^+zmymnP8#%5mtNM>yWu7uYLN99cMrJp_zZcQ`CzA(_Y(qgmfmJQ2*VVOP4Lm-(>pjCCNq^L0M;`f~a0C@am z>xd92r{|LSP6OC54LEfVB&qoG7iw)+Hrfv-9s==_InT_ihGi6m0AxTLLg36VU()8T gNsa^HZX5p(0JF8qg+(fiK>z>%07*qoM6N<$g6=;1<^TWy literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png new file mode 100644 index 0000000000000000000000000000000000000000..9a2e358ab13467aaddc0b8784a56b1cc2dedbd7d GIT binary patch literal 2235 zcmV;s2t@aZP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy32;bRa{vGi!vFvd!vV){sAK>D02p*dSaefwW^{L9a%BKeVQFr3 zE>1;MAa*k@Gd8K`;w1n82mnb$K~z{r?U!kAQ`Z&8^`(;!`O=cokd{fO%e2#N(rJ?> zooOc@+B5;$4kX}|0%mO?g;1DK2pA(Ucm*#tHpaGWu&{;vyvUnuc@f6DY+1IvV%b`} z+mb9Vk}){0`S+Zg$WUe&%5*Z*4|y}cd6M3}_x#T}|NGvPO!md`|5AaWp`q0yBO`lV zE>|KUJ&xP$mY$Wz)=<&>sNvz^w<*?hD|y@P_AgCNPHy!1e6Ho?WqjVp($W%UXJ<_$ zW6iggGn)Z$EjA%b%9 zaZHtszbmtFKye*=l2WlPE)iQU#pB(GC>&B8!LYkah*(@)Tyi>{f0L1tIsU=3Fos~Y z4sZUW4!=FsfDLC2*c58S*64QZO6bCY)LtCEZlM5He4K5^={yGo9mE;U5Q6D^D#wl! zY8#Fy`*AR>4|}h4V@F&EHb7u8M|tVM@g0>aPf}x$FpxEyV_T6Fx}n zL`04iX%w)?;6zD_8x<7LXqm(K!~(pY`|x=dG3mUAk@3640{VyMVYYhFU=!1#I zmKxpAG)_WYGfv6$W7CBe$g>^_;9Vt~n-d*?)oDdwoEGm;1^#%xMU;MbViyjj_ldI0 zsni#BW4O`aM7enyoi?us%E9jp&ZDYx8kvnQq}-l_f>72>;0BReIf_WC;P#kytf#g< zDuB1CjJAXjFyQRRj@V+XJ7d5`>ixD@GxjBQ<8X#W^!9wwh$wSm>lCWHW?<}}BN3D> ziRiZbVCb7gvB`sE3LaTDiqp9ce3UsLytDIir|`n>&ox7yc?sUTpSFNZ_)vh=)r+%v zsgO$vxKf>rOk)DFS}!BLDHRFT8pKo@kyLF%ev1n=olf*xr!YJ+BPzfm+6KJPnO#V$ zYeuYIji~Zagla=^B0C*NGSt|Us6fEQc!b8Ar?zW)MVnc6FA1r-?=(UWYvBQdDLn%~s(Nz9m zT)%x1*KQsEj1!2~>_nIpfb`NJc;}}@Od();`qM9Vj|mC--3V5#M_R*&kj%kQwH-&M z=_4UX-&BC!-d@nn1LNc4p#EWWbX0t&yXjNmag4=cL0elJc=ypd4+U7=El4*UM118g z0{zZLBsc6u zn&AMh=>LNA+3zB*VjGg{_aVP3jSYjbu`$rC8xDtqCkyDFE-J$Cb;e&A&XyS%7+4ug z4p(;vT3C@f2&hf*-cv1e{ zFOC=IGIw`(qpPb6?d|PoX=y=!f4>mVE#vD3gF%vUIr!)puE74}Z)11-H?SvREw)Ci zp>6mw4yF7E*K(s*GUh;!mX_!9f-Hj14Gj(G>FMF@P*-1z+WK1}TlPi^7(axlsa3UxFx z^fu>jH5W3^<$jMeFG<@U*LrFDo&=qBmAJ%YGE`QQBzaH zf+ZPkr4jKgm}tS_tFK^l@RzY!{uKnAU4?*<7Z4csO~j_05sqeaJqnBR!`FFn&P<)F z#Idwr(aXy^Tq=7H$1~qRiaJbO(`YopCtR(fq9TQi`Vqdcu&~6hOTD9Yh%E|4c+Pt( zgsI*~()B3OH>R_*^NFyra&mImT+kHdAmN4_QP&P4Gxw?po|~I1uCZB5OG|x9rE;UJ zuCDI;WUfZh2RiP5LeG18Vem6M??#zUD<<)NX4q&?g8B+clAzP+xW|HuiV7jDyu4hv zpCJML3WegQ;>DDDx0)7I(T;G?opFiYRQPRW1>V~=bJZgsz|`|E3fC&kLPI{y+#8z(O%uc&}RYtzJnSy^Y`17p5zX1;`E%3QL*~I_=002ov JPDHLkV1nBRLyG_a literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png new file mode 100644 index 0000000000000000000000000000000000000000..bde338f7851d2675b29272c7dcf9471196a8f6cc GIT binary patch literal 3270 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 Eg5p97)c^nh literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png new file mode 100644 index 0000000000000000000000000000000000000000..a5a1787d593591f855be9a7eb8da271cc8d8f214 GIT binary patch literal 1496 zcmaKs{XY{30LC|C-c2!W(h#B2QhA@kOt{brn;~tK$;-mn#DM?-zdb>=i zu*@RTd8@_pvUxpuxyoG1>Bsxw?uX}jKHujL_-0@|T~w8{l>h*Ms+%k3&``sHb<81=-~(e+|N^9C&_KHVw5X^3IM3J{S1(sAHJ}8!egC%W4+FY#L`JIX8~B! zIZ7C+< z6bcMhk7Jz$z zt<~^Npzeyeat^;b(tkMW#bRkwb5S`|-P(cZ{!1geIKC7Tzpi^Q9XhN7r*| zh)Tmw?h}4)r(e%EPx*~jbiDn>W9k_F^gyx#1J1b!&uZuD!J$Duh_I|$-B|3)pjcABT`DZr@@$gnJ?g*7niqC zPg~-q=_uM61|+bWZC}wlE4;C-L;LVrU6J(R@D0Z4=p`kt`4==LnW(d8wXiBZND)3NugXyk}j`B>QSp`rx>7I47#1U z_C?Zqn_!w_iq*Q=7#33$KOO+R;CW!bcdn#k;~tqqg>*o8s|#;{%M1@^2B=`1X*QOW z`~~EL<8YMd;Wk~hP%ln9+T{3weTCGPC>#3IdbbgtfSL(^;<-$(&+()%CWY(ZY}rUs zYZ^=Sws7E+dDpj6e_>>!qz;jFg;SMzWx6GvaM=_CJv#h+^qF(IggsR{8BYMQlBT|c zLR(J;=NJUkn>YRLcdDtY?zXt@zIEUuTe=1hEndEU6|7%)i#=`5cs5S}P9Mh=PcJfo z{ZbSwueq|yZyG~GMGk&1;XI&33fgfyu~6eIQgk!Fkv4<^W8F=|9U5oXINb+#fCen_ z{sB?u3Xfi@SxqMAC%ZI%1BJIf0uMiCx!yXz62rndMv z$=6toP8$LinV$s7C|ZjMS5+@W1rn4NxN=o7bmp|tGx-1vXy7V6(LK7Owl1b<1|o_O z>bY9rcsZ;+(mT(U8Vqy|@K*SC7Xeg!@WG?ntw{ZC`G3Vh1-90Bf1vJ=9f)jI$P4Q6YBQ@Z8;^^H#>9pe+1$q6DXU$-5VbBeJ(3kUiuh943T}3C$!G=4Zw&rX zIZx;etQ%$b10W;H`0fD|-g&n~Eq? zJZ zC}pc4u@0qD`7mQX=zMD+8o3Hi#&31p7{mxJ*6-KkigeYIgt}@Xn1a05YyE6U8VHU~ z8PL=CTn*0W$(#-|89Sz`9P!(hY?pOfm^ZQVXfjUeBhD+B#yUg0vkok?_%`$Xq0`=> g{}tB1bjDO$2a)_&SEAML{IoE@&Dj&vfF`E?18{b*hyVZp literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png new file mode 100644 index 0000000000000000000000000000000000000000..d45dcb4674ac76de749509f45685a53954062ccf GIT binary patch literal 4035 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

9hNf?Vhz@D{30l;nt_JM}mQUV~w zU}fFVhIWm|NOEs-N_P;?dO6vhZ=x6b1{FEy`NkD{ET93v*SoKsR0f6P6R8(-ZiNnchebmTE2n{zSpSfg2HYuKG#tYt4ZYTD&Z}v>Y0IYrC-DLxn)fK&= zrBxtFv;I?h(WyuX_0*ExYk&VfA~DMt^E5?fh8D@?nOi z39APLG);rhG>F+T%}S0!6A;4c5OCIAaAo0HADXp-k&!UcM#SFO%s;8m_cd>rQutM_aGu zSKJ-`AQ3zHVe*-DGCQcpGKI6SO^D0Q0`7L|qtw={ZthG@rJ*F{`$RcP$lp$Xq92r5 z)tj15Lz&81C6Xe`iB*{s0DzwlriYYC-N|Tr#>|)waFV%gUs)3XfHQ|OW27jo&txKo zZbF&_X{y`90<-Ox&x|o5?$+a(k<@e=*`yI+=D`Io?k@hPev!Z;fkguUYx{QqFWXW= T3%>DB00000NkvXXu0mjfsaq=9 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png new file mode 100644 index 0000000000000000000000000000000000000000..d2139bb2557984f999a563059ea00f7e76436293 GIT binary patch literal 15587 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 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png new file mode 100644 index 0000000000000000000000000000000000000000..94d9b76c80384a83bc196cd0e03759bfb588cbae GIT binary patch literal 4157 zcmV-D5W???P)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy7<5HgbW?9;ba!ELWdKlNX>N2bPDNB8b~7$BHmT?0B>(^qmq|oH zRA@u(nFmnScecm(&CYwf`?4fzj3#OljWKGfW>bvD7JH|uAR4=Z0@AB+>Ai!1h!p9) z7XiT_f&>wzt0+y>s0ne6MzfpwzH@$mF5wSmcjnE$WM^LP%$Y0q{_p>PKBxW8IsWc< z|6g8)3DYK$tWxC6*LTQWXkwP~u9kk>>u>z({CZJS{=+u?lWmIZh1$cFF-x8`$~k}O zTGzrA=lxD;Ah1FUu0<>0khc&HxeK7kS@3uBztAXf7PJSk+d`nw+)z0tj zGUh8-5rX=?QT*GQzNP9No+sA~D7^qSSs%eX?L8PJO@~4J>o^!Y75XvLKmgzBMNSpJ z{l#BB;=F0*sU{w&nHWc?H8f+eueollB?42$$xFiw6GhKX-L z|HSJ!5c3)c9{Y~IialYk;84t4I1o8)^DhptD`b+2TmI^Hr~Jim%wGie;#E+P(zc|u zRmS^d@poaAJQEcEFo+|?qgnAO1B$)aVU2|I%) zVrP&fI|4}pCXh^oTblaM>ha`n-($DmRH#}#i}mJzh9Z8|zf$KB_j>T)0j^)azGDzV zRu z@x_%`R9ue2skUP%Z3#zla|nu>f>78Pgn~SjGy`awVa--s~*JwwCJzs5+QH&9x4jye?pi-$iT>YQ(OPdJ3PHuu}gIJ{sQ1)V_lp@)Th|wJVq$G$x)JxEQ-<4 zB+;-N1@*(v36E&FL_x>@B0acCD6rMjQiRU(1OJ6>9$K(WxdxlG>#$Al#NmuCA^dNf zv`$#1T!%%H1al~sK#sRz|IrrgI?{w~ftR4=(*O-6g#9@JsK#ejRnYJ-Mp@%=8N|(- zHyZ>%PfvG6MSUVHk1iHsaO8cc+IBA3{UON6>Is18tvj>?Gy)(Svov zs|a#BR*>>)*5hHGPzgnLHym?&;GEYBm;9f^i9U0n@9Z+W1R#SL$6bLzwB!u|5pYTJ zgxh(nb*#loyBaLDIZGf}@XpyJ1GsbN4g>(z>x!Y@T)35k`DT?^Y*~d(?sYgA+6aTt zFQFft4eQuuD3Y$iCG8qKvpTWIYYS8@Ct?@9A20937ftkp7}?k=Lve1#a2 zXp$r4x8Paa2Umg$IN67UGq;gldj|z|ci~9)+dlxYmAuO#s_IgQH4f*nflhKZ7OKXQAp`i$lS2&{9mrZtvMRRo{c_y${iS;~{!)K0<9n z9d7h}i+gvz$2WH$$c-a30-_d&?UDHL^cK1C*kB~>W+Wj3`Iv)to%k*#l zTL7QAh3K*y@Fl}opJ<2K@m3ffZN^G_$qSyDa)7&c?@9o4^2q?s^`>Bv#ToIVHI|wp zIoFvzkBzReB6QeN2GN(XC&(82LiWNaLJ#Iq2jCE|51&*+1ZNr{EZZ3215(>ig6{~3 z!5F5pr5^Kr<<$`C1rpyCB3vjk89*YTJmBk*c zG5Qmh>Ha6h{tgkJyF;6)VQUlBL{l*q8!S{r{pSNr-R3!w=v0)6HUq{MF{hznQ$igF62th##y zP>tZz0W{?uq&Y+j0p%OvQFIXYS&pzs4uEA+2zkQ^Isq2Y_BDfRlA0`pZr{Ewd0;p| zaeELfqUKRN)8S?NoUpE6(Pm^eJ0hdW0qKqQNNco1a)TAT^3}*YGw3v)gk982apSl9 z2sMDz1ac$DVwbQ?RIE0#es$YzWS%cZWR(Mgzt|#1R94*Ylsb5z@+w(J?;GGxpZT0r zr|$SQa2wB^u}h-r(*dY4l6jz@#TOPaa|cgjj^mwyFC(OUJ7Q}OA*R+4k=1&zPM#;` z0`6M5i{+M^Tkri5QX9UX9?B24h@XSxI#(R8HbQKT5ze+HA+E+;C@B;#-5?bAELkhw zy-U|4y2=36t?39W)syZ;_jQinAOpB{>z3q!;Q%>J9`GfLb4+tjBnA~~@b-mHq2!${ zMEBTKx+zU%tS~9ba|F-FJh2%jyaA)c88A+IlLn(VVV(L3SzAYhNn(vH+)_6qsBn)^ zl&3$}qU9vZ#Jd|U3|Nj;=))vpA)N(_#dFv|PH}PoY9%B9>gr@3$h^q$eGqyP)2JgI zFXEcpYYr2(wis?mX&x>0PfQh~CQomsDQ}C3j^}5GyahO%{R!-{=YpoaL2G;GX+t;U zFEEK*K(qFzVsur|wR}BqIvn#^7QrlL9yFaMQYE7qC2XV3|If2LD;)RZ=K;I;=B4AlMJZro%S-W0E=II-bS1`A)(rlhIghI$9d4 zj!c3gdYue_S|ADF>eZ_ z3D2?cTz)8irU)5z`xj^~nIIJiiU9klwK4!|fh2${SFXqa;%d#{U93hzRiStTjL2#> zX>(zmz%l(cS@M0@<;){jFD8pGgKw!Cb)XBR9T5T2woc>%d&xFqF16EhMVPV2cqMZv z{!JW8qIcRYF_;m9k(j5_LLvEmp*&limjzte#B@lLpaSj%V3;fU2w2WW3^mjOhc(UT4%I*61YI$m@@ z(aji!7Gd(TIizIrHbdHO5X=COfEoZA^b#$`*i-B=4o~yw1ypesQS1H@Od}Uk$h<6c z-~z&{8Xj?N!{xI!wLp>w+S=M=0O6;1i?S)5tUS~c2q{14m4UUKEr=+-Y z2erjxJl0u_!5Z?wMn~y+v@sNh=)ye;%@bCEI2&u2H?x*P%kXDjxNxB}FE7uZWb)4{|JxV8S>QJd{APh)#RC5WwsFag>)}+|00000NkvXX Hu0mjfg>t)Y literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png new file mode 100644 index 0000000000000000000000000000000000000000..6693e842c25aba38b1a87a99a06368db17151386 GIT binary patch literal 2157 zcmV-z2$J`SP)-7A@9RST){$KnOGm*#d;%mkJ@luj4;}-zFiro^yMF%3yh!%TL_TEsei1C zJ6*eNwqz&l+IGhqC%EWGKmIb!zVU0Ce(vY=pToS+i1?dN_@kfx^c+q7>WB2!GvT!l zp9+rb24L6fa-o?p7d<@nn9%$5ILNclfiJiWq3{17`tGo!E{Ge`&C$S_NumA8Nqoi{ z^!(^&E$;5n%x)02p0b^_t6k{waW2|9IVSXdZ35&^UdQO+@ERWY_Aq2pJk0<8#rVWc zCAQlOuTS|<{HW0O_!*EtzRXMuTyq;Z!sj9N!t-Jwos67%Wj(Q17uplREBz?`?65HK zl@U<>bCsPeHU_}~cjzc&k^l>T`rD2W?@xN8!I5F1ZR!zF?!Kdo#~+{?1>!jbj{Ye~ zU%V(v%S(|{mntC|2Kaj)iFS^Kg@LC|ftvmoY9^%%*pCUq1-c+JuR`*rEAfdNwGi)p z!4nM*hf(|xsHqQ%;z1WrRilAB0Is8>uz2ZJQCeNCfM^KdD>y5Yvb-{@Zn=Z`=f)PuHMnDuK#J&1khAX?}^I??$E=q z^xE5^w6<cPAv8$u5 zXz=6_p?$I+w2h=8oYD&Mdb5m)%M0$_K3IA4x+sa6(+DxQoz88u5MDlgWV8zk$%XPu zlya{rnrSuma?_u4BKW&G=$sBmXFu--5u2 z?iPIHg@zU~yfKlwk%Vxh7Yd83y47^c)1vjUQ9{j`U}GaBaGcwO=59CioFAI@w7OCJ zifQ=@*Rjrmbv78NqJV=a?4Fi})9A$z#=yzLLU_6x^2?cGyb^uhOc&z7bR{!$l{(&m zmQ~8aS+A8{NFUok5GN0=U^6UVTS!n@jSOGj5F5@ye?f@OlZS-CDRigRtZ|Mj3oiw9 zwfJg(v|8VG7K-9I2M^AG2gRooRM8@zdo3g0_d1|M47DIc2jo|BWe8GbePRPZOG&3} zeJg-<7B~k74!;YQuP*80AGxwA?#n`^XC;K_7zzr5k9I(gLC{(V({)PsmW0!)S+Keg zEn42mfwS2OOS4M}4CKhjn_J?(t;FTjiV)$TF!04ToQb^YGUhA*v7LbugsmGru>| zx3Op=5E*}8esD4H$0HDJ?`aZ3VMBa%3f(OW*~S6}G7DmsN;mFou*x$so{;xH3%%G4 z(Y7OAAvECMyZGH8Ea}wYbLivD-Ha{7eF41Ch2pzVe4h^r>xJ4H$SQuPAl_j;(A^1V zf-R1l^P4pg4FmiE#kY2Ngx-)Bq;<)*bf`(8q)NQCq_9b+)^)+@a{_S?*h+305ZC3# zYoXtDqUGD<|T67Y}5I8VG8Gn3dmV%>%mwlY534 z7^!mG^0`_(DT^m4g2!IY$lF6`wX>kl1eO*oL*u(6-Cc&T#)4+&Mn<1olfZ>z1R0SxW%j-3O1)dk z_KV(9;{D6kAE>b!!?sExbmi=7MLvU&UU*Yh>2+ z@|x%i9*UW(`{VBS7GW-%Q-5;nULJT1EPTHH0<~&IwXV3#q6*H${Jk6#ANl%SDt>j2 z#xomoY-Onu!Vp{(tuWDG2v?1N)~ z#F)?_jCeBv0)F0@NlA-8{;?L@x0P6ja1!BY3lG`6W~O@wTHfI#kQ5c&^50H^xJwlq zZSrt}-^0OrRxLtML%fgIgIJce_!GCa*uK|7C5WD84zd_r%<^swv{Xjb#eXNYvv@0n z*F^-Mi@@5J#=HfBUQUOQ6&nB2CtB=*?FSfy$3cWHAJJd9nAH;ah{!X06mNxK&tV2o zsWAf>!142UXzYP+Xb@rqPhY?*S}={pzMHO3ymfnun=*kILHvuS=jgNhwj(?EPrd_y j1Aqg71Ax68{}W&U)Vv|XcY0W@00000NkvXXu0mjfEXXC` literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png new file mode 100644 index 0000000000000000000000000000000000000000..eb51b8385549539bcdce8c1844655c4912839837 GIT binary patch literal 4395 zcmV+`5!CL9P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000J7Nklu(fQ6#t#OTUuy=5*}h(td$^OB2+OUCMGs2hC~w^zZROD$bnIk=Sh8-fy8z4W2s2dI`h1i&(w1v$4K*PXB8MmanTi0<0NQ z+mI^szB_CvGMCbBCbj}pMX zWv+y6{B!jWw9H?Inq*z-mAwoAJ)gdCYRq0i%#7~OTGrJ!%uFv>(2PW)27(e0Bp^fr zL?SqMZTFL45)vT+5CDT507u!lUbq&IjTfQN_DRj1*^FF%7$?vDIsl-fZ{6u^rRWkf zqibjLp}U%!I_v9Z84q>=g|_$U!=k{?raww%qHv>DKq6!k%rw-^fl>;C7k?X&%IW+( z_1Bq-Ya!O$NaQD*uTMMBZjgk=cS@Oap{=y-ULPAO@;Ao4eA_6u(yLHX7ja+H%65Uo zz=p5eR#wab)(l745F+V%FOY(-<7gxT+w?q{p06B(sA8hh@ipaNIg-DIX~{aYHa*aI z?$W9L^U@ADe%f?C|iHZ&Tx5xCaLTBVN7qRgOxAz1_WFQ zF<3J|fRY>m97u@}EvNnmMdcM|K;toss;Pp!!klr)1_^49NQjk7!pKvYWuFNk_H180 z{y8HgXn4<;T-lu`su-4NzHn*Kv{sO|8jMsSt#uFqzyoZ8HEsWU0|>`cf&gZhB~27K zS7?03yhsQXMvBmyw+D+kH;Flv61z5gwofiT^f>3{e93*w4K}VVGhFZ%ig_o!_lTF+Nx*YTbFml8kvUHx)i7( z8xv?mE(DKwh}ct(r+%7H0+%DeUXZ{LR2m!4ax#2Z1fp@Q-sr*92=pD^ioplY<8k5tKNYseXYlJdQ4Pl=!UTP4@ zk1#@7Go;rf$5|?Qm4;9pbzogD_7hR(f%mRv$9$n7B0T&0j8*_C03Gor7BnvkYkM3l zMP3ymy6>3NG!xQRV=O_!rX`YYnY1mL{(kFl*Lbh10fDJHp5Hv18=GcAIcm)7{BEAl zT9CHxIk+veVv|FStd$1irorE`2q+aU)0u(ds12tm(?@q&T~+@Jjhh47 zO;)90dnV)lx8OH2?sqH+yWn6nV?o+-(!k%U2=wH$R5d@}D( lcmCDj4uLxaZtvs20RU#hX1{$&&UF9)002ovPDHLkV1hXFC|K~$`Q-D9W081y%pFclL-Tj)T-4+UkR(?>D{@`F%Qf8ykFkIK&L)V`j z8X7WIe8IVM=l;bo4BxhG|1a&R*X#bw%*?rLHhX(l@E0yzc!DJL|I&|AspONQ?_Wfr ziHV5^*REar7|~|2>D;PlWLyN+^%t1h7k|OO-ObnAv<{UT0W{xy!DRl!u3Bp(6gJ3YC7 zQ=k@LuLG2!@ww-U-t(#Vg5KphYQ$+8JL24NonY)X$1dOFi)Uhy^LWqo+p%-Y18o6# zesXg1$>HJQPf6qB0OFH2xDIbr!0o(BmE)%cB=QgpjfWmi1Y@cJ5yn2|y7tefsq25rxgcn(dg!#l@M7 z0IGzfwh-;UDa3LsNJwcR(byt$^A0RG(0>cKw?zB>Q3XeT^$&1y09rzY98#OUCXpZ^ zxb~y)-BmPy1F|#nvXDzHtt^eb%+nTSQZW^Obxj(B=?FO#Yn~*R0?P0`xr!YKLFZ}G zTuPILAoM6IwuiF?3w4LINnm-tL1VT|l-{)}uHu=455V;qd{|J>rR%=Snr~WL4Z*7K zhpLXW;>S_}&_w{UNRuY>WX6MU7;PG{AUtMa`U!wS_i#%_WYh?7f_h1~u!I=hvw5}F z=8-3?3zRJv7Yqwe{rqonrnnE$v?jn?HCt$3YAUDm;Iy!~Yx`XnzU2aVZj%~|DZ}GD z(V|7G*_w-pLZ+s1m<6FlTctijrjLa~NK)T&W2R1n=#;BCf?BT}-3`1$KHymRAdFI9)8j^zTZc7Qb5@55^r|h)^F|lP z2%-xXIcjUH62Nd1e547Udszyi5K~I0xkMx+sAdy5w#HRNzgK?o5N79pLg3@1X##IH zNXuS89e%g22tj<(JZs;s^&peMlJ> zz2j{ptzS*l86wT6g-@t*#}Szw-`@KLOpwF&tV@ajQJ$L*z;iq&@LD`91aTS;?79Qr zk+E&d9hjW^Z(0M4W*DwtnG?IdgF-2fa;1cNqei^7774I;%;rCZnsX8bibATCB8N^Q z9oZ4MW4c1rbHzdxA@F)KBBG5&T5nVu0{qR}-hRcD_sYOLJYdEuTR`SdV*J1P%*3U zBMovuv<2{&2;ep6rO8d`wXTI88565%VagPa$+XdEb&qFsK?{pQZLL%n;BVS~hX8Lo z4P44kP|7?*)}nPs*My(=OPI1Eg@W|9(a!4&W)5eI<08$CXDFr6BTM|DqjixEoEwHc z8^^sLz6%4tbg=i>qawC5cs(8wix(eO)k4*vNJI?Xw*5B5l5tp09hO}~)taUEIU=nH zz%RGJZ=n!H0;l7+Mx}_$`5eM3r4f-NqS2^u&~P{|?pGB}EI=Ba=f)J2@(S+#$X!S! z(|GqypT^nAlQ@;%Pn6M-=!*$|s#h#j3iDw1+P3YTr1?1gCIt-o?TeSk1z;^2f|?17 zajPvoL?XJ(0<;cD66Zn+tpgDZt{Fmcwt(DJ4nym%MMCdEGTJ8q>(msPvPk09#iJgK zsSxh{XaK%3?~0gy-#Z^hzjPz?L=bHld^tZ4r|x6q#&;l^)X}i#F>kU^4WgAN95zbX zsiH~(q_BYdJ6M2yfO8>_fO!=1Zn*IVac(*DL7^h@{dVPo{A*Fz1r7IoY!_0A4)~H` z;>^SueB}KPQ)W7fgJVyi)~L`s3H;WZ1^8;M1fx(UAVeXnfvD1tDvE@|?nFHAcL<~G z0}TSoT4idmHKN2_?pafmG%P4sBot1@;msxR!H?hF6@35NG&a6C}n90nt|;75nP zj`T>GETSPdJBeKWB7t5Fiv%l`3y5klidta;X9cyf*Q(;YE4KgxW$-M7B>F%Qsipa5 zUz^t9&i3I$pSb6@g4e%p>-|8jNv(`Pz=V$j%qVSt}yzhbAt_b`~FCRgD!%J}FB4(#& zP^p-~&ISE^wPuhIHL=LKGJ#UL1w}+l)80xHT5174ZCFGVxr+tp&wefk^MxEyjU0{c zJ@k!7kBP+`R-m7( zB1(Dw>Ygy-R0C^Nd8IflD4)l^$N!0vzw#pRqlXS4-?tYv`I2}Szf&dQIf>)^zqKpD z0U?>Dd8!){)cXrUC)W#N+r?SIiCxzk{BnD9ci+B!BkR_!du{XP&0Tk{ z4A6;u11=Qo;v2qiA@ruRefb=YEZNU{_VNbf3y!8wr%6sv14Pm z-g@g6J{Q&N&Ye5QCMPF9b>hT{Wgic6#w5P;!dH>W^y2vVOSqY8Vw=)jF8W!EQ7v#} zwg?yW@A}y1|7hUZSC1Y&Iz|?_qw5!%y?ghL#N+YDHf-2%dn%O@bN}_@zrkhW3~4z8 zqdbSdo=p(%9aM=vOdY1i#eAKzR!V;4)h|By6INv z{p;zPf_b}$uoOqlDkERbLXjfq(bost?Vi`+`;wlcAESzdV%h5l-}|kmaHG`5?!NnO za=hvLPLhCLdIl@IQw_yi2V#S7QmAOD=jSB|b~*{1h$4rEm~N)2TkHz@h>? z*ArDL2RXNK7wrA>IN1LWTI(A?6Fh?(qw_Ee0eBb92&Ai&JkC;#W~PGtXNpIJY!J2Rq&!>^^&8K`Plw3tp6m!cB?qe#Xw zSe+h5Z+s0TKSZfP4b!D8rsl?BlEw{lE=yJ+;L?-d`uo?7Kg)OG_wUXK=cSc(m~#~x z-^P6+mK>pzv>eQ}lRE-DMpPN2^F2@fWA@oMztq1ez?%a6>5u;vU;wqOkyDG_6W0I$ N002ovPDHLkV1nG11v&r# literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png new file mode 100644 index 0000000000000000000000000000000000000000..7ce524883e021b2fdd90ac698f0b2ad0002d06af GIT binary patch literal 4492 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 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml new file mode 100644 index 000000000..0e21a2eb9 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml @@ -0,0 +1,10 @@ + + ovqt_plugin_tile_editor + TileEditor + 1.0 + Ryzom Core + Tile bank editing plugin. + + + + \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc new file mode 100644 index 000000000..55950d217 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc @@ -0,0 +1,29 @@ + + + images/add_tile.png + images/delete_image.png + images/delete_tile.png + images/replace_image.png + + + images/ic_nel_add_item.png + images/ic_nel_new.png + images/ic_nel_open.png + images/ic_nel_save.png + images/ic_nel_save_as.png + images/down.png + images/left.png + images/reset.png + images/right.png + images/up.png + + + images/rotation0.png + images/rotation90.png + images/rotation180.png + images/rotation270.png + + + images/empty_image.png + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp new file mode 100644 index 000000000..a0faa03f8 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -0,0 +1,171 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "tile_editor_main_window.h" + +#include "nel/misc/path.h" + +#include +#include +#include +#include +#include + +#include "../core/icore.h" +#include "../core/core_constants.h" +#include "../core/menu_manager.h" + +#include "tile_model.h" +#include "tile_item.h" + +TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) + : QMainWindow(parent), + m_ui(new Ui::TileEditorMainWindow) +{ + m_ui->setupUi(this); + m_undoStack = new QUndoStack(this); + + // Retrieve the menu manager + Core::ICore *core = Core::ICore::instance(); + Core::MenuManager *menuManager = core->menuManager(); + + QMenu *m_tileEditorMenu; + // Create tile rotation drop down toolbar menu. + m_rotationMenu = new QMenu(tr("Rotate Tile"), m_ui->toolBar); + m_rotationMenu->setIcon(QIcon(":/tileRotation/images/rotation0.png")); + QList rotateActions; + rotateActions.push_back(m_ui->actionRotateTile0); + rotateActions.push_back(m_ui->actionRotateTile90); + rotateActions.push_back(m_ui->actionRotateTile180); + rotateActions.push_back(m_ui->actionRotateTile270); + m_rotationMenu->addActions(rotateActions); + m_ui->toolBar->addAction(m_rotationMenu->menuAction()); + + // Create the tile zoom menu. + m_zoomMenu = new QMenu(tr("Zoom"), m_ui->toolBar); + QList zoomActions; + + m_tileEditorMenu = new QMenu(tr("Tile Editor"), core->menuManager()->menuBar()); + m_tileDisplayMenu = new QMenu(tr("Tile Display"), m_ui->toolBar); + QList displayActions; + displayActions.push_back(m_ui->actionTileDisplayFilename); + displayActions.push_back(m_ui->actionTileDisplayIndex); + m_ui->actionTileDisplayIndex->setChecked(true); + m_tileDisplayMenu->addActions(displayActions); + m_tileEditorMenu->addMenu(m_tileDisplayMenu); + core->menuManager()->menuBar()->addMenu(m_tileEditorMenu); + + // Set up the list views. + QStringList headers; + headers << "Tile Set"; + m_model = new TileModel(headers, this); + + // Set up the tile set list view. + m_ui->tileSetLV->setModel(m_model); + m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); + connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); + + // 128x128 List View + m_ui->listView128->setModel(m_model); + m_ui->listView128->addAction(m_ui->actionAddTile); + m_ui->listView128->addAction(m_ui->actionDeleteTile); + m_ui->listView128->addAction(m_ui->actionReplaceImage); + m_ui->listView128->addAction(m_ui->actionDeleteImage); + + // Connect context menu actions up. + connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); + connect(m_ui->actionDeleteTile, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteTile(bool))); + connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); + connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); +} + +TileEditorMainWindow::~TileEditorMainWindow() +{ + delete m_ui; + delete m_undoStack; + delete m_rotationMenu; + delete m_zoomMenu; +} + +void TileEditorMainWindow::onActionAddTile(bool triggered) +{ + onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); +} + +void TileEditorMainWindow::onActionDeleteTile(bool triggered) +{ +} + +void TileEditorMainWindow::onActionReplaceImage(bool triggered) +{ +} + +void TileEditorMainWindow::onActionDeleteImage(bool triggered) +{ +} + +void TileEditorMainWindow::onTileSetAdd() +{ + bool ok; + QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); + if (ok && !text.isEmpty()) + { + //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) + //{ + // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); + //} + //else + //{ + + QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); + TileModel *model = static_cast(m_ui->tileSetLV->model()); + + if(index.isValid()) + { + if(!model->insertRow(index.row()+1, index.parent())) + return; + + //updateActions() + + for(int column=0; columncolumnCount(index.parent()); column++) + { + QModelIndex child = model->index(index.row()+1, column, index.parent()); + model->setData(child, QVariant(text), Qt::EditRole); + } + } + else + { + QVector items; + items.push_back(QVariant(text)); + TileItem *item = new TileItem(items, 0); + model->appendRow(item); + //updateActions() + } + + // tileBank.addTileSet( text.toStdString() ); + + // ui.tileSetListWidget->addItem(text); + // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); + //} + } +} + +void TileEditorMainWindow::onActionAddTile(int tabId) +{ + QFileDialog::Options options; + QString selectedFilter; + QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "PNG Bitmap(*.png);;All Files (*.*);;", &selectedFilter, options); +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h new file mode 100644 index 000000000..2f5ce3731 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -0,0 +1,63 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_EDITOR_MAIN_WINDOW_H +#define TILE_EDITOR_MAIN_WINDOW_H + +#include "ui_tile_editor_main_window.h" + +#include "nel/misc/types_nl.h" +#include "nel/misc/sheet_id.h" + +#include + +namespace Ui { + class TileEditorMainWindow; +} + +class TileModel; + +class TileEditorMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit TileEditorMainWindow(QWidget *parent = 0); + ~TileEditorMainWindow(); + + QUndoStack *getUndoStack() { return m_undoStack; } + +public Q_SLOTS: + void onActionAddTile(bool triggered); + void onActionDeleteTile(bool triggered); + void onActionReplaceImage(bool triggered); + void onActionDeleteImage(bool triggered); + void onTileSetAdd(); + +private: + void onActionAddTile(int tabId); + + Ui::TileEditorMainWindow *m_ui; + QUndoStack *m_undoStack; + QMenu *m_rotationMenu; + QMenu *m_zoomMenu; + QMenu *m_tileDisplayMenu; + QMenu *m_tileEditorMenu; + + TileModel *m_model; +}; + +#endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui new file mode 100644 index 000000000..7b76e6aaa --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -0,0 +1,663 @@ + + + TileEditorMainWindow + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + 0 + + + + 128x128 + + + + + + Qt::ActionsContextMenu + + + + + + + Edit Channel + + + + + + Diffuse + + + true + + + + + + + Additive + + + + + + + + + + + 256x256 + + + + + + + + + Edit Channel + + + + + + Diffuse + + + true + + + true + + + + + + + Additive + + + + + + + + + + + Transition + + + + + + + + + Edit Channel + + + + + + Diffuse + + + true + + + + + + + Additive + + + + + + + Alpha + + + + + + + + + + + Displacement + + + + + + + + + + Tile Set Details + + + + + + Qt::LeftToRight + + + Oriented + + + + + + + + + + Surface Data: + + + + + + + Vegetation Set: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + + + + + + + + :/newPrefix/reset.png:/newPrefix/reset.png + + + + + + + + + + + + + Tile Editor Tool Bar + + + TopToolBarArea + + + false + + + + + + + + + Tile Bank + + + 1 + + + + + + + Lands + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + + :/movementIcons/images/ic_nel_add_item.png:/movementIcons/images/ic_nel_add_item.png + + + + + + + ... + + + + :/movementIcons/images/reset.png:/movementIcons/images/reset.png + + + + + + + ... + + + + :/movementIcons/images/ic_nel_open.png:/movementIcons/images/ic_nel_open.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Tile Sets + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + ... + + + + :/movementIcons/images/up.png:/movementIcons/images/up.png + + + + + + + ... + + + + :/movementIcons/images/down.png:/movementIcons/images/down.png + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + ... + + + + :/movementIcons/images/ic_nel_add_item.png:/movementIcons/images/ic_nel_add_item.png + + + + + + + ... + + + + :/movementIcons/images/reset.png:/movementIcons/images/reset.png + + + + + + + ... + + + + :/movementIcons/images/ic_nel_open.png:/movementIcons/images/ic_nel_open.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + ... + + + + + + + ... + + + + + + + + + Tile Bank Texture Path + + + + + + + + + + + + + + + + :/movementIcons/images/ic_nel_open.png:/movementIcons/images/ic_nel_open.png + + + Open Tile Bank + + + Open Tile Bank + + + + + + :/tileRotation/images/rotation0.png:/tileRotation/images/rotation0.png + + + 0 + + + Rotate Tile 0 Degrees + + + + + + :/movementIcons/images/ic_nel_save.png:/movementIcons/images/ic_nel_save.png + + + Save Tile Bank + + + Save Tile Bank + + + + + + :/movementIcons/images/ic_nel_save_as.png:/movementIcons/images/ic_nel_save_as.png + + + Save Tile Bank As... + + + Save Tile Bank As... + + + + + + :/tileRotation/images/rotation90.png:/tileRotation/images/rotation90.png + + + 90 + + + Rotate Tile 90 Degrees + + + + + + :/tileRotation/images/rotation180.png:/tileRotation/images/rotation180.png + + + 180 + + + Rotate Tile180 Degrees + + + + + + :/tileRotation/images/rotation270.png:/tileRotation/images/rotation270.png + + + 270 + + + Rotate Tile 270 Degrees + + + + + Batch Load + + + Batch Load + + + + + Import Border + + + Import Border + + + + + Export Border + + + Export Border + + + + + true + + + Index + + + Display Tile Index + + + + + true + + + Filename + + + Display Tile Filename + + + + + + :/tileTools/images/add_tile.png:/tileTools/images/add_tile.png + + + Add Tile + + + Add Tile + + + + + + :/tileTools/images/delete_tile.png:/tileTools/images/delete_tile.png + + + Delete Tile + + + Delete Tile + + + + + + :/tileTools/images/replace_image.png:/tileTools/images/replace_image.png + + + Replace Image + + + Replace Image + + + + + + :/tileTools/images/delete_image.png:/tileTools/images/delete_image.png + + + Delete Image + + + Delete Image + + + + + + + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp new file mode 100644 index 000000000..ac12766b8 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp @@ -0,0 +1,75 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "tile_editor_plugin.h" +#include "tile_editor_main_window.h" +#include "../core/icore.h" +#include "../core/menu_manager.h" +#include "../core/core_constants.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +// NeL includes +#include "nel/misc/debug.h" + +using namespace TileEditorPluginQt; + +TileEditorPlugin::~TileEditorPlugin() +{ + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); +} + +bool TileEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + Q_UNUSED(errorString); + m_plugMan = pluginManager; + addAutoReleasedObject(new TileEditorContext()); + return true; +} + +void TileEditorPlugin::extensionsInitialized() +{ +} + +void TileEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_LibContext = new NLMISC::CLibraryContext(*nelContext); +} + +void TileEditorPlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +Q_EXPORT_PLUGIN(TileEditorPlugin) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h new file mode 100644 index 000000000..2398be2c4 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h @@ -0,0 +1,109 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_EDITOR_PLUGIN_H +#define TILE_EDITOR_PLUGIN_H + +#include "../../extension_system/iplugin.h" +#include "../core/icontext.h" + +#include "nel/misc/app_context.h" + +#include "tile_editor_main_window.h" + +#include + +namespace NLMISC +{ +class CLibraryContext; +} + +namespace TileEditorPluginQt +{ + +class TileEditorPlugin : public QObject, public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_INTERFACES(ExtensionSystem::IPlugin) +public: + + ~TileEditorPlugin(); + + bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); + void extensionsInitialized(); + void setNelContext(NLMISC::INelContext *nelContext); + + void addAutoReleasedObject(QObject *obj); + +protected: + NLMISC::CLibraryContext *m_LibContext; + +private: + ExtensionSystem::IPluginManager *m_plugMan; + QList m_autoReleaseObjects; + +}; + +class TileEditorContext: public Core::IContext +{ + Q_OBJECT +public: + TileEditorContext(QObject *parent = 0) : IContext(parent) + { + m_tileEditorMainWindow = new TileEditorMainWindow(); + } + + virtual ~TileEditorContext() + { + delete m_tileEditorMainWindow; + } + + virtual QString id() const + { + return QLatin1String("TileEditor"); + } + + virtual QString trName() const + { + return tr("Tile Editor"); + } + + virtual QIcon icon() const + { + return QIcon(":/tileRotation/images/rotation0.png"); + } + + virtual QUndoStack *undoStack() + { + return m_tileEditorMainWindow->getUndoStack(); + } + + virtual void open() + { + } + + virtual QWidget *widget() + { + return m_tileEditorMainWindow; + } + +private: + TileEditorMainWindow *m_tileEditorMainWindow; +}; + +} // namespace TileEditorPluginQt + +#endif // TILE_EDITOR_PLUGIN_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp new file mode 100644 index 000000000..d6c87017d --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -0,0 +1,138 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "tile_item.h" + +TileItem::TileItem(const QVector &data, TileItem *parent) +{ + parentItem = parent; + itemData = data; +} + +TileItem::~TileItem() +{ + qDeleteAll(childItems); +} + +void TileItem::appendChild(TileItem *item) +{ + childItems.append(item); +} + +TileItem *TileItem::child(int row) +{ + return childItems.value(row); +} + +int TileItem::childCount() const +{ + return childItems.count(); +} + +int TileItem::childNumber() const +{ + if(parentItem) + return parentItem->childItems.indexOf(const_cast(this)); + return 0; +} + +bool TileItem::insertChildren(int position, int count, int columns) +{ + if(position<0 || position>childItems.size()) + return false; + + for(int row = 0; row < count; row++) + { + QVector data(columns); + TileItem *item = new TileItem(data, this); + childItems.insert(position, item); + } + + return true; +} + +bool TileItem::removeChildren(int position, int count) +{ + if(position<0 || position+count>childItems.size()) + return false; + + for(int row=0; row itemData.size()) + return false; + + for(int column=0; columninsertColumns(position, columns); + + return true; +} + +int TileItem::row() const +{ + if(parentItem) + return parentItem->childItems.indexOf(const_cast(this)); + + return 0; +} + +int TileItem::columnCount() const +{ + return itemData.count(); +} + +QVariant TileItem::data(int column) const +{ + return itemData.value(column); +} + +bool TileItem::setData(int column, const QVariant &value) +{ + if(column < 0 || column >= itemData.size()) + return false; + + itemData[column] = value; + return true; +} + +TileItem *TileItem::parent() +{ + return parentItem; +} + +void TileItem::appendRow(const QList &items) +{ + Q_FOREACH(TileItem *item, items) + appendRow(item); +} + +void TileItem::appendRow(TileItem *item) +{ + childItems.append(item); +} +//QImage *TileItem::getTileImageFromChannel(int channel) +//{ +// return m_tileChannels[channel]; +//} + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h new file mode 100644 index 000000000..4d9f13e0f --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -0,0 +1,66 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_ITEM_H +#define TILE_ITEM_H + +#include "nel/misc/types_nl.h" + +#include +#include + +class TileItem +{ +public: + + TileItem(const QVector &data, TileItem *parent=0); + ~TileItem(); + + void appendChild(TileItem *child); + + TileItem *child(int row); + int childCount() const; + int childNumber() const; + int columnCount() const; + bool setData(int column, const QVariant &value); + QVariant data(int column) const; + + bool insertChildren(int position, int count, int columns); + bool removeChildren(int position, int count); + bool insertColumns(int position, int columns); + + int row() const; + TileItem *parent(); + + void appendRow(const QList &items); + void appendRow(TileItem *item); + + //QImage *getTileImageFromChannel(int channel); + + //int getTileIndex() { return m_tileIndex; } + //QString getTileFilename() { return m_tileFilename; } + +private: + QList childItems; + QVector itemData; + TileItem *parentItem; + + //QMap m_tileChannels; + //int m_tileIndex; + //QString m_tileFilename; +}; + +#endif // TILE_ITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp new file mode 100644 index 000000000..20911310c --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -0,0 +1,123 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "tile_model.h" +#include "tile_item.h" + +#include + +TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) +{ + QVector rootData; + Q_FOREACH(QString header, headers) + rootData << header; + + rootItem = new TileItem(rootData); +} + +TileModel::~TileModel() +{ + delete rootItem; +} + +TileItem *TileModel::getItem(const QModelIndex &index) const +{ + if(index.isValid()) + { + TileItem *item = static_cast(index.internalPointer()); + if(item) return item; + } + return rootItem; +} + +QModelIndex TileModel::index(int row, int column, const QModelIndex &parent) const +{ + if(parent.isValid() && parent.column() != 0) + return QModelIndex(); + + TileItem *parentItem = getItem(parent); + + TileItem *childItem = parentItem->child(row); + if(childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); +} + +QModelIndex TileModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + TileItem *childItem = getItem(index); + TileItem *parentItem = childItem->parent(); + + if(parentItem == rootItem) + return QModelIndex(); + + return createIndex(parentItem->childNumber(), 0, parentItem); +} + +int TileModel::rowCount(const QModelIndex &parent) const +{ + TileItem *parentItem = getItem(parent); + return parentItem->childCount(); +} + +int TileModel::columnCount(const QModelIndex &parent) const +{ + TileItem *parentItem = getItem(parent); + return parentItem->columnCount(); +} + +QVariant TileModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if(role != Qt::DisplayRole) + return QVariant(); + + TileItem *item = static_cast(index.internalPointer()); + return item->data(index.column()); +} + +Qt::ItemFlags TileModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) + return Qt::ItemIsEnabled; + + return Qt::ItemIsEnabled|Qt::ItemIsSelectable; +} + +QVariant TileModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if(orientation == Qt::Horizontal && role == Qt::DisplayRole) + return rootItem->data(section); + + return QVariant(); +} + +void TileModel::appendRow(const QList &items) +{ + rootItem->appendRow(items); +} + + +void TileModel::appendRow(TileItem *item) +{ + rootItem->appendRow(item); +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h new file mode 100644 index 000000000..692d1ee65 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -0,0 +1,54 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TILE_MODEL_H +#define TILE_MODEL_H + +#include "nel/misc/types_nl.h" + +#include + +class TileItem; + +class TileModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + TileModel::TileModel(const QStringList &headers, QObject *parent); + ~TileModel(); + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex &parent= QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + // Tile Model specific functions + void appendRow(const QList &items); + void appendRow(TileItem *item); + +private: + TileItem *getItem(const QModelIndex &index) const; + + //QList m_tiles; + //int m_activeEditChannel; + TileItem *rootItem; +}; + +#endif // TILE_128_MODEL_H From dfc71de78632bf60f4a31d1818af3c9426ff9c69 Mon Sep 17 00:00:00 2001 From: sfb Date: Wed, 7 Dec 2011 13:46:27 -0600 Subject: [PATCH 002/220] Changed: #1409 Tile Edit Qt - Adding some of the hierarchy logic to the list views. --- .../tile_editor/tile_editor_main_window.cpp | 98 +++++++++++++++---- .../tile_editor/tile_editor_main_window.h | 1 + .../tile_editor/tile_editor_main_window.ui | 2 +- .../src/plugins/tile_editor/tile_item.cpp | 30 ++++++ .../src/plugins/tile_editor/tile_item.h | 13 ++- 5 files changed, 122 insertions(+), 22 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index a0faa03f8..afeaadb1d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -75,8 +75,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Set up the tile set list view. m_ui->tileSetLV->setModel(m_model); - m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); + //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); + connect(m_ui->tileSetLV->selectionModel(), + SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View m_ui->listView128->setModel(m_model); @@ -130,30 +133,71 @@ void TileEditorMainWindow::onTileSetAdd() //else //{ - QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); + //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); TileModel *model = static_cast(m_ui->tileSetLV->model()); - if(index.isValid()) - { - if(!model->insertRow(index.row()+1, index.parent())) - return; + //if(index.isValid()) + //{ + // if(!model->insertRow(index.row()+1, index.parent())) + // return; - //updateActions() + // //updateActions() - for(int column=0; columncolumnCount(index.parent()); column++) - { - QModelIndex child = model->index(index.row()+1, column, index.parent()); - model->setData(child, QVariant(text), Qt::EditRole); - } - } - else - { + // for(int column=0; columncolumnCount(index.parent()); column++) + // { + // QModelIndex child = model->index(index.row()+1, column, index.parent()); + // model->setData(child, QVariant(text), Qt::EditRole); + // } + //} + //else + //{ + // Create the new tile set. QVector items; - items.push_back(QVariant(text)); - TileItem *item = new TileItem(items, 0); - model->appendRow(item); + items.push_back(text); + TileItem *tileSet = new TileItem(items); + + // child for 128x128 tiles + QVector tiles128; + tiles128.push_back(QString("128")); + TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); + + // child for 256x256 tiles + QVector tiles256; + tiles256.push_back(QString("256")); + TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); + + + // child for transition tiles. + QVector tilesTrans; + tilesTrans.push_back(QString("Transition")); + TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); + + // Add the default transition tiles. + // TODO tie this to CTileSet::count from NeL + for(int transPos=0; transPos < 48; transPos++) + { + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); + TileItem *transTile= new TileItem(tileInfo); + tileTrans->appendRow(transTile); + } + + // child for displacement tiles + QVector tilesDisp; + tilesDisp.push_back(QString("Displacement")); + TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); + + // Append them in the correct order to the tile set. + tileSet->appendRow(tile128); + tileSet->appendRow(tile256); + tileSet->appendRow(tileTrans); + tileSet->appendRow(tileDisp); + + model->appendRow(tileSet); + + m_ui->tileSetLV->reset(); //updateActions() - } + //} // tileBank.addTileSet( text.toStdString() ); @@ -168,4 +212,20 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QFileDialog::Options options; QString selectedFilter; QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "PNG Bitmap(*.png);;All Files (*.*);;", &selectedFilter, options); +} + +void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) +{ + + QModelIndex tile128Idx = newIndex.child(0,0); + QModelIndex tile256Idx = newIndex.child(1,0); + QModelIndex tileTransIdx = newIndex.child(2,0); + QModelIndex tileDispIdx = newIndex.child(3,0); + + + m_ui->listView128->setRootIndex(newIndex); + m_ui->listView256->setRootIndex(tile256Idx); + m_ui->listViewTransition->setRootIndex(tileTransIdx); + m_ui->listViewDisplacement->setRootIndex(tileDispIdx); +// m_ui->listView128->setModelColumn } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 2f5ce3731..267eff50c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -46,6 +46,7 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); private: void onActionAddTile(int tabId); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index 7b76e6aaa..d9b8d7116 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -468,7 +468,7 @@ - + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index d6c87017d..ee255755b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -16,6 +16,8 @@ #include "tile_item.h" +#include + TileItem::TileItem(const QVector &data, TileItem *parent) { parentItem = parent; @@ -121,6 +123,11 @@ TileItem *TileItem::parent() return parentItem; } +void TileItem::setParent(TileItem *parent) +{ + parentItem = parent; +} + void TileItem::appendRow(const QList &items) { Q_FOREACH(TileItem *item, items) @@ -129,10 +136,33 @@ void TileItem::appendRow(const QList &items) void TileItem::appendRow(TileItem *item) { + nlinfo("number of children: %d", childItems.size()); + item->setParent(this); childItems.append(item); + nlinfo("number of children: %d", childItems.size()); } //QImage *TileItem::getTileImageFromChannel(int channel) //{ // return m_tileChannels[channel]; //} + +/////////////////////////////////////////////////// + +TileTypeTileItem::TileTypeTileItem(const QVector &data, TileItem *parent) : TileItem(data,parent) +{ +} + +TileTypeTileItem::~TileTypeTileItem() +{ + qDeleteAll(childItems); +} + +QVariant TileTypeTileItem::data(int column) const +{ + QVariant val = itemData.value(column); + + nlinfo("the column is %d and the value is '%s'. there are %d values", + column, val.toString().toStdString().c_str(), itemData.size()); + return itemData.value(column); +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h index 4d9f13e0f..8f1c6a61a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -27,7 +27,7 @@ class TileItem public: TileItem(const QVector &data, TileItem *parent=0); - ~TileItem(); + virtual ~TileItem(); void appendChild(TileItem *child); @@ -44,6 +44,7 @@ public: int row() const; TileItem *parent(); + void setParent(TileItem *parent); void appendRow(const QList &items); void appendRow(TileItem *item); @@ -53,7 +54,7 @@ public: //int getTileIndex() { return m_tileIndex; } //QString getTileFilename() { return m_tileFilename; } -private: +protected: QList childItems; QVector itemData; TileItem *parentItem; @@ -63,4 +64,12 @@ private: //QString m_tileFilename; }; +class TileTypeTileItem : public TileItem +{ +public: + TileTypeTileItem(const QVector &data, TileItem *parent=0); + virtual ~TileTypeTileItem(); + QVariant data(int column) const; +}; + #endif // TILE_ITEM_H From ceb8f7997d95d9a3cd9a9fc8a3f99a85b94d3ac1 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 9 Dec 2011 07:03:33 -0600 Subject: [PATCH 003/220] Changed: #1409 Made the tile set and tile type tabs connect. Added the context menu to each tab. --- .../tile_editor/tile_editor_main_window.cpp | 46 +++++++++++++++---- .../tile_editor/tile_editor_main_window.ui | 28 +++++++++-- .../src/plugins/tile_editor/tile_item.cpp | 8 +--- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index afeaadb1d..48e8ff36f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -87,6 +87,27 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView128->addAction(m_ui->actionDeleteTile); m_ui->listView128->addAction(m_ui->actionReplaceImage); m_ui->listView128->addAction(m_ui->actionDeleteImage); + + // 256x256 List View + m_ui->listView256->setModel(m_model); + m_ui->listView256->addAction(m_ui->actionAddTile); + m_ui->listView256->addAction(m_ui->actionDeleteTile); + m_ui->listView256->addAction(m_ui->actionReplaceImage); + m_ui->listView256->addAction(m_ui->actionDeleteImage); + + // Transition List View + m_ui->listViewTransition->setModel(m_model); + //m_ui->listViewTransition->addAction(m_ui->actionAddTile); + //m_ui->listViewTransition->addAction(m_ui->actionDeleteTile); + m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); + m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); + + // Displacement List View + m_ui->listViewDisplacement->setModel(m_model); + //m_ui->listViewDisplacement->addAction(m_ui->actionAddTile); + //m_ui->listViewDisplacement->addAction(m_ui->actionDeleteTile); + m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); + m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); // Connect context menu actions up. connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); @@ -174,7 +195,7 @@ void TileEditorMainWindow::onTileSetAdd() // Add the default transition tiles. // TODO tie this to CTileSet::count from NeL - for(int transPos=0; transPos < 48; transPos++) + for(int transPos=0; transPos<48; transPos++) { QVector tileInfo; tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); @@ -187,6 +208,16 @@ void TileEditorMainWindow::onTileSetAdd() tilesDisp.push_back(QString("Displacement")); TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); + // Add the default displacement tiles. + // TODO tie this to CTileSet::CountDisplace from NeL + for(int dispPos=0; dispPos<16; dispPos++) + { + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); + TileItem *dispTile= new TileItem(tileInfo); + tileDisp->appendRow(dispTile); + } + // Append them in the correct order to the tile set. tileSet->appendRow(tile128); tileSet->appendRow(tile256); @@ -216,16 +247,13 @@ void TileEditorMainWindow::onActionAddTile(int tabId) void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { - - QModelIndex tile128Idx = newIndex.child(0,0); - QModelIndex tile256Idx = newIndex.child(1,0); - QModelIndex tileTransIdx = newIndex.child(2,0); - QModelIndex tileDispIdx = newIndex.child(3,0); + QModelIndex &tile128Idx = newIndex.child(0,0); + QModelIndex &tile256Idx = newIndex.child(1,0); + QModelIndex &tileTransIdx = newIndex.child(2,0); + QModelIndex &tileDispIdx = newIndex.child(3,0); - - m_ui->listView128->setRootIndex(newIndex); + m_ui->listView128->setRootIndex(tile128Idx); m_ui->listView256->setRootIndex(tile256Idx); m_ui->listViewTransition->setRootIndex(tileTransIdx); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); -// m_ui->listView128->setModelColumn } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index d9b8d7116..5897d29be 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -18,7 +18,7 @@ - 0 + 2 @@ -66,7 +66,11 @@ - + + + Qt::ActionsContextMenu + + @@ -105,7 +109,17 @@ - + + + Qt::ActionsContextMenu + + + QListView::LeftToRight + + + QListView::Batched + + @@ -148,7 +162,11 @@ - + + + Qt::ActionsContextMenu + + @@ -468,7 +486,7 @@ - + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index ee255755b..5758b9280 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -36,6 +36,7 @@ void TileItem::appendChild(TileItem *item) TileItem *TileItem::child(int row) { + //nlinfo("row %d and size %d", row, childItems.size()); return childItems.value(row); } @@ -136,16 +137,9 @@ void TileItem::appendRow(const QList &items) void TileItem::appendRow(TileItem *item) { - nlinfo("number of children: %d", childItems.size()); item->setParent(this); childItems.append(item); - nlinfo("number of children: %d", childItems.size()); } -//QImage *TileItem::getTileImageFromChannel(int channel) -//{ -// return m_tileChannels[channel]; -//} - /////////////////////////////////////////////////// From c9bf8088b41d19287044ffe163f62b429fb86374 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 9 Dec 2011 08:10:02 -0600 Subject: [PATCH 004/220] Changed: #1409 Fixed some things for a sane compiler (Linux/gcc) --- .../tile_editor/tile_editor_main_window.cpp | 200 +++++++++--------- .../src/plugins/tile_editor/tile_model.h | 4 +- 2 files changed, 102 insertions(+), 102 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 48e8ff36f..12596e1bb 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -39,7 +39,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_undoStack = new QUndoStack(this); // Retrieve the menu manager - Core::ICore *core = Core::ICore::instance(); + Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); QMenu *m_tileEditorMenu; @@ -77,8 +77,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); - connect(m_ui->tileSetLV->selectionModel(), - SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), + connect(m_ui->tileSetLV->selectionModel(), + SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View @@ -143,98 +143,98 @@ void TileEditorMainWindow::onActionDeleteImage(bool triggered) void TileEditorMainWindow::onTileSetAdd() { - bool ok; - QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); - if (ok && !text.isEmpty()) - { - //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) - //{ - // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); - //} - //else - //{ - - //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); - TileModel *model = static_cast(m_ui->tileSetLV->model()); - - //if(index.isValid()) - //{ - // if(!model->insertRow(index.row()+1, index.parent())) - // return; - - // //updateActions() - - // for(int column=0; columncolumnCount(index.parent()); column++) - // { - // QModelIndex child = model->index(index.row()+1, column, index.parent()); - // model->setData(child, QVariant(text), Qt::EditRole); - // } - //} - //else - //{ - // Create the new tile set. - QVector items; - items.push_back(text); - TileItem *tileSet = new TileItem(items); - - // child for 128x128 tiles - QVector tiles128; - tiles128.push_back(QString("128")); - TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); - - // child for 256x256 tiles - QVector tiles256; - tiles256.push_back(QString("256")); - TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); - - - // child for transition tiles. - QVector tilesTrans; - tilesTrans.push_back(QString("Transition")); - TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); - - // Add the default transition tiles. - // TODO tie this to CTileSet::count from NeL - for(int transPos=0; transPos<48; transPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); - TileItem *transTile= new TileItem(tileInfo); - tileTrans->appendRow(transTile); - } - - // child for displacement tiles - QVector tilesDisp; - tilesDisp.push_back(QString("Displacement")); - TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); - - // Add the default displacement tiles. - // TODO tie this to CTileSet::CountDisplace from NeL - for(int dispPos=0; dispPos<16; dispPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); - TileItem *dispTile= new TileItem(tileInfo); - tileDisp->appendRow(dispTile); - } - - // Append them in the correct order to the tile set. - tileSet->appendRow(tile128); - tileSet->appendRow(tile256); - tileSet->appendRow(tileTrans); - tileSet->appendRow(tileDisp); - - model->appendRow(tileSet); - - m_ui->tileSetLV->reset(); - //updateActions() - //} - - // tileBank.addTileSet( text.toStdString() ); - - // ui.tileSetListWidget->addItem(text); - // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); - //} + bool ok; + QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); + if (ok && !text.isEmpty()) + { + //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) + //{ + // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); + //} + //else + //{ + + //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); + TileModel *model = static_cast(m_ui->tileSetLV->model()); + + //if(index.isValid()) + //{ + // if(!model->insertRow(index.row()+1, index.parent())) + // return; + + // //updateActions() + + // for(int column=0; columncolumnCount(index.parent()); column++) + // { + // QModelIndex child = model->index(index.row()+1, column, index.parent()); + // model->setData(child, QVariant(text), Qt::EditRole); + // } + //} + //else + //{ + // Create the new tile set. + QVector items; + items.push_back(text); + TileItem *tileSet = new TileItem(items); + + // child for 128x128 tiles + QVector tiles128; + tiles128.push_back(QString("128")); + TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); + + // child for 256x256 tiles + QVector tiles256; + tiles256.push_back(QString("256")); + TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); + + + // child for transition tiles. + QVector tilesTrans; + tilesTrans.push_back(QString("Transition")); + TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); + + // Add the default transition tiles. + // TODO tie this to CTileSet::count from NeL + for(int transPos=0; transPos<48; transPos++) + { + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); + TileItem *transTile= new TileItem(tileInfo); + tileTrans->appendRow(transTile); + } + + // child for displacement tiles + QVector tilesDisp; + tilesDisp.push_back(QString("Displacement")); + TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); + + // Add the default displacement tiles. + // TODO tie this to CTileSet::CountDisplace from NeL + for(int dispPos=0; dispPos<16; dispPos++) + { + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); + TileItem *dispTile= new TileItem(tileInfo); + tileDisp->appendRow(dispTile); + } + + // Append them in the correct order to the tile set. + tileSet->appendRow(tile128); + tileSet->appendRow(tile256); + tileSet->appendRow(tileTrans); + tileSet->appendRow(tileDisp); + + model->appendRow(tileSet); + + m_ui->tileSetLV->reset(); + //updateActions() + //} + + // tileBank.addTileSet( text.toStdString() ); + + // ui.tileSetListWidget->addItem(text); + // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); + //} } } @@ -247,13 +247,13 @@ void TileEditorMainWindow::onActionAddTile(int tabId) void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { - QModelIndex &tile128Idx = newIndex.child(0,0); - QModelIndex &tile256Idx = newIndex.child(1,0); - QModelIndex &tileTransIdx = newIndex.child(2,0); - QModelIndex &tileDispIdx = newIndex.child(3,0); + const QModelIndex &tile128Idx = newIndex.child(0,0); + const QModelIndex &tile256Idx = newIndex.child(1,0); + const QModelIndex &tileTransIdx = newIndex.child(2,0); + const QModelIndex &tileDispIdx = newIndex.child(3,0); m_ui->listView128->setRootIndex(tile128Idx); m_ui->listView256->setRootIndex(tile256Idx); m_ui->listViewTransition->setRootIndex(tileTransIdx); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); -} \ No newline at end of file +} diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index 692d1ee65..140f60555 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -28,8 +28,8 @@ class TileModel : public QAbstractItemModel Q_OBJECT public: - TileModel::TileModel(const QStringList &headers, QObject *parent); - ~TileModel(); + TileModel(const QStringList &headers, QObject *parent); + ~TileModel(); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; Qt::ItemFlags flags(const QModelIndex &index) const; From eaa6882d4e99b4dd45cb27fcf66077440d70b36d Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 22 Dec 2011 19:58:59 -0600 Subject: [PATCH 005/220] Changed: #1409 Added hierarchy to the tile model, renamed the base class to 'Node' --- .../tile_editor/tile_editor_main_window.cpp | 71 +------- .../src/plugins/tile_editor/tile_item.cpp | 172 ++++++++++++------ .../src/plugins/tile_editor/tile_item.h | 88 ++++++--- .../src/plugins/tile_editor/tile_model.cpp | 68 +++++-- .../src/plugins/tile_editor/tile_model.h | 15 +- 5 files changed, 254 insertions(+), 160 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 12596e1bb..427fda7a9 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -97,15 +97,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Transition List View m_ui->listViewTransition->setModel(m_model); - //m_ui->listViewTransition->addAction(m_ui->actionAddTile); - //m_ui->listViewTransition->addAction(m_ui->actionDeleteTile); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View m_ui->listViewDisplacement->setModel(m_model); - //m_ui->listViewDisplacement->addAction(m_ui->actionAddTile); - //m_ui->listViewDisplacement->addAction(m_ui->actionDeleteTile); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -172,69 +168,11 @@ void TileEditorMainWindow::onTileSetAdd() //} //else //{ - // Create the new tile set. - QVector items; - items.push_back(text); - TileItem *tileSet = new TileItem(items); - // child for 128x128 tiles - QVector tiles128; - tiles128.push_back(QString("128")); - TileTypeTileItem *tile128= new TileTypeTileItem(tiles128); - - // child for 256x256 tiles - QVector tiles256; - tiles256.push_back(QString("256")); - TileTypeTileItem *tile256= new TileTypeTileItem(tiles256); + TileSetNode *tileSet = model->createTileSetNode(text); - // child for transition tiles. - QVector tilesTrans; - tilesTrans.push_back(QString("Transition")); - TileTypeTileItem *tileTrans= new TileTypeTileItem(tilesTrans); - - // Add the default transition tiles. - // TODO tie this to CTileSet::count from NeL - for(int transPos=0; transPos<48; transPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); - TileItem *transTile= new TileItem(tileInfo); - tileTrans->appendRow(transTile); - } - - // child for displacement tiles - QVector tilesDisp; - tilesDisp.push_back(QString("Displacement")); - TileTypeTileItem *tileDisp= new TileTypeTileItem(tilesDisp); - - // Add the default displacement tiles. - // TODO tie this to CTileSet::CountDisplace from NeL - for(int dispPos=0; dispPos<16; dispPos++) - { - QVector tileInfo; - tileInfo.push_back(QString("filename").append(QString::number(dispPos+1))); - TileItem *dispTile= new TileItem(tileInfo); - tileDisp->appendRow(dispTile); - } - - // Append them in the correct order to the tile set. - tileSet->appendRow(tile128); - tileSet->appendRow(tile256); - tileSet->appendRow(tileTrans); - tileSet->appendRow(tileDisp); - - model->appendRow(tileSet); - - m_ui->tileSetLV->reset(); - //updateActions() - //} - - // tileBank.addTileSet( text.toStdString() ); - - // ui.tileSetListWidget->addItem(text); - // ui.tileSetListWidget->setCurrentRow(ui.tileSetListWidget->count() - 1); - //} + m_ui->tileSetLV->reset(); } } @@ -256,4 +194,9 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->listView256->setRootIndex(tile256Idx); m_ui->listViewTransition->setRootIndex(tileTransIdx); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); + + m_ui->listView128->reset(); + m_ui->listView256->reset(); + m_ui->listViewTransition->reset(); + m_ui->listViewDisplacement->reset(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index 5758b9280..289bc4a83 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -18,145 +18,213 @@ #include -TileItem::TileItem(const QVector &data, TileItem *parent) +Node::Node() : m_parentItem(0) { - parentItem = parent; - itemData = data; } -TileItem::~TileItem() +Node::Node(const QVector &data, Node *parent) { - qDeleteAll(childItems); + m_parentItem = parent; + m_itemData = data; } -void TileItem::appendChild(TileItem *item) +Node::~Node() { - childItems.append(item); + qDeleteAll(m_childItems); } -TileItem *TileItem::child(int row) +void Node::appendChild(Node *item) +{ + m_childItems.append(item); +} + +Node *Node::child(int row) { //nlinfo("row %d and size %d", row, childItems.size()); - return childItems.value(row); + return m_childItems.value(row); } -int TileItem::childCount() const +int Node::childCount() const { - return childItems.count(); + return m_childItems.count(); } -int TileItem::childNumber() const +int Node::childNumber() const { - if(parentItem) - return parentItem->childItems.indexOf(const_cast(this)); + if(m_parentItem) + return m_parentItem->m_childItems.indexOf(const_cast(this)); return 0; } -bool TileItem::insertChildren(int position, int count, int columns) +bool Node::insertChildren(int position, int count, int columns) { - if(position<0 || position>childItems.size()) + if(position<0 || position>m_childItems.size()) return false; for(int row = 0; row < count; row++) { QVector data(columns); - TileItem *item = new TileItem(data, this); - childItems.insert(position, item); + Node *item = new Node(data, this); + m_childItems.insert(position, item); } return true; } -bool TileItem::removeChildren(int position, int count) +bool Node::removeChildren(int position, int count) { - if(position<0 || position+count>childItems.size()) + if(position<0 || position+count>m_childItems.size()) return false; for(int row=0; row itemData.size()) + if(position<0 || position > m_itemData.size()) return false; for(int column=0; columninsertColumns(position, columns); return true; } -int TileItem::row() const +int Node::row() const { - if(parentItem) - return parentItem->childItems.indexOf(const_cast(this)); + if(m_parentItem) + return m_parentItem->m_childItems.indexOf(const_cast(this)); return 0; } -int TileItem::columnCount() const +int Node::columnCount() const { - return itemData.count(); + return m_itemData.count(); } -QVariant TileItem::data(int column) const +QVariant Node::data(int column) const { - return itemData.value(column); + return m_itemData.value(column); } -bool TileItem::setData(int column, const QVariant &value) +bool Node::setData(int column, const QVariant &value) { - if(column < 0 || column >= itemData.size()) + if(column < 0 || column >= m_itemData.size()) return false; - itemData[column] = value; + m_itemData[column] = value; return true; } -TileItem *TileItem::parent() +Node *Node::parent() { - return parentItem; + return m_parentItem; } -void TileItem::setParent(TileItem *parent) +void Node::setParent(Node *parent) { - parentItem = parent; + m_parentItem = parent; } -void TileItem::appendRow(const QList &items) +void Node::appendRow(const QList &items) { - Q_FOREACH(TileItem *item, items) + Q_FOREACH(Node *item, items) appendRow(item); } -void TileItem::appendRow(TileItem *item) +void Node::appendRow(Node *item) { item->setParent(this); - childItems.append(item); + m_childItems.append(item); } /////////////////////////////////////////////////// -TileTypeTileItem::TileTypeTileItem(const QVector &data, TileItem *parent) : TileItem(data,parent) +TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) { + m_parentItem = parent; } -TileTypeTileItem::~TileTypeTileItem() +TileSetNode::~TileSetNode() { - qDeleteAll(childItems); + qDeleteAll(m_childItems); } -QVariant TileTypeTileItem::data(int column) const +QVariant TileSetNode::data(int column) const { - QVariant val = itemData.value(column); + return QVariant(m_tileSetName); +} - nlinfo("the column is %d and the value is '%s'. there are %d values", - column, val.toString().toStdString().c_str(), itemData.size()); - return itemData.value(column); -} \ No newline at end of file +/////////////////////////////////////////////////// + +TileTypeNode::TileTypeNode(TNodeTileType type, Node *parent) : m_nodeTileType(type) +{ + m_parentItem = parent; +} + +TileTypeNode::~TileTypeNode() +{ + qDeleteAll(m_childItems); +} + +QVariant TileTypeNode::data(int column) const +{ + return QVariant(getTileTypeName(m_nodeTileType)); +} + +TileTypeNode::TNodeTileType TileTypeNode::getTileType() +{ + return m_nodeTileType; +} + + +const char *TileTypeNode::getTileTypeName(TNodeTileType type) +{ + switch(type) + { + case Tile128: + return "128"; + case Tile256: + return "256"; + case TileTransition: + return "Transition"; + case TileDisplacement: + return "Displacement"; + default: + break; + } + return "UNKNOWN"; +} + +/////////////////////////////////////////////////// + +TileItemNode::TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) +{ + m_tileFilename[channel] = filename; + m_parentItem = parent; + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); +} + +TileItemNode::~TileItemNode() +{ + qDeleteAll(m_childItems); +} + +void TileItemNode::setTileFilename(TTileChannel channel, QString filename) +{ + m_tileFilename[channel] = filename; +} + +QVariant TileItemNode::data(int column) const +{ + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); + // find some way to know which file/bitmap to display + return QVariant(m_tileFilename[TileDiffuse]); +} diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h index 8f1c6a61a..eceb38a79 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -22,54 +22,90 @@ #include #include -class TileItem +class Node { public: + Node(); + Node(const QVector &data, Node *parent=0); + virtual ~Node(); - TileItem(const QVector &data, TileItem *parent=0); - virtual ~TileItem(); + void appendChild(Node *child); - void appendChild(TileItem *child); - - TileItem *child(int row); + Node *child(int row); int childCount() const; int childNumber() const; int columnCount() const; bool setData(int column, const QVariant &value); - QVariant data(int column) const; + virtual QVariant data(int column) const; bool insertChildren(int position, int count, int columns); bool removeChildren(int position, int count); bool insertColumns(int position, int columns); int row() const; - TileItem *parent(); - void setParent(TileItem *parent); + Node *parent(); + void setParent(Node *parent); - void appendRow(const QList &items); - void appendRow(TileItem *item); - - //QImage *getTileImageFromChannel(int channel); - - //int getTileIndex() { return m_tileIndex; } - //QString getTileFilename() { return m_tileFilename; } + void appendRow(const QList &items); + void appendRow(Node *item); protected: - QList childItems; - QVector itemData; - TileItem *parentItem; - - //QMap m_tileChannels; - //int m_tileIndex; - //QString m_tileFilename; + QList m_childItems; + QVector m_itemData; + Node *m_parentItem; }; -class TileTypeTileItem : public TileItem +class TileSetNode : public Node { public: - TileTypeTileItem(const QVector &data, TileItem *parent=0); - virtual ~TileTypeTileItem(); + TileSetNode(QString tileSetName, Node *parent=0); + virtual ~TileSetNode(); QVariant data(int column) const; + + const QString &getTileSetName(); +private: + QString m_tileSetName; +}; + +class TileTypeNode : public Node +{ +public: + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3 + }; + + TileTypeNode(TNodeTileType type, Node *parent=0); + virtual ~TileTypeNode(); + QVariant data(int column) const; + + TNodeTileType getTileType(); + + static const char *getTileTypeName(TNodeTileType type); +private: + TNodeTileType m_nodeTileType; +}; + +class TileItemNode : public Node +{ +public: + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + }; + + TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent=0); + virtual ~TileItemNode(); + QVariant data(int column) const; + void setTileFilename(TTileChannel channel, QString filename); +private: + int m_tileId; + QMap m_tileFilename; }; #endif // TILE_ITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index 20911310c..d31289c21 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -25,7 +25,7 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte Q_FOREACH(QString header, headers) rootData << header; - rootItem = new TileItem(rootData); + rootItem = new Node(rootData); } TileModel::~TileModel() @@ -33,11 +33,11 @@ TileModel::~TileModel() delete rootItem; } -TileItem *TileModel::getItem(const QModelIndex &index) const +Node *TileModel::getItem(const QModelIndex &index) const { if(index.isValid()) { - TileItem *item = static_cast(index.internalPointer()); + Node *item = static_cast(index.internalPointer()); if(item) return item; } return rootItem; @@ -48,9 +48,9 @@ QModelIndex TileModel::index(int row, int column, const QModelIndex &parent) con if(parent.isValid() && parent.column() != 0) return QModelIndex(); - TileItem *parentItem = getItem(parent); + Node *parentItem = getItem(parent); - TileItem *childItem = parentItem->child(row); + Node *childItem = parentItem->child(row); if(childItem) return createIndex(row, column, childItem); else @@ -62,8 +62,8 @@ QModelIndex TileModel::parent(const QModelIndex &index) const if(!index.isValid()) return QModelIndex(); - TileItem *childItem = getItem(index); - TileItem *parentItem = childItem->parent(); + Node *childItem = getItem(index); + Node *parentItem = childItem->parent(); if(parentItem == rootItem) return QModelIndex(); @@ -73,13 +73,13 @@ QModelIndex TileModel::parent(const QModelIndex &index) const int TileModel::rowCount(const QModelIndex &parent) const { - TileItem *parentItem = getItem(parent); + Node *parentItem = getItem(parent); return parentItem->childCount(); } int TileModel::columnCount(const QModelIndex &parent) const { - TileItem *parentItem = getItem(parent); + Node *parentItem = getItem(parent); return parentItem->columnCount(); } @@ -91,7 +91,7 @@ QVariant TileModel::data(const QModelIndex &index, int role) const if(role != Qt::DisplayRole) return QVariant(); - TileItem *item = static_cast(index.internalPointer()); + Node *item = static_cast(index.internalPointer()); return item->data(index.column()); } @@ -111,13 +111,57 @@ QVariant TileModel::headerData(int section, Qt::Orientation orientation, int rol return QVariant(); } -void TileModel::appendRow(const QList &items) +void TileModel::appendRow(const QList &items) { rootItem->appendRow(items); } -void TileModel::appendRow(TileItem *item) +void TileModel::appendRow(Node *item) { rootItem->appendRow(item); +} + +TileSetNode *TileModel::createTileSetNode(QString tileSetName) +{ + // Create the new tile set. + TileSetNode *tileSet = new TileSetNode(tileSetName); + + // child for 128x128 tiles + TileTypeNode *tile128= new TileTypeNode(TileTypeNode::Tile128); + + // child for 256x256 tiles + TileTypeNode *tile256= new TileTypeNode(TileTypeNode::Tile256); + + // child for transition tiles. + TileTypeNode *tileTrans= new TileTypeNode(TileTypeNode::TileTransition); + + // Add the default transition tiles. + // TODO tie this to CTileSet::count from NeL + for(int transPos=0; transPos<48; transPos++) + { + TileItemNode *transTile= new TileItemNode(transPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(transPos+1))); + tileTrans->appendRow(transTile); + } + + // child for displacement tiles + TileTypeNode *tileDisp= new TileTypeNode(TileTypeNode::TileDisplacement); + + // Add the default displacement tiles. + // TODO tie this to CTileSet::CountDisplace from NeL + for(int dispPos=0; dispPos<16; dispPos++) + { + TileItemNode *dispTile= new TileItemNode(dispPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(dispPos+1))); + tileDisp->appendRow(dispTile); + } + + // Append them in the correct order to the tile set. + tileSet->appendRow(tile128); + tileSet->appendRow(tile256); + tileSet->appendRow(tileTrans); + tileSet->appendRow(tileDisp); + + this->appendRow(tileSet); + + return tileSet; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index 140f60555..fba135812 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -21,7 +21,8 @@ #include -class TileItem; +class Node; +class TileSetNode; class TileModel : public QAbstractItemModel { @@ -40,15 +41,17 @@ public: int columnCount(const QModelIndex &parent = QModelIndex()) const; // Tile Model specific functions - void appendRow(const QList &items); - void appendRow(TileItem *item); + void appendRow(const QList &items); + void appendRow(Node *item); + + TileSetNode *createTileSetNode(QString tileSetName); private: - TileItem *getItem(const QModelIndex &index) const; + Node *getItem(const QModelIndex &index) const; //QList m_tiles; //int m_activeEditChannel; - TileItem *rootItem; + Node *rootItem; }; -#endif // TILE_128_MODEL_H +#endif // TILE_MODEL_H From 247745273e105d782fae3f3efa15eb2ccd50c70a Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 30 Dec 2011 14:36:51 -0600 Subject: [PATCH 006/220] Changed: #1409 Added TileItemDelegate for rendering the icons at the correct size, adding tile set auto selects newest tile set, converted model items to accept role in their data for special handling, fixed column count bug, moved important enums centrally to TileModel. --- .../tile_editor/tile_editor_main_window.cpp | 43 ++++-- .../tile_editor/tile_editor_main_window.h | 2 + .../tile_editor/tile_editor_main_window.ui | 72 ++++++++++ .../src/plugins/tile_editor/tile_item.cpp | 124 +++++++++++++----- .../src/plugins/tile_editor/tile_item.h | 46 +++---- .../tile_editor/tile_item_delegate.cpp | 98 ++++++++++++++ .../plugins/tile_editor/tile_item_delegate.h | 53 ++++++++ .../src/plugins/tile_editor/tile_model.cpp | 66 +++++++--- .../src/plugins/tile_editor/tile_model.h | 26 ++++ 9 files changed, 443 insertions(+), 87 deletions(-) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 427fda7a9..301f3564a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -30,6 +30,7 @@ #include "tile_model.h" #include "tile_item.h" +#include "tile_item_delegate.h" TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), @@ -72,6 +73,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) QStringList headers; headers << "Tile Set"; m_model = new TileModel(headers, this); + m_tileItemDelegate = new TileItemDelegate(); // Set up the tile set list view. m_ui->tileSetLV->setModel(m_model); @@ -82,6 +84,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View + m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->setModel(m_model); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); @@ -89,6 +92,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView128->addAction(m_ui->actionDeleteImage); // 256x256 List View + m_ui->listView256->setItemDelegate(m_tileItemDelegate); m_ui->listView256->setModel(m_model); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); @@ -96,14 +100,17 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView256->addAction(m_ui->actionDeleteImage); // Transition List View + m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); m_ui->listViewTransition->setModel(m_model); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View + m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); m_ui->listViewDisplacement->setModel(m_model); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); + // Connect context menu actions up. connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); @@ -168,11 +175,15 @@ void TileEditorMainWindow::onTileSetAdd() //} //else //{ - - + + + // Create and append the new tile set to the model. TileSetNode *tileSet = model->createTileSetNode(text); - + + // Retrieve how many rows there currently are and set the current index using that. m_ui->tileSetLV->reset(); + uint32 rows = model->rowCount(); + m_ui->tileSetLV->setCurrentIndex(model->index(rows-1, 0)); } } @@ -180,23 +191,31 @@ void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; QString selectedFilter; - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "PNG Bitmap(*.png);;All Files (*.*);;", &selectedFilter, options); + QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); } void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { - const QModelIndex &tile128Idx = newIndex.child(0,0); - const QModelIndex &tile256Idx = newIndex.child(1,0); - const QModelIndex &tileTransIdx = newIndex.child(2,0); - const QModelIndex &tileDispIdx = newIndex.child(3,0); + TileModel *model = static_cast(m_ui->tileSetLV->model()); + + QModelIndex tile128Idx = model->index(0, 0, newIndex); + QModelIndex tile256Idx = model->index(1, 0, newIndex); + QModelIndex tileTransIdx = model->index(2, 0, newIndex); + QModelIndex tileDispIdx = model->index(3, 0, newIndex); m_ui->listView128->setRootIndex(tile128Idx); + m_ui->listView128->setCurrentIndex(m_ui->listView128->model()->index(0, 0, m_ui->listView128->rootIndex())); m_ui->listView256->setRootIndex(tile256Idx); + m_ui->listView256->setCurrentIndex(m_ui->listView256->model()->index(0, 0, m_ui->listView256->rootIndex())); m_ui->listViewTransition->setRootIndex(tileTransIdx); + m_ui->listViewTransition->setCurrentIndex(m_ui->listViewTransition->model()->index(0, 0, m_ui->listViewTransition->rootIndex())); m_ui->listViewDisplacement->setRootIndex(tileDispIdx); + m_ui->listViewDisplacement->setCurrentIndex(m_ui->listViewDisplacement->model()->index(0, 0, m_ui->listViewDisplacement->rootIndex())); - m_ui->listView128->reset(); - m_ui->listView256->reset(); - m_ui->listViewTransition->reset(); - m_ui->listViewDisplacement->reset(); + //nlinfo("number of rows in displacement: %d", tileDispIdx.model()->rowCount(tileDispIdx)); + + //m_ui->listView128->reset(); + //m_ui->listView256->reset(); + //m_ui->listViewTransition->reset(); + //m_ui->listViewDisplacement->reset(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 267eff50c..93cde3d8f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -29,6 +29,7 @@ namespace Ui { } class TileModel; +class TileItemDelegate; class TileEditorMainWindow : public QMainWindow { @@ -59,6 +60,7 @@ private: QMenu *m_tileEditorMenu; TileModel *m_model; + TileItemDelegate *m_tileItemDelegate; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index 5897d29be..a7130bf9d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -30,6 +30,24 @@ Qt::ActionsContextMenu + + + 128 + 128 + + + + QListView::LeftToRight + + + true + + + QListView::IconMode + + + true + @@ -70,6 +88,24 @@ Qt::ActionsContextMenu + + + 256 + 256 + + + + QListView::LeftToRight + + + true + + + QListView::IconMode + + + true + @@ -113,12 +149,27 @@ Qt::ActionsContextMenu + + + 64 + 64 + + QListView::LeftToRight + + true + QListView::Batched + + QListView::IconMode + + + false + @@ -166,6 +217,27 @@ Qt::ActionsContextMenu + + + 32 + 32 + + + + QListView::LeftToRight + + + true + + + QListView::Fixed + + + QListView::IconMode + + + false + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index 289bc4a83..04b044382 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -14,8 +14,12 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +#include + #include "tile_item.h" +//#include "tile_widget.h" + #include Node::Node() : m_parentItem(0) @@ -109,9 +113,11 @@ int Node::columnCount() const return m_itemData.count(); } -QVariant Node::data(int column) const +QVariant Node::data(int column, int role) const { - return m_itemData.value(column); + if(role == Qt::DisplayRole) + return m_itemData.value(column); + return QVariant(); } bool Node::setData(int column, const QVariant &value) @@ -157,14 +163,21 @@ TileSetNode::~TileSetNode() qDeleteAll(m_childItems); } -QVariant TileSetNode::data(int column) const +QVariant TileSetNode::data(int column, int role) const { - return QVariant(m_tileSetName); + if(role == Qt::DisplayRole) + return QVariant(m_tileSetName); + return QVariant(); +} + +int TileSetNode::columnCount() const +{ + return 1; } /////////////////////////////////////////////////// -TileTypeNode::TileTypeNode(TNodeTileType type, Node *parent) : m_nodeTileType(type) +TileTypeNode::TileTypeNode(TileModel::TNodeTileType type, Node *parent) : m_nodeTileType(type) { m_parentItem = parent; } @@ -174,42 +187,34 @@ TileTypeNode::~TileTypeNode() qDeleteAll(m_childItems); } -QVariant TileTypeNode::data(int column) const +QVariant TileTypeNode::data(int column, int role) const { - return QVariant(getTileTypeName(m_nodeTileType)); + if(role == Qt::DisplayRole) + return QVariant(TileModel::getTileTypeName(m_nodeTileType)); + return QVariant(); + } -TileTypeNode::TNodeTileType TileTypeNode::getTileType() +int TileTypeNode::columnCount() const +{ + return 1; +} + +TileModel::TNodeTileType TileTypeNode::getTileType() { return m_nodeTileType; } -const char *TileTypeNode::getTileTypeName(TNodeTileType type) -{ - switch(type) - { - case Tile128: - return "128"; - case Tile256: - return "256"; - case TileTransition: - return "Transition"; - case TileDisplacement: - return "Displacement"; - default: - break; - } - return "UNKNOWN"; -} + /////////////////////////////////////////////////// -TileItemNode::TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) +TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) { m_tileFilename[channel] = filename; m_parentItem = parent; - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); } TileItemNode::~TileItemNode() @@ -217,14 +222,71 @@ TileItemNode::~TileItemNode() qDeleteAll(m_childItems); } -void TileItemNode::setTileFilename(TTileChannel channel, QString filename) +void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) { m_tileFilename[channel] = filename; } -QVariant TileItemNode::data(int column) const +QVariant TileItemNode::data(int column, int role) const { - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileDiffuse].toStdString().c_str()); + + + nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); // find some way to know which file/bitmap to display - return QVariant(m_tileFilename[TileDiffuse]); + QString tileFilename = m_tileFilename[TileModel::TileDiffuse]; + //TileWidget *tile = m_tileWidget[TileModel::TileDiffuse]; + + // + // + // return QVariant(); + + //if(tile == NULL) + //{ + // + // + + // // Create a new tile widget. + // tile = new TileWidget(); + // tile->initWidget(tileFilename, tileFilename, tileSize); + //} + + if(role == TileModel::TilePixmapRole) + { + TileTypeNode *parent = dynamic_cast(m_parentItem); + if(parent == NULL) + return QVariant(); + + // Retrieve the target tile size. + uint32 tileSize = TileModel::getTileTypeSize(parent->getTileType()); + + if(tileFilename.isEmpty() || tileFilename == "empty") + tileFilename = ":/placeHolder/images/empty_image.png"; + + QPixmap pixmap;// = new QPixmap(); + if(!pixmap.load(tileFilename)) + nlinfo("failed to load %s", tileFilename.toStdString().c_str()); + + //pixmap.scaled(tileSize*100, tileSize*100); + + return pixmap; + } + else if(role == TileModel::TileFilenameRole) + { + return QVariant(tileFilename); + } + else if(role == TileModel::TileIndexRole) + { + return QVariant(tileFilename); + } + /*else if(role == Qt::TextAlignmentRole) + { + return QVariant(Qt::AlignHCenter|Qt::AlignVCenter); + }*/ + + return QVariant(); } + +int TileItemNode::columnCount() const +{ + return 1; +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h index eceb38a79..f89b20ab7 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h @@ -22,6 +22,10 @@ #include #include +#include "tile_model.h" + +class TileWidget; + class Node { public: @@ -34,9 +38,9 @@ public: Node *child(int row); int childCount() const; int childNumber() const; - int columnCount() const; + virtual int columnCount() const; bool setData(int column, const QVariant &value); - virtual QVariant data(int column) const; + virtual QVariant data(int column, int role) const; bool insertChildren(int position, int count, int columns); bool removeChildren(int position, int count); @@ -60,7 +64,8 @@ class TileSetNode : public Node public: TileSetNode(QString tileSetName, Node *parent=0); virtual ~TileSetNode(); - QVariant data(int column) const; + QVariant data(int column, int role) const; + int columnCount() const; const QString &getTileSetName(); private: @@ -70,42 +75,29 @@ private: class TileTypeNode : public Node { public: - enum TNodeTileType - { - Tile128 = 0, - Tile256 = 1, - TileTransition = 2, - TileDisplacement = 3 - }; - TileTypeNode(TNodeTileType type, Node *parent=0); + TileTypeNode(TileModel::TNodeTileType type, Node *parent=0); virtual ~TileTypeNode(); - QVariant data(int column) const; + QVariant data(int column, int role) const; + int columnCount() const; - TNodeTileType getTileType(); - - static const char *getTileTypeName(TNodeTileType type); + TileModel::TNodeTileType getTileType(); private: - TNodeTileType m_nodeTileType; + TileModel::TNodeTileType m_nodeTileType; }; class TileItemNode : public Node { public: - enum TTileChannel - { - TileDiffuse = 0, - TileAdditive = 1, - TileAlpha = 2, - }; - - TileItemNode(int tileId, TTileChannel channel, QString filename, Node *parent=0); + TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); virtual ~TileItemNode(); - QVariant data(int column) const; - void setTileFilename(TTileChannel channel, QString filename); + QVariant data(int column, int role) const; + int columnCount() const; + void setTileFilename(TileModel::TTileChannel channel, QString filename); private: int m_tileId; - QMap m_tileFilename; + QMap m_tileFilename; + QMap m_tileWidget; }; #endif // TILE_ITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp new file mode 100644 index 000000000..f689ff83e --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp @@ -0,0 +1,98 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include + +#include + +#include "tile_item_delegate.h" + +#include "tile_model.h" + +TileItemDelegate::TileItemDelegate() +{ + m_zoomFactor = ZoomNormal; +} + +TileItemDelegate::~TileItemDelegate() +{ +} + +void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyledItemDelegate::paint(painter,option,index); + + painter->save(); + + QFont font = QApplication::font(); + QFont SubFont = QApplication::font(); + //font.setPixelSize(font.weight()+); + font.setBold(true); + SubFont.setWeight(SubFont.weight()-2); + QFontMetrics fm(font); + + QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); + QString headerText = qvariant_cast(index.data(TileModel::TileFilenameRole)); + QString subText = qvariant_cast(index.data(TileModel::TileIndexRole)); + + QSize tileSize = tile.size(); + + QRect headerRect = option.rect; + QRect subheaderRect = option.rect; + QRect tileRect = subheaderRect; + + tileRect.setRight(tileSize.width()+30); + tileRect.setTop(tileRect.top()+5); + headerRect.setLeft(tileRect.right()); + subheaderRect.setLeft(tileRect.right()); + headerRect.setTop(headerRect.top()+5); + headerRect.setBottom(headerRect.top()+fm.height()); + + subheaderRect.setTop(headerRect.bottom()+2); + + + //painter->drawPixmap(QPoint(iconRect.right()/2,iconRect.top()/2),icon.pixmap(iconsize.width(),iconsize.height())); + painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); + + painter->setFont(font); + painter->drawText(headerRect,headerText); + + + painter->setFont(SubFont); + painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); + + painter->restore(); +} + +QSize TileItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); + QSize tileSize = tile.size();//tile.actualSize(option.decorationSize); + QFont font = QApplication::font(); + QFontMetrics fm(font); + + return(QSize(tileSize.width(), tileSize.height()+fm.height()+8 )); +} + +TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() +{ + return m_zoomFactor; +} + +void TileItemDelegate::setZoomFactor(TileItemDelegate::TZoomFactor zoomFactor) +{ + m_zoomFactor = zoomFactor; +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h new file mode 100644 index 000000000..b87a17344 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h @@ -0,0 +1,53 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +#ifndef TILE_ITEM_DELEGATE_H +#define TILE_ITEM_DELEGATE_H + +#include +#include +#include + +#include "ui_tile_widget.h" + +#include + +class TileItemDelegate : public QStyledItemDelegate + { + public: + + enum TZoomFactor + { + ZoomSmall = 0, + ZoomNormal = 1, + ZoomLarge = 2 + }; + + static const int PIXMAP_MARGIN = 5; + + TileItemDelegate(); + virtual ~TileItemDelegate(); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const; + + TZoomFactor getZoomFactor(); + void setZoomFactor(TZoomFactor zoomFactor); + + private: + TZoomFactor m_zoomFactor; + }; + +#endif // TILE_ITEM_DELEGATE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index d31289c21..19fa9409f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -88,11 +88,8 @@ QVariant TileModel::data(const QModelIndex &index, int role) const if(!index.isValid()) return QVariant(); - if(role != Qt::DisplayRole) - return QVariant(); - Node *item = static_cast(index.internalPointer()); - return item->data(index.column()); + return item->data(index.column(), role); } Qt::ItemFlags TileModel::flags(const QModelIndex &index) const @@ -106,7 +103,7 @@ Qt::ItemFlags TileModel::flags(const QModelIndex &index) const QVariant TileModel::headerData(int section, Qt::Orientation orientation, int role) const { if(orientation == Qt::Horizontal && role == Qt::DisplayRole) - return rootItem->data(section); + return rootItem->data(section,role); return QVariant(); } @@ -128,40 +125,75 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) TileSetNode *tileSet = new TileSetNode(tileSetName); // child for 128x128 tiles - TileTypeNode *tile128= new TileTypeNode(TileTypeNode::Tile128); - + TileTypeNode *tile128= new TileTypeNode(Tile128); + tileSet->appendRow(tile128); + // child for 256x256 tiles - TileTypeNode *tile256= new TileTypeNode(TileTypeNode::Tile256); + TileTypeNode *tile256= new TileTypeNode(Tile256); + tileSet->appendRow(tile256); // child for transition tiles. - TileTypeNode *tileTrans= new TileTypeNode(TileTypeNode::TileTransition); + TileTypeNode *tileTrans= new TileTypeNode(TileTransition); + tileSet->appendRow(tileTrans); // Add the default transition tiles. // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode(transPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(transPos+1))); + TileItemNode *transTile= new TileItemNode(transPos, TileDiffuse, QString("empty")); tileTrans->appendRow(transTile); } // child for displacement tiles - TileTypeNode *tileDisp= new TileTypeNode(TileTypeNode::TileDisplacement); + TileTypeNode *tileDisp= new TileTypeNode(TileDisplacement); + tileSet->appendRow(tileDisp); // Add the default displacement tiles. // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode(dispPos, TileItemNode::TileDiffuse, QString("filename").append(QString::number(dispPos+1))); + TileItemNode *dispTile= new TileItemNode(dispPos, TileDiffuse, QString("empty")); tileDisp->appendRow(dispTile); } // Append them in the correct order to the tile set. - tileSet->appendRow(tile128); - tileSet->appendRow(tile256); - tileSet->appendRow(tileTrans); - tileSet->appendRow(tileDisp); - this->appendRow(tileSet); return tileSet; +} + +const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) +{ + switch(type) + { + case Tile128: + return "128"; + case Tile256: + return "256"; + case TileTransition: + return "Transition"; + case TileDisplacement: + return "Displacement"; + default: + break; + } + return "UNKNOWN"; +} + +uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) +{ + switch(type) + { + case Tile128: + return 128; + case Tile256: + return 256; + case TileTransition: + return 64; + case TileDisplacement: + return 32; + default: + break; + } + return 0; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index fba135812..aea6461b1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -29,6 +29,29 @@ class TileModel : public QAbstractItemModel Q_OBJECT public: + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + }; + + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3 + }; + + enum TTileItemRole + { + TilePixmapRole = Qt::UserRole+1, + TileFilenameRole = Qt::UserRole+2, + TileIndexRole = Qt::UserRole+3 + }; + + TileModel(const QStringList &headers, QObject *parent); ~TileModel(); @@ -46,6 +69,9 @@ public: TileSetNode *createTileSetNode(QString tileSetName); + static const char *getTileTypeName(TNodeTileType type); + static uint32 getTileTypeSize(TileModel::TNodeTileType type); + private: Node *getItem(const QModelIndex &index) const; From e56f07bfc531003b4d928df5e370be8a9a442d31 Mon Sep 17 00:00:00 2001 From: sfb Date: Mon, 27 Feb 2012 08:40:23 -0600 Subject: [PATCH 007/220] Changed: #1409 Removing the tile item delegate, modifying the model with custom roles for view modes. --- .../tile_editor/tile_editor_main_window.cpp | 41 +++++++++-- .../tile_editor/tile_editor_main_window.h | 9 ++- .../tile_editor/tile_editor_main_window.ui | 40 ++++++++++- .../src/plugins/tile_editor/tile_item.cpp | 49 ++++++------- .../tile_editor/tile_item_delegate.cpp | 70 +++++++++++++------ .../plugins/tile_editor/tile_item_delegate.h | 4 ++ .../src/plugins/tile_editor/tile_model.cpp | 51 ++++++++++++++ .../src/plugins/tile_editor/tile_model.h | 19 ++++- 8 files changed, 223 insertions(+), 60 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 301f3564a..c367addbe 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -43,7 +43,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - QMenu *m_tileEditorMenu; // Create tile rotation drop down toolbar menu. m_rotationMenu = new QMenu(tr("Rotate Tile"), m_ui->toolBar); m_rotationMenu->setIcon(QIcon(":/tileRotation/images/rotation0.png")); @@ -57,7 +56,17 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Create the tile zoom menu. m_zoomMenu = new QMenu(tr("Zoom"), m_ui->toolBar); + m_zoomActionGroup = new QActionGroup(this); + m_zoomSignalMapper = new QSignalMapper(this); QList zoomActions; + zoomActions.push_back(m_ui->actionZoom50); + zoomActions.push_back(m_ui->actionZoom100); + zoomActions.push_back(m_ui->actionZoom200); + m_zoomActionGroup->addAction(m_ui->actionZoom50); + m_zoomActionGroup->addAction(m_ui->actionZoom100); + m_zoomActionGroup->addAction(m_ui->actionZoom200); + m_zoomMenu->addActions(zoomActions); + m_ui->toolBar->addAction(m_zoomMenu->menuAction()); m_tileEditorMenu = new QMenu(tr("Tile Editor"), core->menuManager()->menuBar()); m_tileDisplayMenu = new QMenu(tr("Tile Display"), m_ui->toolBar); @@ -84,7 +93,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); // 128x128 List View - m_ui->listView128->setItemDelegate(m_tileItemDelegate); + //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->setModel(m_model); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); @@ -92,7 +101,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView128->addAction(m_ui->actionDeleteImage); // 256x256 List View - m_ui->listView256->setItemDelegate(m_tileItemDelegate); + //m_ui->listView256->setItemDelegate(m_tileItemDelegate); m_ui->listView256->setModel(m_model); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); @@ -100,13 +109,13 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->listView256->addAction(m_ui->actionDeleteImage); // Transition List View - m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); + //m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); m_ui->listViewTransition->setModel(m_model); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View - m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); + //m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); m_ui->listViewDisplacement->setModel(m_model); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -117,6 +126,20 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionDeleteTile, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteTile(bool))); connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); + + connect(m_ui->actionTileDisplayFilename, SIGNAL(toggled(bool)), m_model, SLOT(selectFilenameDisplay(bool))); + connect(m_ui->actionTileDisplayIndex, SIGNAL(toggled(bool)), m_model, SLOT(selectIndexDisplay(bool))); + + //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); + + // Connect the zoom buttons. + connect(m_ui->actionZoom50, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); + m_zoomSignalMapper->setMapping(m_ui->actionZoom50, 0); + connect(m_ui->actionZoom100, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); + m_zoomSignalMapper->setMapping(m_ui->actionZoom100, 1); + connect(m_ui->actionZoom200, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); + m_zoomSignalMapper->setMapping(m_ui->actionZoom200, 2); + connect(m_zoomSignalMapper, SIGNAL(mapped(int)), m_model, SLOT(onZoomFactor(int))); } TileEditorMainWindow::~TileEditorMainWindow() @@ -125,6 +148,14 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_undoStack; delete m_rotationMenu; delete m_zoomMenu; + + + delete m_tileDisplayMenu; + delete m_tileEditorMenu; + + delete m_zoomMenu; + delete m_zoomActionGroup; + delete m_zoomSignalMapper; } void TileEditorMainWindow::onActionAddTile(bool triggered) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 93cde3d8f..8233d16d3 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -23,6 +23,7 @@ #include "nel/misc/sheet_id.h" #include +#include namespace Ui { class TileEditorMainWindow; @@ -47,7 +48,7 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); - void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); private: void onActionAddTile(int tabId); @@ -55,10 +56,14 @@ private: Ui::TileEditorMainWindow *m_ui; QUndoStack *m_undoStack; QMenu *m_rotationMenu; - QMenu *m_zoomMenu; + QMenu *m_tileDisplayMenu; QMenu *m_tileEditorMenu; + QMenu *m_zoomMenu; + QActionGroup *m_zoomActionGroup; + QSignalMapper *m_zoomSignalMapper; + TileModel *m_model; TileItemDelegate *m_tileItemDelegate; }; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index a7130bf9d..7bf82ca05 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -161,14 +161,17 @@ true + + QListView::Adjust + - QListView::Batched + QListView::SinglePass QListView::IconMode - false + true @@ -678,6 +681,9 @@ true + + true + Index @@ -689,6 +695,9 @@ true + + true + Filename @@ -744,6 +753,33 @@ Delete Image + + + true + + + Zoom 50% + + + + + true + + + true + + + Zoom 100% + + + + + true + + + Zoom 200% + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index 04b044382..adf381dc0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -115,7 +115,10 @@ int Node::columnCount() const QVariant Node::data(int column, int role) const { - if(role == Qt::DisplayRole) + if(role == Qt::DisplayRole || + role == TileModel::TileFilenameIndexRole || + role == TileModel::TileFilenameRole || + role == TileModel::TileIndexRole) return m_itemData.value(column); return QVariant(); } @@ -165,7 +168,10 @@ TileSetNode::~TileSetNode() QVariant TileSetNode::data(int column, int role) const { - if(role == Qt::DisplayRole) + if(role == Qt::DisplayRole || + role == TileModel::TileFilenameIndexRole || + role == TileModel::TileFilenameRole || + role == TileModel::TileIndexRole) return QVariant(m_tileSetName); return QVariant(); } @@ -189,7 +195,10 @@ TileTypeNode::~TileTypeNode() QVariant TileTypeNode::data(int column, int role) const { - if(role == Qt::DisplayRole) + if(role == Qt::DisplayRole || + role == TileModel::TileFilenameIndexRole || + role == TileModel::TileFilenameRole || + role == TileModel::TileIndexRole) return QVariant(TileModel::getTileTypeName(m_nodeTileType)); return QVariant(); @@ -228,29 +237,11 @@ void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file } QVariant TileItemNode::data(int column, int role) const -{ - - - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); +{ // find some way to know which file/bitmap to display QString tileFilename = m_tileFilename[TileModel::TileDiffuse]; - //TileWidget *tile = m_tileWidget[TileModel::TileDiffuse]; - // - // - // return QVariant(); - - //if(tile == NULL) - //{ - // - // - - // // Create a new tile widget. - // tile = new TileWidget(); - // tile->initWidget(tileFilename, tileFilename, tileSize); - //} - - if(role == TileModel::TilePixmapRole) + if(role == TileModel::TilePixmapRole || role == Qt::DecorationRole) { TileTypeNode *parent = dynamic_cast(m_parentItem); if(parent == NULL) @@ -270,18 +261,22 @@ QVariant TileItemNode::data(int column, int role) const return pixmap; } + else if(role == Qt::DisplayRole) + { + return QVariant(tileFilename); + } else if(role == TileModel::TileFilenameRole) { return QVariant(tileFilename); } else if(role == TileModel::TileIndexRole) { - return QVariant(tileFilename); + return QVariant("("+QString::number(m_tileId)+")"); } - /*else if(role == Qt::TextAlignmentRole) + else if(role == TileModel::TileFilenameIndexRole) { - return QVariant(Qt::AlignHCenter|Qt::AlignVCenter); - }*/ + return QVariant(tileFilename + " ("+QString::number(m_tileId)+")"); + } return QVariant(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp index f689ff83e..43751d612 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp @@ -25,6 +25,7 @@ TileItemDelegate::TileItemDelegate() { m_zoomFactor = ZoomNormal; + m_imageHint = 128; } TileItemDelegate::~TileItemDelegate() @@ -38,41 +39,48 @@ void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti painter->save(); QFont font = QApplication::font(); - QFont SubFont = QApplication::font(); - //font.setPixelSize(font.weight()+); - font.setBold(true); - SubFont.setWeight(SubFont.weight()-2); + + //font.setBold(true); + //SubFont.setWeight(SubFont.weight()-2); QFontMetrics fm(font); QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); - QString headerText = qvariant_cast(index.data(TileModel::TileFilenameRole)); - QString subText = qvariant_cast(index.data(TileModel::TileIndexRole)); + QString tileFileText = qvariant_cast(index.data(TileModel::TileFilenameRole)); + QString tileIdText = qvariant_cast(index.data(TileModel::TileIndexRole)); QSize tileSize = tile.size(); - QRect headerRect = option.rect; - QRect subheaderRect = option.rect; - QRect tileRect = subheaderRect; + //QRect headerRect = option.rect; + QRect rect(option.rect); + //QRect tileRect(option.rect); + int textHeight = fm.height(); + int iconPosModX = PIXMAP_MARGIN + (tile.width() / 2); + int iconPosModY = (option.rect.height() - tile.height()) / 2; - tileRect.setRight(tileSize.width()+30); - tileRect.setTop(tileRect.top()+5); - headerRect.setLeft(tileRect.right()); - subheaderRect.setLeft(tileRect.right()); - headerRect.setTop(headerRect.top()+5); - headerRect.setBottom(headerRect.top()+fm.height()); + painter->drawPixmap(rect.adjusted(iconPosModX, iconPosModY, iconPosModX, iconPosModY).topLeft(), tile); - subheaderRect.setTop(headerRect.bottom()+2); + + + //tileRect.setRight(tileSize.width()+30); + //tileRect.setTop(tileRect.top()+5); + //headerRect.setLeft(tileRect.right()); + //subheaderRect.setLeft(tileRect.right()); + //headerRect.setTop(headerRect.top()+5); + //headerRect.setBottom(headerRect.top()+fm.height()); + + //subheaderRect.setTop(headerRect.bottom()+2); + //painter->drawPixmap(targetrect, pixmap, sourcerect) //painter->drawPixmap(QPoint(iconRect.right()/2,iconRect.top()/2),icon.pixmap(iconsize.width(),iconsize.height())); - painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); + //painter->drawPixmap(QPoint(tileRect.left()+tileSize.width()/2+2,tileRect.top()+tileSize.height()/2+3),tile); - painter->setFont(font); - painter->drawText(headerRect,headerText); + //painter->setFont(font); + //painter->drawText(headerRect,headerText); - painter->setFont(SubFont); - painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); + //painter->setFont(SubFont); + //painter->drawText(subheaderRect.left(),subheaderRect.top()+17,subText); painter->restore(); } @@ -80,11 +88,11 @@ void TileItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti QSize TileItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const { QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); - QSize tileSize = tile.size();//tile.actualSize(option.decorationSize); + QSize tileSize = tile.size(); QFont font = QApplication::font(); QFontMetrics fm(font); - return(QSize(tileSize.width(), tileSize.height()+fm.height()+8 )); + return(QSize(tileSize.width()+(2*PIXMAP_MARGIN), tileSize.height()+fm.height()+(2*PIXMAP_MARGIN))); } TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() @@ -95,4 +103,20 @@ TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() void TileItemDelegate::setZoomFactor(TileItemDelegate::TZoomFactor zoomFactor) { m_zoomFactor = zoomFactor; +} + +// SLOTS + +void TileItemDelegate::currentTab(int index) +{ + if(index == 1) + { + nlinfo("switching delegate to 1 or 256"); + m_imageHint = 256; + } + else + { + nlinfo("switching delegate to 0,2,3 or 128"); + m_imageHint = 128; + } } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h index b87a17344..1b7058b48 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h @@ -46,8 +46,12 @@ class TileItemDelegate : public QStyledItemDelegate TZoomFactor getZoomFactor(); void setZoomFactor(TZoomFactor zoomFactor); +public Q_SLOTS: + void currentTab(int index); + private: TZoomFactor m_zoomFactor; + int m_imageHint; }; #endif // TILE_ITEM_DELEGATE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index 19fa9409f..cd5c1c4ce 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -19,6 +19,8 @@ #include +#include + TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) { QVector rootData; @@ -26,6 +28,10 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte rootData << header; rootItem = new Node(rootData); + + m_tileZoomFactor = TileZoom100; + m_indexDisplay = true; + m_fileDisplay = true; } TileModel::~TileModel() @@ -89,6 +95,18 @@ QVariant TileModel::data(const QModelIndex &index, int role) const return QVariant(); Node *item = static_cast(index.internalPointer()); + + // Translate the display role to the settings-specific role. + + if(role == Qt::DisplayRole) + { + if(m_indexDisplay && m_fileDisplay) + role = TileFilenameIndexRole; + else if(m_fileDisplay) + role = TileFilenameRole; + else if(m_indexDisplay) + role = TileIndexRole; + } return item->data(index.column(), role); } @@ -196,4 +214,37 @@ uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) break; } return 0; +} + +void TileModel::selectFilenameDisplay(bool selected) +{ + m_fileDisplay = selected; +} + +void TileModel::selectIndexDisplay(bool selected) +{ + m_indexDisplay = selected; +} + +void TileModel::onZoomFactor(int level) +{ + switch(level) + { + // Zoom Level 50% + case 0: + nlinfo("zooming to 50%"); + m_tileZoomFactor = TileZoom50; + break; + case 1: + nlinfo("zooming to 100%"); + m_tileZoomFactor = TileZoom100; + break; + case 2: + nlinfo("zooming to 200%"); + m_tileZoomFactor = TileZoom200; + break; + default: + nlwarning("Invalid Time Zoom Factor passed."); + break; + }; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index aea6461b1..e9884cd61 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -48,7 +48,15 @@ public: { TilePixmapRole = Qt::UserRole+1, TileFilenameRole = Qt::UserRole+2, - TileIndexRole = Qt::UserRole+3 + TileIndexRole = Qt::UserRole+3, + TileFilenameIndexRole = Qt::UserRole+4 + }; + + enum TTileZoomFactor + { + TileZoom50 = 0, + TileZoom100 = 1, + TileZoom200 = 2 }; @@ -72,9 +80,18 @@ public: static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); +public Q_SLOTS: + void selectFilenameDisplay(bool selected); + void selectIndexDisplay(bool selected); + void onZoomFactor(int level); + private: Node *getItem(const QModelIndex &index) const; + bool m_fileDisplay; + bool m_indexDisplay; + TTileZoomFactor m_tileZoomFactor; + //QList m_tiles; //int m_activeEditChannel; Node *rootItem; From 9481a6cdd50831e6a1b462b41397ce0b9398a187 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 2 Mar 2012 14:17:38 -0600 Subject: [PATCH 008/220] Changed: #1409 Adding zoom functionality to views, trying to fix icon size problem. --- .../tile_editor/tile_editor_main_window.cpp | 49 ++++++++++++++++++- .../tile_editor/tile_editor_main_window.h | 5 +- .../tile_editor/tile_editor_main_window.ui | 6 +++ .../src/plugins/tile_editor/tile_item.cpp | 9 +++- .../src/plugins/tile_editor/tile_model.cpp | 28 ++--------- .../src/plugins/tile_editor/tile_model.h | 12 +++-- 6 files changed, 77 insertions(+), 32 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index c367addbe..930ae9d8b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -139,7 +139,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_zoomSignalMapper->setMapping(m_ui->actionZoom100, 1); connect(m_ui->actionZoom200, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); m_zoomSignalMapper->setMapping(m_ui->actionZoom200, 2); - connect(m_zoomSignalMapper, SIGNAL(mapped(int)), m_model, SLOT(onZoomFactor(int))); + connect(m_zoomSignalMapper, SIGNAL(mapped(int)), this, SLOT(onZoomFactor(int))); } TileEditorMainWindow::~TileEditorMainWindow() @@ -158,6 +158,53 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_zoomSignalMapper; } +void TileEditorMainWindow::onZoomFactor(int level) +{ + int tile128Scaled=TileModel::TILE_128_BASE_SIZE; + int tile256Scaled=TileModel::TILE_256_BASE_SIZE; + int tileTransScaled=TileModel::TILE_TRANSITION_BASE_SIZE; + int tileDispScaled=TileModel::TILE_DISPLACE_BASE_SIZE; + switch(level) + { + // Zoom Level 50% + case 0: + nlinfo("zooming to 50%"); + TileModel::CurrentZoomFactor = TileModel::TileZoom50; + tile128Scaled /= 2; + tile256Scaled /= 2; + tileTransScaled /= 2; + tileDispScaled /= 2; + break; + case 1: + nlinfo("zooming to 100%"); + TileModel::CurrentZoomFactor = TileModel::TileZoom100; + break; + case 2: + nlinfo("zooming to 200%"); + TileModel::CurrentZoomFactor = TileModel::TileZoom200; + tile128Scaled *= 2; + tile256Scaled *= 2; + tileTransScaled *= 2; + tileDispScaled *= 2; + break; + default: + nlwarning("Invalid Time Zoom Factor passed."); + break; + }; + + nlinfo("resizing transition view. base size: %d factor %d to: %d", TileModel::TILE_TRANSITION_BASE_SIZE, level, tileTransScaled); + + m_ui->listView128->setIconSize(QSize(tile128Scaled, tile128Scaled)); + m_ui->listView128->setCurrentIndex(m_ui->listView128->model()->index(0, 0, m_ui->listView128->rootIndex())); + m_ui->listView256->setIconSize(QSize(tile256Scaled, tile256Scaled)); + m_ui->listView256->setCurrentIndex(m_ui->listView256->model()->index(0, 0, m_ui->listView256->rootIndex())); + m_ui->listViewTransition->setIconSize(QSize(tileTransScaled, tileTransScaled)); + m_ui->listViewTransition->setCurrentIndex(m_ui->listViewTransition->model()->index(0, 0, m_ui->listViewTransition->rootIndex())); + m_ui->listViewDisplacement->setIconSize(QSize(tileDispScaled, tileDispScaled)); + m_ui->listViewDisplacement->setCurrentIndex(m_ui->listViewDisplacement->model()->index(0, 0, m_ui->listViewDisplacement->rootIndex())); + m_ui->listViewTransition->repaint(); +} + void TileEditorMainWindow::onActionAddTile(bool triggered) { onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h index 8233d16d3..ae3520465 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h @@ -40,7 +40,7 @@ public: explicit TileEditorMainWindow(QWidget *parent = 0); ~TileEditorMainWindow(); - QUndoStack *getUndoStack() { return m_undoStack; } + QUndoStack *getUndoStack() { return m_undoStack; } public Q_SLOTS: void onActionAddTile(bool triggered); @@ -48,7 +48,8 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); - void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); + void onZoomFactor(int level); private: void onActionAddTile(int tabId); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui index 7bf82ca05..66a086179 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui @@ -155,6 +155,9 @@ 64 + + QListView::Static + QListView::LeftToRight @@ -226,6 +229,9 @@ 32 + + QListView::Static + QListView::LeftToRight diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index adf381dc0..fcd14a61b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -223,7 +223,7 @@ TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString { m_tileFilename[channel] = filename; m_parentItem = parent; - nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); + //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); } TileItemNode::~TileItemNode() @@ -257,7 +257,12 @@ QVariant TileItemNode::data(int column, int role) const if(!pixmap.load(tileFilename)) nlinfo("failed to load %s", tileFilename.toStdString().c_str()); - //pixmap.scaled(tileSize*100, tileSize*100); + if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) + tileSize *= 2; + else if(TileModel::CurrentZoomFactor == TileModel::TileZoom50) + tileSize /= 2; + + pixmap.scaled(tileSize, tileSize); return pixmap; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp index cd5c1c4ce..c167dbd44 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp @@ -21,6 +21,9 @@ #include +// Initialize the static members +TileModel::TTileZoomFactor TileModel::CurrentZoomFactor; + TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) { QVector rootData; @@ -29,7 +32,7 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte rootItem = new Node(rootData); - m_tileZoomFactor = TileZoom100; + TileModel::CurrentZoomFactor = TileModel::TileZoom100; m_indexDisplay = true; m_fileDisplay = true; } @@ -224,27 +227,4 @@ void TileModel::selectFilenameDisplay(bool selected) void TileModel::selectIndexDisplay(bool selected) { m_indexDisplay = selected; -} - -void TileModel::onZoomFactor(int level) -{ - switch(level) - { - // Zoom Level 50% - case 0: - nlinfo("zooming to 50%"); - m_tileZoomFactor = TileZoom50; - break; - case 1: - nlinfo("zooming to 100%"); - m_tileZoomFactor = TileZoom100; - break; - case 2: - nlinfo("zooming to 200%"); - m_tileZoomFactor = TileZoom200; - break; - default: - nlwarning("Invalid Time Zoom Factor passed."); - break; - }; } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h index e9884cd61..bd7d808fb 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h @@ -59,6 +59,11 @@ public: TileZoom200 = 2 }; + static const int TILE_DISPLACE_BASE_SIZE = 32; + static const int TILE_TRANSITION_BASE_SIZE = 64; + static const int TILE_128_BASE_SIZE = 128; + static const int TILE_256_BASE_SIZE = 256; + TileModel(const QStringList &headers, QObject *parent); ~TileModel(); @@ -80,17 +85,18 @@ public: static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); + static TTileZoomFactor CurrentZoomFactor; + public Q_SLOTS: void selectFilenameDisplay(bool selected); - void selectIndexDisplay(bool selected); - void onZoomFactor(int level); + void selectIndexDisplay(bool selected); private: Node *getItem(const QModelIndex &index) const; bool m_fileDisplay; bool m_indexDisplay; - TTileZoomFactor m_tileZoomFactor; + //TTileZoomFactor m_tileZoomFactor; //QList m_tiles; //int m_activeEditChannel; From e527bfdeaa8ef85b7b9319b1e4275f4c97489115 Mon Sep 17 00:00:00 2001 From: sfb Date: Mon, 17 Sep 2012 15:12:01 -0500 Subject: [PATCH 010/220] merging legacy dfn-based method into geqt. Warning: broke the build. --- .../src/plugins/georges_editor/formitem.cpp | 198 ++- .../src/plugins/georges_editor/formitem.h | 17 +- .../georges_treeview_dialog.cpp | 124 +- .../georges_editor/georges_treeview_dialog.h | 12 +- .../georges_editor/georgesform_model.cpp | 1494 ++++++++++------- .../georges_editor/georgesform_model.h | 17 +- .../src/plugins/object_viewer/main_window.cpp | 2 +- 7 files changed, 1140 insertions(+), 724 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index e6e526631..014338a2d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -23,11 +23,13 @@ #include #include +using namespace NLGEORGES; + namespace GeorgesQt { CFormItem::CFormItem(NLGEORGES::UFormElm* elm, const QList &data, CFormItem *parent, - NLGEORGES::UFormElm::TWhereIsValue wV, NLGEORGES::UFormElm::TWhereIsNode wN) + NLGEORGES::UFormElm::TWhereIsValue wV, NLGEORGES::UFormElm::TWhereIsNode wN) { parentItem = parent; itemData = data; @@ -159,4 +161,198 @@ namespace GeorgesQt //formElm->setValueByName(); return true; } + +// CFormItem *CFormItem::add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot) +// { + // Add at the end +// uint index = _Children.size(); +// _Children.push_back (new CGeorgesEditDocSub); + +// _Children[index]->_Type = type; +// _Children[index]->_Name = name; +// _Children[index]->_Parent = this; +// _Children[index]->_StructId = structId; +// _Children[index]->_FormName = formName; +// _Children[index]->_Slot = slot; +// return _Children[index]; +// CFormItem *newNode = new CFormItem(); +// appendChild(newNode); +// return NULL; +// } + + CFormItem *CFormItem::add(NLGEORGES::UFormElm* root, std::string elmName) + { + CFormItem *newItem = NULL; + UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; + UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; + // Append a new item to the current parent's list of children. +// std::string elmName; +// if(root->getStructNodeName(num, elmName)) +// { + QList columnData; + //QVariant value; + std::string value; + //NLMISC::CRGBA value_color; + //uint value_uint; + //sint value_sint; + //double value_double; + QString elmtType = ""; + UFormElm *elmt = 0; + if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) + { + if (elmt) + { + if (elmt->isArray()) + elmtType = "Array"; + if (elmt->isStruct()) + elmtType = "Struct"; + if (elmt->isAtom()) + { + elmtType = "Atom"; + uint numDefinitions = 0; + const UType *type = elmt->getType(); + if (type) + { + numDefinitions = type->getNumDefinition(); + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (type->getType()) + { + case UType::UnsignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_uint");break; + case UType::SignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_sint");break; + case UType::Double: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); + elmtType.append("_double");break; + case UType::String: + elmtType.append("_string");break; + case UType::Color: + elmtType.append("_color");break; + default: + elmtType.append("_unknownType"); + } + } + else + { + elmtType.append("_noType"); + } + + if (numDefinitions) + { + std::string l, v; + QString tmpLabel, tmpValue; + for (uint i = 0; i < numDefinitions; i++) + { + type->getDefinition(i,l,v); + tmpLabel = l.c_str(); + tmpValue = v.c_str(); + if (type->getType() == UType::SignedInt) + { + if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { + value = l; + break; + } + } + if (type->getType() == UType::String) + { + if (QString(value.c_str()) == tmpValue) + { + value = l; + break; + } + } + } + } + } + if (elmt->isVirtualStruct()) + { + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + elmtType = "VirtualStruct"; + } + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + + newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); + this->appendChild(newItem); + + return newItem; + //if (parents.last()->childCount() > 0) { + // parents << parents.last()->child(parents.last()->childCount()-1); + //} + + // The building of the tree should be haoppening in the mode,. + //loadFormData(elmt, parent->child(parent->childCount()-1)); + } + else + { + // add Defaults + // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes + bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); + this->appendChild(newItem); + return newItem; + } +// } +// else +// { +// nlinfo("getNodeByName returned false"); +// } + } + } + } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index f440d1cf4..c56422caf 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -33,11 +33,13 @@ namespace GeorgesQt public: CFormItem(NLGEORGES::UFormElm *elm, const QList &data, CFormItem *parent = 0, - NLGEORGES::UFormElm::TWhereIsValue = NLGEORGES::UFormElm::ValueForm, - NLGEORGES::UFormElm::TWhereIsNode = NLGEORGES::UFormElm::NodeForm); + NLGEORGES::UFormElm::TWhereIsValue wV = NLGEORGES::UFormElm::ValueForm, + NLGEORGES::UFormElm::TWhereIsNode wN = NLGEORGES::UFormElm::NodeForm); ~CFormItem(); void appendChild(CFormItem *child); + //CFormItem *add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot); + CFormItem *add(NLGEORGES::UFormElm* root, std::string elmName); CFormItem *child(int row); int childCount() const; @@ -56,13 +58,18 @@ namespace GeorgesQt return whereN; } - private: + void setValueFrom(NLGEORGES::UFormElm::TWhereIsValue wV) { whereV = wV; } + void setNodeFrom(NLGEORGES::UFormElm::TWhereIsNode wN) { whereN = wN; } + + + private: + //CFormItem() { whereV = NLGEORGES::UFormElm::ValueForm; whereN = NLGEORGES::UFormElm::NodeForm; } QList childItems; QList itemData; CFormItem *parentItem; NLGEORGES::UFormElm* formElm; - NLGEORGES::UFormElm::TWhereIsValue whereV; - NLGEORGES::UFormElm::TWhereIsNode whereN; + NLGEORGES::UFormElm::TWhereIsValue whereV; + NLGEORGES::UFormElm::TWhereIsNode whereN; }; // CFormItem } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index 3bdc680ff..92da6e8a0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -61,7 +61,7 @@ namespace GeorgesQt // Set the default sheet dir dir to the level design path. m_lastSheetDir = "."; QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); m_lastSheetDir = settings->value(Core::Constants::LEVELDESIGN_PATH, "l:/leveldesign").toString(); settings->endGroup(); @@ -102,12 +102,12 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::headerClicked(int section) { if (section == 0) - { + { if (*(m_header->expanded())) m_ui.treeView->expandAll(); else m_ui.treeView->collapseAll(); - } + } } void CGeorgesTreeViewDialog::setForm(const CForm *form) @@ -119,8 +119,8 @@ namespace GeorgesQt { if(NLMISC::CPath::exists(formName.toStdString())) { - //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toStdString())); - return (NLGEORGES::CForm *)m_georges->loadForm(formName.toStdString()); + //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toStdString())); + return (NLGEORGES::CForm *)m_georges->loadForm(formName.toStdString()); } //else //{ @@ -156,56 +156,56 @@ namespace GeorgesQt // } // return form; //} - nlinfo("File '%s' does not exist!", formName.toStdString().c_str()); + nlinfo("File '%s' does not exist!", formName.toStdString().c_str()); return 0; } NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByDfnName(const QString dfnName) { - if(NLMISC::CPath::exists(dfnName.toStdString())) - { - // Create a new form object. - NLGEORGES::CForm *form = new NLGEORGES::CForm(); - m_form = form; + if(NLMISC::CPath::exists(dfnName.toStdString())) + { + // Create a new form object. + NLGEORGES::CForm *form = new NLGEORGES::CForm(); + m_form = form; - // Retrieve a copy of the root definition. - NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toStdString())); + // Retrieve a copy of the root definition. + NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toStdString())); - // Next we'll use the root node to build a new form. - NLGEORGES::CFormElmStruct *fes = dynamic_cast(getRootNode(0)); - fes->build(formDfn); + // Next we'll use the root node to build a new form. + NLGEORGES::CFormElmStruct *fes = dynamic_cast(getRootNode(0)); + fes->build(formDfn); - // And then initialize the held elements; - for(uint i = 0; i(getRootNode(i+1)); - fes->build(formDfn); - } + // And then initialize the held elements; + for(uint i = 0; i(getRootNode(i+1)); + fes->build(formDfn); + } - return form; - } - nlinfo("File '%s' does not exist!", dfnName.toStdString().c_str()); - return NULL; + return form; + } + nlinfo("File '%s' does not exist!", dfnName.toStdString().c_str()); + return NULL; } NLGEORGES::CFormElm *CGeorgesTreeViewDialog::getRootNode(uint slot) { - NLGEORGES::CForm *form = getFormPtr(); + NLGEORGES::CForm *form = getFormPtr(); - if(slot == 0) - { - const NLGEORGES::UFormElm &formElm = form->getRootNode(); - return (NLGEORGES::CFormElm *)&formElm; - } + if(slot == 0) + { + const NLGEORGES::UFormElm &formElm = form->getRootNode(); + return (NLGEORGES::CFormElm *)&formElm; + } - // Make sure the slot value is valid and then return the corresponding element. - nlassert(slot < NLGEORGES::CForm::HeldElementCount+1); - return getFormPtr()->HeldElements[slot-1]; + // Make sure the slot value is valid and then return the corresponding element. + nlassert(slot < NLGEORGES::CForm::HeldElementCount+1); + return getFormPtr()->HeldElements[slot-1]; } NLGEORGES::CForm *CGeorgesTreeViewDialog::getFormPtr() { - return dynamic_cast(m_form); + return dynamic_cast(m_form); } void CGeorgesTreeViewDialog::loadFormIntoDialog(CForm *form) @@ -219,14 +219,16 @@ namespace GeorgesQt UFormElm *root = 0; root = &m_form->getRootNode(); + // Extract the parent forms into the list of parents in the dialog. QStringList parents; - uint cnt = form->getParentCount(); - for (uint i = 0; i < cnt /*form->getParentCount()*/; i++) + uint cnt = form->getParentCount(); + for (uint i = 0; i < cnt /*form->getParentCount()*/; i++) { UForm *u = m_form->getParentForm(i); parents << u->getFilename().c_str(); } + // Exact the comment box for the dialog. QString comments; comments = m_form->getComment().c_str(); @@ -255,7 +257,7 @@ namespace GeorgesQt { loadedForm = m_form->getFilename().c_str(); - CGeorgesFormModel *model = new CGeorgesFormModel(root,deps,comments,parents,m_header->expanded()); + CGeorgesFormModel *model = new CGeorgesFormModel(m_form,deps,comments,parents,m_header->expanded()); CGeorgesFormProxyModel *proxyModel = new CGeorgesFormProxyModel(); proxyModel->setSourceModel(model); m_ui.treeView->setModel(proxyModel); @@ -317,12 +319,12 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::write( ) { - NLMISC::COFile file; - std::string s = NLMISC::CPath::lookup(loadedForm.toStdString(), false); - if(file.open (s)) - { - try - { + NLMISC::COFile file; + std::string s = NLMISC::CPath::lookup(loadedForm.toStdString(), false); + if(file.open (s)) + { + try + { // if (loadedForm.contains(".typ")) // { // //nlassert (Type != NULL); @@ -335,7 +337,7 @@ namespace GeorgesQt // // flushValueChange (); // //} // //Type->write (xmlStream.getDocument (), theApp.Georges4CVS); - // //modify (NULL, NULL, false); + // //modify (NULL, NULL, false); // //flushValueChange (); // //UpdateAllViews (NULL); // //return TRUE; @@ -357,17 +359,17 @@ namespace GeorgesQt // } // else // { - nlassert (m_form != NULL); + nlassert (m_form != NULL); - // Write the file + // Write the file // /*if (IsModified ()) // { // ((CForm*)(UForm*)Form)->Header.MinorVersion++; // }*/ // //((CForm*)(UForm*)Form)->write (xmlStream.getDocument (), lpszPathName, theApp.Georges4CVS); - m_form->write(file, false); - setWindowTitle(windowTitle().remove("*")); - m_modified = false; + m_form->write(file, false); + setWindowTitle(windowTitle().remove("*")); + m_modified = false; // //if (strcmp (xmlStream.getErrorString (), "") != 0) // //{ // // char message[512]; @@ -381,16 +383,16 @@ namespace GeorgesQt // // Get the left view // //CView* pView = getLeftView (); // } - } - catch (Exception &e) - { - nlerror("Error while loading file: %s", e.what()); - } - } - else - { - nlerror("Can't open the file %s for writing.", s.c_str()); - } + } + catch (Exception &e) + { + nlerror("Error while loading file: %s", e.what()); + } + } + else + { + nlerror("Can't open the file %s for writing.", s.c_str()); + } } void CGeorgesTreeViewDialog::doubleClicked ( const QModelIndex & index ) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h index e34ab572b..6f7b57acc 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h @@ -57,14 +57,14 @@ namespace GeorgesQt bool isModified() {return m_modified;} void setModified(bool m) {m_modified = m;} - NLGEORGES::CForm* getFormByName(const QString formName); - NLGEORGES::CForm* getFormByDfnName(const QString dfnName); + NLGEORGES::CForm* getFormByName(const QString formName); + NLGEORGES::CForm* getFormByDfnName(const QString dfnName); - /// Retrieves the root element based on the slot (document or held elements.) - NLGEORGES::CFormElm *getRootNode(uint slot); + /// Retrieves the root element based on the slot (document or held elements.) + NLGEORGES::CFormElm *getRootNode(uint slot); - /// Returns the form as a CForm pointer. - NLGEORGES::CForm *getFormPtr(); + /// Returns the form as a CForm pointer. + NLGEORGES::CForm *getFormPtr(); void addParentForm(QString parentFormNm); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index 9e3f97c48..b8c9f56ff 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -16,13 +16,18 @@ #include "georgesform_model.h" +// System Includes +#include + // NeL includes #include #include #include +#include #include #include #include +#include // Qt includes #include @@ -43,653 +48,848 @@ using namespace NLGEORGES; namespace GeorgesQt { - CGeorgesFormModel::CGeorgesFormModel(UFormElm *rootElm, QMap< QString, QStringList> deps, - QString comment, QStringList parents, bool *expanded, QObject *parent) : QAbstractItemModel(parent) - { - - m_rootData << "Value" << "Data" << "Extra";// << "Type"; - m_rootElm = rootElm; - m_rootItem = new CFormItem(m_rootElm, m_rootData); - m_dependencies = deps; - m_comments = comment; - m_parents = parents; - m_parentRows = new QList; - m_expanded = expanded; - - setupModelData(); - } - - CGeorgesFormModel::~CGeorgesFormModel() - { - delete m_rootItem; - } - - /******************************************************************************/ - - QVariant CGeorgesFormModel::data(const QModelIndex &p_index, int p_role) const - { - if (!p_index.isValid()) - return QVariant(); - - switch (p_role) - { - case Qt::DisplayRole: - { - return getItem(p_index)->data(p_index.column()); - } - case Qt::BackgroundRole: - { - QBrush defaultBrush = QBrush(QColor(255,0,0,30)); - QBrush parentBrush = QBrush(QColor(0,255,0,30)); - - // if elm not existing it must be some kind of default or type value - if(!getItem(p_index)->getFormElm()) - { - return defaultBrush; - } - - // else it might be some parent elm - switch (getItem(p_index)->nodeFrom()) - { - case NLGEORGES::UFormElm::NodeParentForm: - { - return parentBrush; - } - case NLGEORGES::UFormElm::NodeForm: - { - switch (getItem(p_index)->valueFrom()) - { - case NLGEORGES::UFormElm::ValueParentForm: - { - return parentBrush; - } - default: - { - // parent status test kindof ugly, testing only 2 steps deep - // only needed for colorization as treeview default hides childs - // when parent is hidden - CFormItem *parent = getItem(p_index)->parent(); - if (parent) - { - if (parent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - - CFormItem *parentParent = parent->parent(); - if (parentParent) - { - if (parentParent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - } // endif parentParent - } // endif parent - } // end default - } // end switch valueFrom - } // end case nodeForm - } // end switch nodeFrom - return QVariant(); - } - case Qt::DecorationRole: - { - if (p_index.column() == 2) - { - //p_index. - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - - QString value = item->data(1).toString(); - //QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - return QIcon(path); - } - } - return QVariant(); - break; - } - case Qt::ToolTipRole: - { - if (p_index.column() == 2) - { - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - QString value = item->data(1).toString(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - - QString imageTooltip = QString("").arg(path); - - return imageTooltip; - } - } - return QVariant(); - break; - } - default: - return QVariant(); - } - } - - /******************************************************************************/ - - CFormItem *CGeorgesFormModel::getItem(const QModelIndex &index) const - { - if (index.isValid()) - { - CFormItem *item = static_cast(index.internalPointer()); - if (item) - return item; - } - return m_rootItem; - } - - /******************************************************************************/ - - bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, - int role) - { - - if (role != Qt::EditRole) - return false; - - CFormItem *item = getItem(index); - bool result = item->setData(index.column(), value); - - Q_EMIT dataChanged(index, index); - - //setupModelData(); - return result; - } - - /******************************************************************************/ - - Qt::ItemFlags CGeorgesFormModel::flags(const QModelIndex& index) const { - - if (!index.isValid()) - return 0; - - Qt::ItemFlags returnValue = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - - if(index.column() == 1) - returnValue |= Qt::ItemIsEditable; - - return returnValue; - - } - - /******************************************************************************/ - - QVariant CGeorgesFormModel::headerData(int section, - Qt::Orientation orientation, int role) const - { - if (orientation == Qt::Horizontal) - { - if (role == Qt::DisplayRole) - return m_rootItem->data(section); - if (role == Qt::TextAlignmentRole) - return Qt::AlignLeft; - if (section == 0 && role == Qt::DecorationRole) - { - // transparent pixmap as we paint it ourself with tree brach - // if we extend the HeaderView::paintSection for the CE_HeaderLabel - // we could drop this - QPixmap pixmap = QPixmap( - QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize), - QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize)); - // Create new picture for transparent - QPixmap transparent(pixmap.size()); - - // Do transparency - transparent.fill(Qt::transparent); - QPainter p(&transparent); - p.setCompositionMode(QPainter::CompositionMode_Source); - p.drawPixmap(0, 0, pixmap); - p.setCompositionMode(QPainter::CompositionMode_DestinationIn); - // Set transparency level to 150 (possible values are 0-255) - // The alpha channel of a color specifies the transparency effect, - // 0 represents a fully transparent color, while 255 represents - // a fully opaque color. - p.fillRect(transparent.rect(), QColor(0, 0, 0, 0)); - p.end(); - - // Set original picture's reference to new transparent one - pixmap = transparent; - return pixmap; - } - } - return QVariant(); - } - - /******************************************************************************/ - - QModelIndex CGeorgesFormModel::index(int row, int column, const QModelIndex &parent) - const - { - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - CFormItem *parentItem; - - if (!parent.isValid()) - parentItem = m_rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - CFormItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else - return QModelIndex(); - } - - /******************************************************************************/ - - QModelIndex CGeorgesFormModel::parent(const QModelIndex &index) const - { - if (!index.isValid()) - return QModelIndex(); - - CFormItem *childItem = static_cast(index.internalPointer()); - CFormItem *parentItem = childItem->parent(); - - if (parentItem == m_rootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); - } - - /******************************************************************************/ - - int CGeorgesFormModel::rowCount(const QModelIndex &parent) const { - - CFormItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = m_rootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); - - } - - /******************************************************************************/ - - int CGeorgesFormModel::columnCount(const QModelIndex &parent) const { - - if (parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); - else - return m_rootItem->columnCount(); - - } - - /******************************************************************************/ - - void CGeorgesFormModel::loadFormData(UFormElm *root, CFormItem *parent) { - - if (!root) - return; - - uint num = 0; - - - if (root->isStruct()) - { - //((CFormElm*)root)->getForm()->getComment(); - uint structSize = 0; - root->getStructSize(structSize); - while (num < structSize) - { - UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - // Append a new item to the current parent's list of children. - std::string elmName; - if(root->getStructNodeName(num, elmName)) - { - QList columnData; - //QVariant value; - std::string value; - //NLMISC::CRGBA value_color; - //uint value_uint; - //sint value_sint; - //double value_double; - QString elmtType = ""; - UFormElm *elmt = 0; - if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) - { - if (elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) - elmtType = "Struct"; - if (elmt->isAtom()) - { - elmtType = "Atom"; - uint numDefinitions = 0; - const UType *type = elmt->getType(); - if (type) - { - numDefinitions = type->getNumDefinition(); - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (type->getType()) - { - case UType::UnsignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_uint");break; - case UType::SignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_sint");break; - case UType::Double: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); - elmtType.append("_double");break; - case UType::String: - elmtType.append("_string");break; - case UType::Color: - elmtType.append("_color");break; - default: - elmtType.append("_unknownType"); - } - } - else - { - elmtType.append("_noType"); - } - - if (numDefinitions) - { - std::string l, v; - QString tmpLabel, tmpValue; - for (uint i = 0; i < numDefinitions; i++) - { - type->getDefinition(i,l,v); - tmpLabel = l.c_str(); - tmpValue = v.c_str(); - if (type->getType() == UType::SignedInt) - { - if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { - value = l; - break; - } - } - if (type->getType() == UType::String) - { - if (QString(value.c_str()) == tmpValue) - { - value = l; - break; - } - } - } - } - } - if (elmt->isVirtualStruct()) - { - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - elmtType = "VirtualStruct"; - } - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - //if (parents.last()->childCount() > 0) { - // parents << parents.last()->child(parents.last()->childCount()-1); - //} - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - else - { - // add Defaults - // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes - bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - } - } - else - { - nlinfo("getNodeByName returned false"); - } - } - num++; - } - } - if (root->isArray()) - { - uint arraySize = 0; - root->getArraySize(arraySize); - while (num < arraySize) - { - std::string elmName; - if(root->getArrayNodeName(elmName, num)) - { - QList columnData; - std::string value; - QString elmtType = ""; - - UFormElm *elmt = 0; - if(root->getArrayNode(&elmt,0) && elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) { - elmtType = "Struct"; - } - if (elmt->isAtom()) - { - elmt->getValue(value); - elmtType = "Atom"; - } - if (elmt->isVirtualStruct()) - elmtType = "VirtualStruct"; - - elmtType.append("_arrayValue"); - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent)); - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - } - num++; - } - } - } - - /******************************************************************************/ - - void CGeorgesFormModel::loadFormHeader() - { - - if (m_parents.size()) - { - CFormItem *fi_pars = new CFormItem(m_rootElm, QList() << "parents" << "" << "", m_rootItem); - m_rootItem->appendChild(fi_pars); - - Q_FOREACH(QString str, m_parents) - { - fi_pars->appendChild(new CFormItem(m_rootElm, QList() << str << "" << "", fi_pars)); - } - } - - /*QStringList dfns = _dependencies["dfn"]; - QStringList typs = _dependencies["typ"]; - - _dependencies.remove("dfn"); - _dependencies.remove("typ"); - - CFormItem *fi_dep = new CFormItem(_rootElm, QList() << "dependencies", _rootItem); - _rootItem->appendChild(fi_dep); - - if (!dfns.isEmpty()) { - CFormItem *fi_dfn = new CFormItem(_rootElm, QList() << "dfn", fi_dep); - fi_dep->appendChild(fi_dfn); - foreach(QString str, dfns) { - fi_dfn->appendChild(new CFormItem(_rootElm, QList() << str, fi_dfn)); - } - } - if (!typs.isEmpty()) { - CFormItem *fi_typ = new CFormItem(_rootElm, QList() << "typ", fi_dep); - fi_dep->appendChild(fi_typ); - foreach(QString str, typs) { - fi_typ->appendChild(new CFormItem(_rootElm, QList() << str, fi_typ)); - } - } - if (!_dependencies.isEmpty()) { - CFormItem *fi_other = new CFormItem(_rootElm, QList() << "other", fi_dep); - fi_dep->appendChild(fi_other); - foreach(QStringList list, _dependencies) { - foreach(QString str, list) { - fi_other->appendChild(new CFormItem(_rootElm, QList() << str, fi_other)); - } - } - }*/ - } - - /******************************************************************************/ - - void CGeorgesFormModel::setupModelData() - { - loadFormHeader(); - loadFormData(m_rootElm, m_rootItem); - } - - /******************************************************************************/ - - void CGeorgesFormModel::setShowParents( bool show ) { - m_showParents = show; - Q_EMIT layoutAboutToBeChanged(); - Q_EMIT layoutChanged(); - } - void CGeorgesFormModel::setShowDefaults( bool show ) - { - m_showDefaults = show; - Q_EMIT layoutAboutToBeChanged(); - Q_EMIT layoutChanged(); - } - - void CGeorgesFormModel::addParentForm(QString parentForm) - { - beginResetModel(); - m_parents.push_back(parentForm); - delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); - setupModelData(); - endResetModel(); - } - - void CGeorgesFormModel::removeParentForm(QString parentForm) - { - beginResetModel(); - m_parents.removeOne(parentForm); - - delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); - setupModelData(); - endResetModel(); - } + CGeorgesFormModel::CGeorgesFormModel(UForm *form, QMap< QString, QStringList> deps, + QString comment, QStringList parents, bool *expanded, QObject *parent) : QAbstractItemModel(parent) + { + m_form = form; + m_rootData << "Value" << "Data" << "Extra";// << "Type"; + m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_dependencies = deps; + m_comments = comment; + m_parents = parents; + m_parentRows = new QList; + m_expanded = expanded; + + setupModelData(); + } + + CGeorgesFormModel::~CGeorgesFormModel() + { + delete m_rootItem; + } + + /******************************************************************************/ + + QVariant CGeorgesFormModel::data(const QModelIndex &p_index, int p_role) const + { + if (!p_index.isValid()) + return QVariant(); + + switch (p_role) + { + case Qt::DisplayRole: + { + return getItem(p_index)->data(p_index.column()); + } + case Qt::BackgroundRole: + { + QBrush defaultBrush = QBrush(QColor(255,0,0,30)); + QBrush parentBrush = QBrush(QColor(0,255,0,30)); + + // if elm not existing it must be some kind of default or type value + if(!getItem(p_index)->getFormElm()) + { + return defaultBrush; + } + + // else it might be some parent elm + switch (getItem(p_index)->nodeFrom()) + { + case NLGEORGES::UFormElm::NodeParentForm: + { + return parentBrush; + } + case NLGEORGES::UFormElm::NodeForm: + { + switch (getItem(p_index)->valueFrom()) + { + case NLGEORGES::UFormElm::ValueParentForm: + { + return parentBrush; + } + default: + { + // parent status test kindof ugly, testing only 2 steps deep + // only needed for colorization as treeview default hides childs + // when parent is hidden + CFormItem *parent = getItem(p_index)->parent(); + if (parent) + { + if (parent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) + { + return parentBrush; + } + + CFormItem *parentParent = parent->parent(); + if (parentParent) + { + if (parentParent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) + { + return parentBrush; + } + } // endif parentParent + } // endif parent + } // end default + } // end switch valueFrom + } // end case nodeForm + } // end switch nodeFrom + return QVariant(); + } + case Qt::DecorationRole: + { + if (p_index.column() == 2) + { + //p_index. + QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); + CFormItem *item = getItem(in); + + QString value = item->data(1).toString(); + //QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); + + /*if (value.contains(".shape")) + { + if (Modules::objViewInt()) + { + QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); + if (icon) + { + if(icon->isNull()) + return QIcon(":/images/pqrticles.png"); + else + return QIcon(*icon); + } + else + { + return QIcon(); + } + } + }*/ + if(value.contains(".tga") || value.contains(".png")) + { + QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); + if(path.isEmpty()) + { + path = ":/images/pqrticles.png"; + } + return QIcon(path); + } + } + return QVariant(); + break; + } + case Qt::ToolTipRole: + { + if (p_index.column() == 2) + { + QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); + CFormItem *item = getItem(in); + QString value = item->data(1).toString(); + + /*if (value.contains(".shape")) + { + if (Modules::objViewInt()) + { + QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); + if (icon) + { + if(icon->isNull()) + return QIcon(":/images/pqrticles.png"); + else + return QIcon(*icon); + } + else + { + return QIcon(); + } + } + }*/ + if(value.contains(".tga") || value.contains(".png")) + { + QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); + if(path.isEmpty()) + { + path = ":/images/pqrticles.png"; + } + + QString imageTooltip = QString("").arg(path); + + return imageTooltip; + } + } + return QVariant(); + break; + } + default: + return QVariant(); + } + } + + /******************************************************************************/ + + CFormItem *CGeorgesFormModel::getItem(const QModelIndex &index) const + { + if (index.isValid()) + { + CFormItem *item = static_cast(index.internalPointer()); + if (item) + return item; + } + return m_rootItem; + } + + /******************************************************************************/ + + bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, + int role) + { + + if (role != Qt::EditRole) + return false; + + CFormItem *item = getItem(index); + bool result = item->setData(index.column(), value); + + Q_EMIT dataChanged(index, index); + + //setupModelData(); + return result; + } + + /******************************************************************************/ + + Qt::ItemFlags CGeorgesFormModel::flags(const QModelIndex& index) const { + + if (!index.isValid()) + return 0; + + Qt::ItemFlags returnValue = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + + if(index.column() == 1) + returnValue |= Qt::ItemIsEditable; + + return returnValue; + + } + + /******************************************************************************/ + + QVariant CGeorgesFormModel::headerData(int section, + Qt::Orientation orientation, int role) const + { + if (orientation == Qt::Horizontal) + { + if (role == Qt::DisplayRole) + return m_rootItem->data(section); + if (role == Qt::TextAlignmentRole) + return Qt::AlignLeft; + if (section == 0 && role == Qt::DecorationRole) + { + // transparent pixmap as we paint it ourself with tree brach + // if we extend the HeaderView::paintSection for the CE_HeaderLabel + // we could drop this + QPixmap pixmap = QPixmap( + QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize), + QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize)); + // Create new picture for transparent + QPixmap transparent(pixmap.size()); + + // Do transparency + transparent.fill(Qt::transparent); + QPainter p(&transparent); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.drawPixmap(0, 0, pixmap); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + // Set transparency level to 150 (possible values are 0-255) + // The alpha channel of a color specifies the transparency effect, + // 0 represents a fully transparent color, while 255 represents + // a fully opaque color. + p.fillRect(transparent.rect(), QColor(0, 0, 0, 0)); + p.end(); + + // Set original picture's reference to new transparent one + pixmap = transparent; + return pixmap; + } + } + return QVariant(); + } + + /******************************************************************************/ + + QModelIndex CGeorgesFormModel::index(int row, int column, const QModelIndex &parent) + const + { + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + CFormItem *parentItem; + + if (!parent.isValid()) + parentItem = m_rootItem; + else + parentItem = static_cast(parent.internalPointer()); + + CFormItem *childItem = parentItem->child(row); + if (childItem) + return createIndex(row, column, childItem); + else + return QModelIndex(); + } + + /******************************************************************************/ + + QModelIndex CGeorgesFormModel::parent(const QModelIndex &index) const + { + if (!index.isValid()) + return QModelIndex(); + + CFormItem *childItem = static_cast(index.internalPointer()); + CFormItem *parentItem = childItem->parent(); + + if (parentItem == m_rootItem) + return QModelIndex(); + + return createIndex(parentItem->row(), 0, parentItem); + } + + /******************************************************************************/ + + int CGeorgesFormModel::rowCount(const QModelIndex &parent) const { + + CFormItem *parentItem; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parentItem = m_rootItem; + else + parentItem = static_cast(parent.internalPointer()); + + return parentItem->childCount(); + + } + + /******************************************************************************/ + + int CGeorgesFormModel::columnCount(const QModelIndex &parent) const { + + if (parent.isValid()) + return static_cast(parent.internalPointer())->columnCount(); + else + return m_rootItem->columnCount(); + + } + + /******************************************************************************/ + + void CGeorgesFormModel::loadFormData(UFormElm *root, CFormItem *parent) { + + if (!root) + return; + + uint num = 0; + + + if (root->isStruct()) + { + //((CFormElm*)root)->getForm()->getComment(); + uint structSize = 0; + root->getStructSize(structSize); + while (num < structSize) + { + UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; + UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; + // Append a new item to the current parent's list of children. + std::string elmName; + if(root->getStructNodeName(num, elmName)) + { + QList columnData; + //QVariant value; + std::string value; + //NLMISC::CRGBA value_color; + //uint value_uint; + //sint value_sint; + //double value_double; + QString elmtType = ""; + UFormElm *elmt = 0; + if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) + { + if (elmt) + { + if (elmt->isArray()) + elmtType = "Array"; + if (elmt->isStruct()) + elmtType = "Struct"; + if (elmt->isAtom()) + { + elmtType = "Atom"; + uint numDefinitions = 0; + const UType *type = elmt->getType(); + if (type) + { + numDefinitions = type->getNumDefinition(); + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (type->getType()) + { + case UType::UnsignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_uint");break; + case UType::SignedInt: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); + elmtType.append("_sint");break; + case UType::Double: + value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); + elmtType.append("_double");break; + case UType::String: + elmtType.append("_string");break; + case UType::Color: + elmtType.append("_color");break; + default: + elmtType.append("_unknownType"); + } + } + else + { + elmtType.append("_noType"); + } + + if (numDefinitions) + { + std::string l, v; + QString tmpLabel, tmpValue; + for (uint i = 0; i < numDefinitions; i++) + { + type->getDefinition(i,l,v); + tmpLabel = l.c_str(); + tmpValue = v.c_str(); + if (type->getType() == UType::SignedInt) + { + if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { + value = l; + break; + } + } + if (type->getType() == UType::String) + { + if (QString(value.c_str()) == tmpValue) + { + value = l; + break; + } + } + } + } + } + if (elmt->isVirtualStruct()) + { + root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + elmtType = "VirtualStruct"; + } + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); + //if (parents.last()->childCount() > 0) { + // parents << parents.last()->child(parents.last()->childCount()-1); + //} + loadFormData(elmt, parent->child(parent->childCount()-1)); + } + else + { + // add Defaults + // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes + bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); + switch (*whereN) + { + case UFormElm::NodeForm: + elmtType.append("_fromForm"); break; + case UFormElm::NodeParentForm: + elmtType.append("_fromParentForm"); break; + case UFormElm::NodeDfn: + elmtType.append("_isDFN"); break; + case UFormElm::NodeType: + elmtType.append("_isType"); break; + default: + elmtType.append("_noNode"); + } + switch (*whereV) + { + case UFormElm::ValueForm: + elmtType.append("_formValue"); break; + case UFormElm::ValueParentForm: + elmtType.append("_parentValue"); break; + case UFormElm::ValueDefaultDfn: + elmtType.append("_dfnValue"); break; + case UFormElm::ValueDefaultType: + elmtType.append("_typeValue"); break; + default: + elmtType.append("_noValue"); + } + + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); + } + } + else + { + nlinfo("getNodeByName returned false"); + } + } + num++; + } + } + if (root->isArray()) + { + uint arraySize = 0; + root->getArraySize(arraySize); + while (num < arraySize) + { + std::string elmName; + if(root->getArrayNodeName(elmName, num)) + { + QList columnData; + std::string value; + QString elmtType = ""; + + UFormElm *elmt = 0; + if(root->getArrayNode(&elmt,0) && elmt) + { + if (elmt->isArray()) + elmtType = "Array"; + if (elmt->isStruct()) { + elmtType = "Struct"; + } + if (elmt->isAtom()) + { + elmt->getValue(value); + elmtType = "Atom"; + } + if (elmt->isVirtualStruct()) + elmtType = "VirtualStruct"; + + elmtType.append("_arrayValue"); + columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; + parent->appendChild(new CFormItem(elmt, columnData, parent)); + loadFormData(elmt, parent->child(parent->childCount()-1)); + } + } + num++; + } + } + } + + CFormItem *CGeorgesFormModel::addStruct (CFormItem *parent, + NLGEORGES::CFormElmStruct *_struct, + NLGEORGES::CFormDfn *parentDfn, + const char *name, + uint structId, + const char *formName, + uint slot) +{ + // The form pointer + NLGEORGES::CForm *formPtr = static_cast(m_form); + + // Add the new node +// CFormItem *newNode = parent->add(/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); + CFormItem *newNode = parent->add(_struct, name); + + // Can be NULL in virtual DFN + if (parentDfn) + { + // Get the parents + std::vector arrayDfn; + arrayDfn.reserve (parentDfn->countParentDfn ()); + parentDfn->getParentDfn (arrayDfn); + + // For each child + uint elm=0; + for (uint dfn=0; dfngetNumEntry (); i++) + { + // Get the entry ref + NLGEORGES::CFormDfn::CEntry &entry = arrayDfn[dfn]->getEntry (i); + + // Form entry name + std::string entryName = (std::string (formName)+"."+entry.getName ()); + + // Is a struct ? + if ( (entry.getType () == NLGEORGES::UFormDfn::EntryDfn) || (entry.getType () == NLGEORGES::UFormDfn::EntryVirtualDfn) ) + { + // Is an array of struct ? + if (entry.getArrayFlag ()) + { + // Get it from the form + CFormElmArray *nextArray = NULL; + if (_struct && _struct->Elements[elm].Element) + nextArray = NLMISC::safe_cast (_struct->Elements[elm].Element); + + // Else, get it from the parent if we are not a virtual DFN (don't inheritate) + + // todo array of virtual struct + if (!nextArray && (entry.getType () != NLGEORGES::UFormDfn::EntryVirtualDfn) ) + { + // For each parent form + for (uint parent=0; parentgetParentCount (); parent++) + { + // Get the node by name + NLGEORGES::UFormElm *uNode; + if (formPtr->getParent (parent)->getRootNode ().getNodeByName (&uNode, entryName.c_str(), NULL, false) && uNode) + { + nextArray = NLMISC::safe_cast (uNode); + } + } + } + + // Add the new struct + addArray (newNode, nextArray, entry.getDfnPtr (), entry.getName().c_str(), elm, entryName.c_str (), slot); + } + else + { + // Add it + NLGEORGES::CFormElmStruct *nextForm = NULL; + + // Get it from the form + if (_struct && _struct->Elements[elm].Element) + nextForm = NLMISC::safe_cast (_struct->Elements[elm].Element); + + // Else, get it from the parent + if (!nextForm) + { + // For each parent form + for (uint parent=0; parentgetParentCount (); parent++) + { + // Get the node by name + NLGEORGES::UFormElm *uNode; + if (formPtr->getParent (parent)->getRootNode ().getNodeByName (&uNode, entryName.c_str(), NULL, false) && uNode) + { + nextForm = NLMISC::safe_cast (uNode); + } + } + } + + // Virtual Dfn pointer + NLGEORGES::CFormElmVirtualStruct *vStruct = ((entry.getType () == NLGEORGES::UFormDfn::EntryVirtualDfn) && nextForm) ? + NLMISC::safe_cast (nextForm) : NULL; + + NLGEORGES::CFormDfn *tmpDfn = vStruct ? + ((NLGEORGES::CFormDfn*)vStruct->FormDfn) : entry.getDfnPtr(); + // Add the new struct + addStruct (newNode, nextForm, tmpDfn, entry.getName().c_str(), elm, entryName.c_str(), slot); + } + } + // Array of type ? + else if ( entry.getArrayFlag () ) + { + NLGEORGES::CFormElmArray *nextArray = NULL; + + // Get it from the form + if (_struct && _struct->Elements[elm].Element) + nextArray = NLMISC::safe_cast (_struct->Elements[elm].Element); + + // Else, get it from the parent + if (!nextArray) + { + // For each parent form + for (uint parent=0; parentgetParentCount (); parent++) + { + // Get the node by name + NLGEORGES::UFormElm *uNode; + if (formPtr->getParent (parent)->getRootNode ().getNodeByName (&uNode, entryName.c_str(), NULL, false) && uNode) + { + nextArray = NLMISC::safe_cast (uNode); + } + } + } + + // Add the new array + addArray ( newNode, nextArray, NULL, entry.getName().c_str(), elm, entryName.c_str(), slot ); + } + + // Next element + elm++; + } + } + } + + return newNode; +} + +// *************************************************************************** + +CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, + NLGEORGES::CFormElmArray *array, + NLGEORGES::CFormDfn *rootDfn, + const char *name, + uint structId, + const char *formName, + uint slot) +{ + // Add the new node + //CFormItem *newNode = parent->add (/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); + CFormItem *newNode = parent->add (array, name); + + // The array exist + if (array) + { + // For each array element + for (uint elm=0; elmElements.size(); elm++) + { + // The form name + char formArrayElmName[512]; + NLMISC::smprintf (formArrayElmName, 512, "%s[%d]", formName, elm); + + // The name + char formArrayName[512]; + if (array->Elements[elm].Name.empty ()) + { + NLMISC::smprintf (formArrayName, 512, "#%d", elm); + } + else + { + NLMISC::smprintf (formArrayName, 512, "%s", array->Elements[elm].Name.c_str()); + } + + // Is a struct + if (rootDfn) + { + // Get struct ptr + NLGEORGES::CFormElmStruct *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; + addStruct (newNode, elmPtr, rootDfn, formArrayName, elm, formArrayElmName, slot); + } + else + { + NLGEORGES::CFormElmArray *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; + newNode->add (elmPtr, formArrayElmName); + //newNode->add (/*CGeorgesEditDocSub::Form,*/ formArrayName, elm, formArrayElmName, slot); + } + } + } + + return newNode; +} + + + + /******************************************************************************/ + + void CGeorgesFormModel::loadFormHeader() + { + + if (m_parents.size()) + { + CFormItem *fi_pars = new CFormItem(m_rootElm, QList() << "parents" << "" << "", m_rootItem); + m_rootItem->appendChild(fi_pars); + + Q_FOREACH(QString str, m_parents) + { + fi_pars->appendChild(new CFormItem(m_rootElm, QList() << str << "" << "", fi_pars)); + } + } + + /*QStringList dfns = _dependencies["dfn"]; + QStringList typs = _dependencies["typ"]; + + _dependencies.remove("dfn"); + _dependencies.remove("typ"); + + CFormItem *fi_dep = new CFormItem(_rootElm, QList() << "dependencies", _rootItem); + _rootItem->appendChild(fi_dep); + + if (!dfns.isEmpty()) { + CFormItem *fi_dfn = new CFormItem(_rootElm, QList() << "dfn", fi_dep); + fi_dep->appendChild(fi_dfn); + foreach(QString str, dfns) { + fi_dfn->appendChild(new CFormItem(_rootElm, QList() << str, fi_dfn)); + } + } + if (!typs.isEmpty()) { + CFormItem *fi_typ = new CFormItem(_rootElm, QList() << "typ", fi_dep); + fi_dep->appendChild(fi_typ); + foreach(QString str, typs) { + fi_typ->appendChild(new CFormItem(_rootElm, QList() << str, fi_typ)); + } + } + if (!_dependencies.isEmpty()) { + CFormItem *fi_other = new CFormItem(_rootElm, QList() << "other", fi_dep); + fi_dep->appendChild(fi_other); + foreach(QStringList list, _dependencies) { + foreach(QString str, list) { + fi_other->appendChild(new CFormItem(_rootElm, QList() << str, fi_other)); + } + } + }*/ + } + + /******************************************************************************/ + + void CGeorgesFormModel::setupModelData() + { + m_rootElm = &((NLGEORGES::CForm*)m_form)->Elements; + NLGEORGES::CFormElmStruct *rootstruct = &((NLGEORGES::CForm*)m_form)->Elements; + loadFormHeader(); + addStruct(m_rootItem, rootstruct, rootstruct->FormDfn, "Content", 0xffffffff, "", 0); + //loadFormData(m_rootElm, m_rootItem); + } + + /******************************************************************************/ + + void CGeorgesFormModel::setShowParents( bool show ) { + m_showParents = show; + Q_EMIT layoutAboutToBeChanged(); + Q_EMIT layoutChanged(); + } + void CGeorgesFormModel::setShowDefaults( bool show ) + { + m_showDefaults = show; + Q_EMIT layoutAboutToBeChanged(); + Q_EMIT layoutChanged(); + } + + void CGeorgesFormModel::addParentForm(QString parentForm) + { + beginResetModel(); + m_parents.push_back(parentForm); + delete m_rootItem; + m_rootItem = new CFormItem(m_rootElm, m_rootData); + setupModelData(); + endResetModel(); + } + + void CGeorgesFormModel::removeParentForm(QString parentForm) + { + beginResetModel(); + m_parents.removeOne(parentForm); + + delete m_rootItem; + m_rootItem = new CFormItem(m_rootElm, m_rootData); + setupModelData(); + endResetModel(); + } } /* namespace GeorgesQt */ /* end of file */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h index 710598236..493f672dd 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h @@ -27,6 +27,10 @@ namespace NLGEORGES { class UFormElm; + class UForm; + class CFormElmStruct; + class CFormDfn; + class CFormElmArray; } namespace GeorgesQt @@ -38,7 +42,7 @@ namespace GeorgesQt { public: - CGeorgesFormModel(NLGEORGES::UFormElm *root, QMap< QString, QStringList> deps, + CGeorgesFormModel(NLGEORGES::UForm *form, QMap< QString, QStringList> deps, QString comment, QStringList parents, bool* expanded, QObject *parent = 0); ~CGeorgesFormModel(); @@ -58,15 +62,22 @@ namespace GeorgesQt void setShowDefaults( bool show ); void addParentForm(QString parentForm); void removeParentForm(QString parentForm); - NLGEORGES::UFormElm *getRootForm() { return m_rootElm; } + NLGEORGES::UFormElm *getRootForm() { return m_rootElm; } + + CFormItem *addStruct (CFormItem *parent, NLGEORGES::CFormElmStruct *_struct, NLGEORGES::CFormDfn *parentDfn, + const char *name, uint structId, const char *formName, uint slot); + + CFormItem *addArray(CFormItem *parent, NLGEORGES::CFormElmArray *array, NLGEORGES::CFormDfn *rootDfn, + const char *name, uint structId, const char *formName, uint slot); private: void setupModelData(); void loadFormData(NLGEORGES::UFormElm *rootElm, CFormItem *parent); void loadFormHeader(); + NLGEORGES::UForm* m_form; CFormItem* m_rootItem; - NLGEORGES::UFormElm* m_rootElm; + NLGEORGES::UFormElm* m_rootElm; QList m_rootData; QMap< QString, QStringList> m_dependencies; QString m_comments; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp index a65f510c4..edbc31275 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp @@ -66,7 +66,7 @@ CMainWindow::CMainWindow(QWidget *parent) _isGraphicsInitialized(false), _isGraphicsEnabled(false), _isSoundInitialized(false), - _isSoundEnabled(true), + _isSoundEnabled(false), // MTR workaround for sheet id nonsense _GraphicsViewport(NULL), _lastDir("."), _mouseMode(NL3D::U3dMouseListener::edit3d) From 51705fd800e1bb804751a4ac3de3c5d4b0cd8d49 Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 20 Sep 2012 16:39:21 -0500 Subject: [PATCH 011/220] Changed: #1306 Radically changed the plugin in a new branch to match the way classic GE loads forms. - Refactored the tree view to show only structs, arrays, vstructs and eliminated atoms from its view. - Refactored the form view to have a Qt Properties Browser - Refactored the loader to use the classic GE addStruct/addArray. - Moved some functionality into CFormItem. - Added icons from classic GE and configured model/item to return them appropriately. - Getting read for changes via undo commands. - Eliminating/ignoring the hold/slots business from classic GE code. --- .../src/plugins/georges_editor/CMakeLists.txt | 8 +- .../src/plugins/georges_editor/actions.cpp | 17 + .../src/plugins/georges_editor/actions.h | 20 + .../plugins/georges_editor/formdelegate.cpp | 4 + .../src/plugins/georges_editor/formdelegate.h | 4 + .../src/plugins/georges_editor/formitem.cpp | 400 ++++++----------- .../src/plugins/georges_editor/formitem.h | 160 +++---- .../plugins/georges_editor/georges_editor.qrc | 7 + .../georges_treeview_dialog.cpp | 255 +++++------ .../georges_editor/georges_treeview_form.ui | 110 +++-- .../georges_editor/georgesform_model.cpp | 406 ++---------------- .../georgesform_proxy_model.cpp | 3 + .../georges_editor/georgesform_proxy_model.h | 3 +- .../plugins/georges_editor/images/array.ico | Bin 0 -> 1406 bytes .../plugins/georges_editor/images/header.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/hold.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/root.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/struct.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/vstruct.ico | Bin 0 -> 318 bytes .../plugins/georges_editor/images/zfee51.ico | Bin 0 -> 2238 bytes 20 files changed, 481 insertions(+), 916 deletions(-) create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/struct.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico create mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt index 3661decef..5aba06740 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt @@ -1,12 +1,14 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES}) + ${QT_INCLUDES} + ${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/qtpropertybrowser) FILE(GLOB SRC *.cpp *.h) SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) SET(OVQT_PLUG_GEORGES_EDITOR_HDR georges_editor_plugin.h georges_editor_form.h @@ -36,7 +38,7 @@ SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) ADD_LIBRARY(ovqt_plugin_georges_editor MODULE ${SRC} ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_GEORGES_EDITOR_UI_HDRS} ${OVQT_PLUGIN_GEORGES_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_georges_editor ovqt_plugin_core nelmisc nelgeorges ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(ovqt_plugin_georges_editor ovqt_plugin_core nelmisc nelgeorges qt_property_browser ${QT_LIBRARIES}) NL_DEFAULT_PROPS(ovqt_plugin_georges_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Georges Editor") NL_ADD_RUNTIME_FLAGS(ovqt_plugin_georges_editor) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp new file mode 100644 index 000000000..dba45fb96 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -0,0 +1,17 @@ +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "actions.h" \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h new file mode 100644 index 000000000..c646adc72 --- /dev/null +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -0,0 +1,20 @@ +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ACTIONS_H +#define ACTIONS_H + +#endif // ACTIONS_H \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp index 7f21fa072..ab306bf05 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp @@ -37,6 +37,8 @@ #include "georgesform_proxy_model.h" #include "formitem.h" +#if 0 + namespace GeorgesQt { @@ -276,3 +278,5 @@ namespace GeorgesQt editor->setGeometry(r); } } /* namespace GeorgesQt */ + +#endif // 0 \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h index b6885833e..42b10ef3d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h @@ -19,6 +19,8 @@ #include +#if 0 + namespace GeorgesQt { @@ -38,4 +40,6 @@ namespace GeorgesQt }; } +#endif // 0 + #endif // FORMDELEGATE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index 014338a2d..98bffa7e2 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -17,9 +17,11 @@ #include "formitem.h" // Qt includes +#include // NeL includes #include +#include #include #include @@ -27,15 +29,8 @@ using namespace NLGEORGES; namespace GeorgesQt { - - CFormItem::CFormItem(NLGEORGES::UFormElm* elm, const QList &data, CFormItem *parent, - NLGEORGES::UFormElm::TWhereIsValue wV, NLGEORGES::UFormElm::TWhereIsNode wN) + CFormItem::CFormItem() { - parentItem = parent; - itemData = data; - formElm = elm; - whereV = wV; - whereN = wN; } CFormItem::~CFormItem() @@ -61,12 +56,14 @@ namespace GeorgesQt int CFormItem::columnCount() const { //nlinfo("columnCount %d",itemData.count()); - return itemData.count(); + //return itemData.count(); + return 1; } QVariant CFormItem::data(int column) const { - return itemData.value(column); + //return itemData.value(column); + return QVariant(_Name.c_str()); } CFormItem *CFormItem::parent() @@ -84,275 +81,146 @@ namespace GeorgesQt bool CFormItem::setData(int column, const QVariant &value) { - if (column < 0 || column >= itemData.size()) + if (column != 0) return false; - // TODO: default values - if (!formElm) - return false; + bool deleteInsert = false; - itemData[column] = value; - if (formElm->isAtom()) - { - const NLGEORGES::UType *type = formElm->getType(); - if (type) - { - switch (type->getType()) - { - case NLGEORGES::UType::UnsignedInt: - case NLGEORGES::UType::SignedInt: - case NLGEORGES::UType::Double: - case NLGEORGES::UType::String: - if (parentItem->formElm->isArray()) - { - //((NLGEORGES::CFormElm*)parentItem->formElm);//->arrayInsertNodeByName( - //if(parentItem->formElm->getArrayNode(elmName, num)) - //{ - //} + - bool ok; - // TODO: the node can be renamed from eg "#0" to "foobar" - int arrayIndex = itemData[0].toString().remove("#").toInt(&ok); - if(ok) - { - NLGEORGES::UFormElm *elmt = 0; - if(parentItem->formElm->getArrayNode(&elmt, arrayIndex) && elmt) - { - if (elmt->isAtom()) - { - ((NLGEORGES::CFormElmAtom*)elmt)->setValue(value.toString().toStdString().c_str()); - nldebug(QString("array element string %1 %2") - .arg(itemData[0].toString()).arg(value.toString()) - .toStdString().c_str()); - } - } - } - } - else - { - if(parentItem->formElm->setValueByName( - value.toString().toStdString().c_str(), - itemData[0].toString().toStdString().c_str())) - { - nldebug(QString("string %1 %2") - .arg(itemData[0].toString()).arg(value.toString()) - .toStdString().c_str()); - } - else - { - nldebug(QString("FAILED string %1 %2") - .arg(itemData[0].toString()).arg(value.toString()) - .toStdString().c_str()); - } - } - break; - case NLGEORGES::UType::Color: - nldebug("Color is TODO"); - break; - default: - break; - } - } - } - else + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *parentNode; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form=static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if (parentItem && parentItem->nodeType () == CFormItem::Form) { - nldebug("setting sth other than Atom"); + std::string newName = value.toString().toStdString(); + _Name = newName; + + // Create an action to update the form. } - //formElm->setValueByName(); return true; } -// CFormItem *CFormItem::add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot) -// { - // Add at the end -// uint index = _Children.size(); -// _Children.push_back (new CGeorgesEditDocSub); + bool CFormItem::isEditable(int column) + { + // Ensure only valid types can be edited. + if(_Type == Null) + return false; -// _Children[index]->_Type = type; -// _Children[index]->_Name = name; -// _Children[index]->_Parent = this; -// _Children[index]->_StructId = structId; -// _Children[index]->_FormName = formName; -// _Children[index]->_Slot = slot; -// return _Children[index]; -// CFormItem *newNode = new CFormItem(); -// appendChild(newNode); -// return NULL; -// } + // Make sure only the first column (name) can be editted. + if (column != 0) + return false; - CFormItem *CFormItem::add(NLGEORGES::UFormElm* root, std::string elmName) + CFormItem *parent = this->parent(); + + // If it wasn't a root node then lets check the node type. + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *parentNode; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form = static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (parent->formName ().c_str (), &parentDfn, indexDfn, + &nodeDfn, &nodeType, &parentNode, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(array && parentNode) + return true; + + return false; + + } + + QIcon CFormItem::getItemImage(CFormItem *rootItem) + { + if(_Type == CFormItem::Null) + { + return QIcon(":/images/root.ico"); + } + else if(_Type == CFormItem::Form) + { + // If the parent is the root item then this is the content. + if(parentItem == rootItem) + return QIcon(":/images/root.ico"); + + // If it wasn't a root node then lets check the node type. + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form = static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(array) + { + return QIcon(":/images/array.ico"); + } + else + { + if(type == NLGEORGES::UFormDfn::EntryType) + { + if(parentDfn) + { + // Not sure what the hell to do with this. Gets filename from parent dfn? + } + return QIcon(":/images/zfee51.ico"); + } + else if(type == NLGEORGES::UFormDfn::EntryDfn) + { + if(parentDfn) + { + // Not sure what the hell to do with this. Gets filename from parent dfn? + } + return QIcon(":/images/struct.ico"); + } + else if(type == NLGEORGES::UFormDfn::EntryVirtualDfn) + { + if(node) + { + // Not sure what the hell to do with this. Gets filename from parent dfn? + std::string dfnName; + NLMISC::safe_cast(node)->getDfnName(dfnName); + // return dfnName.c_str() ? + } + return QIcon(":/images/vstruct.ico"); + } + } + //return QIcon(":/images/struct.ico"); + } + return QIcon(); + } + + CFormItem *CFormItem::add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr) { - CFormItem *newItem = NULL; - UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - // Append a new item to the current parent's list of children. -// std::string elmName; -// if(root->getStructNodeName(num, elmName)) -// { - QList columnData; - //QVariant value; - std::string value; - //NLMISC::CRGBA value_color; - //uint value_uint; - //sint value_sint; - //double value_double; - QString elmtType = ""; - UFormElm *elmt = 0; - if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) - { - if (elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) - elmtType = "Struct"; - if (elmt->isAtom()) - { - elmtType = "Atom"; - uint numDefinitions = 0; - const UType *type = elmt->getType(); - if (type) - { - numDefinitions = type->getNumDefinition(); - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (type->getType()) - { - case UType::UnsignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_uint");break; - case UType::SignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_sint");break; - case UType::Double: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); - elmtType.append("_double");break; - case UType::String: - elmtType.append("_string");break; - case UType::Color: - elmtType.append("_color");break; - default: - elmtType.append("_unknownType"); - } - } - else - { - elmtType.append("_noType"); - } + CFormItem *newNode = new CFormItem(); + newNode->_Type = type; + newNode->_Name = name; + newNode->parentItem = this; + newNode->_StructId = structId; + newNode->_FormName = formName; + newNode->_Slot = slot; + newNode->m_form = formPtr; - if (numDefinitions) - { - std::string l, v; - QString tmpLabel, tmpValue; - for (uint i = 0; i < numDefinitions; i++) - { - type->getDefinition(i,l,v); - tmpLabel = l.c_str(); - tmpValue = v.c_str(); - if (type->getType() == UType::SignedInt) - { - if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { - value = l; - break; - } - } - if (type->getType() == UType::String) - { - if (QString(value.c_str()) == tmpValue) - { - value = l; - break; - } - } - } - } - } - if (elmt->isVirtualStruct()) - { - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - elmtType = "VirtualStruct"; - } - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - - newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); - this->appendChild(newItem); - - return newItem; - //if (parents.last()->childCount() > 0) { - // parents << parents.last()->child(parents.last()->childCount()-1); - //} - - // The building of the tree should be haoppening in the mode,. - //loadFormData(elmt, parent->child(parent->childCount()-1)); - } - else - { - // add Defaults - // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes - bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - newItem = new CFormItem(elmt, columnData, this, *whereV, *whereN); - this->appendChild(newItem); - return newItem; - } -// } -// else -// { -// nlinfo("getNodeByName returned false"); -// } - } + appendChild(newNode); + return newNode; } } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index c56422caf..e08a198bd 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -1,76 +1,84 @@ -// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework -// Copyright (C) 2011 Adrian Jaekel -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef FORMITEM_H -#define FORMITEM_H - -// NeL includes -#include - -// Qt includes -#include -#include - -namespace GeorgesQt -{ - - class CFormItem - - { - public: - CFormItem(NLGEORGES::UFormElm *elm, const QList &data, - CFormItem *parent = 0, - NLGEORGES::UFormElm::TWhereIsValue wV = NLGEORGES::UFormElm::ValueForm, - NLGEORGES::UFormElm::TWhereIsNode wN = NLGEORGES::UFormElm::NodeForm); - ~CFormItem(); - - void appendChild(CFormItem *child); - //CFormItem *add (/*TSub type,*/ const char *name, uint structId, const char *formName, uint slot); - CFormItem *add(NLGEORGES::UFormElm* root, std::string elmName); - - CFormItem *child(int row); - int childCount() const; - int columnCount() const; - QVariant data(int column) const; - int row() const; - CFormItem *parent(); - bool setData(int column, const QVariant &value); - NLGEORGES::UFormElm* getFormElm() {return formElm;} - NLGEORGES::UFormElm::TWhereIsValue valueFrom() - { - return whereV; - } - NLGEORGES::UFormElm::TWhereIsNode nodeFrom() - { - return whereN; - } - - void setValueFrom(NLGEORGES::UFormElm::TWhereIsValue wV) { whereV = wV; } - void setNodeFrom(NLGEORGES::UFormElm::TWhereIsNode wN) { whereN = wN; } - - - private: - //CFormItem() { whereV = NLGEORGES::UFormElm::ValueForm; whereN = NLGEORGES::UFormElm::NodeForm; } - QList childItems; - QList itemData; - CFormItem *parentItem; - NLGEORGES::UFormElm* formElm; - NLGEORGES::UFormElm::TWhereIsValue whereV; - NLGEORGES::UFormElm::TWhereIsNode whereN; - }; // CFormItem - -} -#endif // FORMITEM_H +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef FORMITEM_H +#define FORMITEM_H + +// NeL includes +#include +#include + +// Qt includes +#include +#include + +namespace GeorgesQt +{ + + class CFormItem + { + public: + // What is the sub object ? + enum TSub + { + Null, // Nothing in this node (root ?) + Header, // Header node + Type, // This node is a type + Dfn, // This node is a dfn + Form, // This node is a form + }; + + CFormItem(); + ~CFormItem(); + + void appendChild(CFormItem *child); + + CFormItem *add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr); + + CFormItem *child(int row); + int childCount() const; + int columnCount() const; + QVariant data(int column) const; + int row() const; + CFormItem *parent(); + bool setData(int column, const QVariant &value); + + TSub nodeType() { return _Type; } + std::string formName() { return _FormName; } + std::string name() { return _Name; } + uint structId() { return _StructId; } + + bool isEditable(int column); + + QIcon getItemImage(CFormItem *rootItem); + + private: + QList childItems; + QList itemData; + CFormItem *parentItem; + NLGEORGES::UFormElm* formElm; + NLGEORGES::UForm *m_form; + + uint _StructId; + std::string _Name; + std::string _FormName; + TSub _Type; + uint _Slot; + + }; // CFormItem + +} +#endif // FORMITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc index 3d514dbc0..8d71d1438 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc @@ -1,5 +1,12 @@ + images/array.ico + images/header.ico + images/hold.ico + images/root.ico + images/struct.ico + images/vstruct.ico + images/zfee51.ico images/ic_nel_georges_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index 92da6e8a0..aa289a4aa 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -72,23 +72,10 @@ namespace GeorgesQt m_ui.treeView->header()->setStretchLastSection(true); m_ui.treeViewTabWidget->setTabEnabled (2,false); - m_ui.checkBoxParent->setStyleSheet("background-color: rgba(0,255,0,30)"); - m_ui.checkBoxDefaults->setStyleSheet("background-color: rgba(255,0,0,30)"); m_form = 0; - FormDelegate *formdelegate = new FormDelegate(this); - m_ui.treeView->setItemDelegateForColumn(1, formdelegate); - - // Set up custom context menu. - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&))); - connect(m_ui.treeView, SIGNAL(doubleClicked (QModelIndex)), this, SLOT(doubleClicked (QModelIndex))); - connect(m_ui.checkBoxParent, SIGNAL(toggled(bool)), - this, SLOT(filterRows())); - connect(m_ui.checkBoxDefaults, SIGNAL(toggled(bool)), - this, SLOT(filterRows())); connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); } @@ -258,16 +245,9 @@ namespace GeorgesQt loadedForm = m_form->getFilename().c_str(); CGeorgesFormModel *model = new CGeorgesFormModel(m_form,deps,comments,parents,m_header->expanded()); - CGeorgesFormProxyModel *proxyModel = new CGeorgesFormProxyModel(); - proxyModel->setSourceModel(model); - m_ui.treeView->setModel(proxyModel); + m_ui.treeView->setModel(model); m_ui.treeView->expandAll(); - // this is a debug output row - m_ui.treeView->hideColumn(3); - filterRows(); - - // //_ui.treeView->setRowHidden(0,QModelIndex(),true); connect(model, SIGNAL(dataChanged(const QModelIndex, const QModelIndex)), this, SLOT(modifiedFile())); @@ -283,8 +263,7 @@ namespace GeorgesQt NLGEORGES::CForm *parentForm = dynamic_cast(uParentForm); NLGEORGES::CForm *mainForm = static_cast(m_form); - CGeorgesFormProxyModel * proxyModel = dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *model = dynamic_cast(proxyModel->sourceModel()); + CGeorgesFormModel *model = dynamic_cast(m_ui.treeView->model()); if(parentForm) { @@ -397,19 +376,15 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::doubleClicked ( const QModelIndex & index ) { - // TODO: this is messy :( perhaps this can be done better - CGeorgesFormProxyModel * proxyModel = - dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *model = - dynamic_cast(proxyModel->sourceModel()); - QModelIndex sourceIndex = proxyModel->mapToSource(index); + //CGeorgesFormModel *model = + // dynamic_cast((m_ui.treeView->model()); - CFormItem *item = model->getItem(sourceIndex); + //CFormItem *item = model->getItem(index); - if (item->parent() && item->parent()->data(0) == "parents") - { - Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toStdString(),false).c_str()); - } + //if (item->parent() && item->parent()->data(0) == "parents") + //{ + // Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toStdString(),false).c_str()); + //} //// col containing additional stuff like icons //if (index.column() == 2) @@ -475,129 +450,129 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::filterRows() { - CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); - if (m) { - m->setShowParents(m_ui.checkBoxParent->isChecked()); - m->setShowDefaults(m_ui.checkBoxDefaults->isChecked()); - } + //CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); + //CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); + //if (m) { + // m->setShowParents(m_ui.checkBoxParent->isChecked()); + // m->setShowDefaults(m_ui.checkBoxDefaults->isChecked()); + //} } void CGeorgesTreeViewDialog::showContextMenu(const QPoint &pos) { - QMenu contextMenu; - QMenu *structContext = NULL; - QPoint globalPos = this->mapToGlobal(pos); - - // Fisrt we're going to see if we've right clicked on a new item and select it. - const QModelIndex &index = this->m_ui.treeView->currentIndex(); + //QMenu contextMenu; + //QMenu *structContext = NULL; + //QPoint globalPos = this->mapToGlobal(pos); + // + //// Fisrt we're going to see if we've right clicked on a new item and select it. + //const QModelIndex &index = this->m_ui.treeView->currentIndex(); - if(!index.isValid()) - return; + //if(!index.isValid()) + // return; - CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); - CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); - QModelIndex sourceIndex = mp->mapToSource(index); + //CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); + //CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); + //QModelIndex sourceIndex = mp->mapToSource(index); - if (m) - { - - CFormItem *item = m->getItem(sourceIndex); + //if (m) + //{ + // + // CFormItem *item = m->getItem(sourceIndex); - // Right click on the "parents" item - if (item->data(0) == "parents") - contextMenu.addAction("Add parent..."); - // Right click on a parent item - else if(item->parent() && item->parent()->data(0) == "parents") - { - contextMenu.addAction("Add parent..."); - contextMenu.addAction("Remove parent"); - } - else if(item->getFormElm()->isArray()) - contextMenu.addAction("Add array entry..."); - else if(item->getFormElm()->isStruct()) - { - QMenu *structContext = new QMenu("Add struct element...", this); - contextMenu.addMenu(structContext); + // // Right click on the "parents" item + // if (item->data(0) == "parents") + // contextMenu.addAction("Add parent..."); + // // Right click on a parent item + // else if(item->parent() && item->parent()->data(0) == "parents") + // { + // contextMenu.addAction("Add parent..."); + // contextMenu.addAction("Remove parent"); + // } + // else if(item->getFormElm()->isArray()) + // contextMenu.addAction("Add array entry..."); + // else if(item->getFormElm()->isStruct()) + // { + // QMenu *structContext = new QMenu("Add struct element...", this); + // contextMenu.addMenu(structContext); - NLGEORGES::UFormDfn *defn = item->getFormElm()->getStructDfn(); - if(defn) - { - for(uint defnNum=0; defnNum < defn->getNumEntry(); defnNum++) - { - std::string entryName; - std::string dummy; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - bool result = defn->getEntryName(defnNum, entryName); - bool result2 = item->getFormElm()->getValueByName(dummy, entryName.c_str(), NLGEORGES::UFormElm::Eval, whereV); + // NLGEORGES::UFormDfn *defn = item->getFormElm()->getStructDfn(); + // if(defn) + // { + // for(uint defnNum=0; defnNum < defn->getNumEntry(); defnNum++) + // { + // std::string entryName; + // std::string dummy; + // UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; + // bool result = defn->getEntryName(defnNum, entryName); + // bool result2 = item->getFormElm()->getValueByName(dummy, entryName.c_str(), NLGEORGES::UFormElm::Eval, whereV); - - if(result2 && *whereV != UFormElm::ValueForm) - { - structContext->addAction(entryName.c_str()); - } - delete whereV; - } - } - } - else if(item->getFormElm()->isAtom() && item->valueFrom() == NLGEORGES::UFormElm::ValueForm) - contextMenu.addAction("Revert to parent/default..."); + // + // if(result2 && *whereV != UFormElm::ValueForm) + // { + // structContext->addAction(entryName.c_str()); + // } + // delete whereV; + // } + // } + // } + // else if(item->getFormElm()->isAtom() && item->valueFrom() == NLGEORGES::UFormElm::ValueForm) + // contextMenu.addAction("Revert to parent/default..."); - QAction *selectedItem = contextMenu.exec(globalPos); - if(selectedItem) - { - if(selectedItem->text() == "Add parent...") - { - // Get the file extension of the form so we can build a dialog pattern. - QString file = m_form->getFilename().c_str(); - file = file.remove(0,file.indexOf(".")+1); - QString filePattern = "Parent Sheets (*."+file+")"; - - nlinfo("parent defn name '%s'", file.toStdString().c_str()); - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select parent sheets..."), m_lastSheetDir, filePattern); - if(!fileNames.isEmpty()) - { - Q_FOREACH(QString fileToParent, fileNames) - { - // Get just the filename. Georges doesn't want the path. - QFileInfo pathInfo( fileToParent ); - QString tmpFileName( pathInfo.fileName() ); + // QAction *selectedItem = contextMenu.exec(globalPos); + // if(selectedItem) + // { + // if(selectedItem->text() == "Add parent...") + // { + // // Get the file extension of the form so we can build a dialog pattern. + // QString file = m_form->getFilename().c_str(); + // file = file.remove(0,file.indexOf(".")+1); + // QString filePattern = "Parent Sheets (*."+file+")"; + // + // nlinfo("parent defn name '%s'", file.toStdString().c_str()); + // QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select parent sheets..."), m_lastSheetDir, filePattern); + // if(!fileNames.isEmpty()) + // { + // Q_FOREACH(QString fileToParent, fileNames) + // { + // // Get just the filename. Georges doesn't want the path. + // QFileInfo pathInfo( fileToParent ); + // QString tmpFileName( pathInfo.fileName() ); - nlinfo("requesting to add parent form '%s'", tmpFileName.toStdString().c_str()); - - // Call to add the form and load it into the Georges form. - addParentForm(tmpFileName); + // nlinfo("requesting to add parent form '%s'", tmpFileName.toStdString().c_str()); + // + // // Call to add the form and load it into the Georges form. + // addParentForm(tmpFileName); - // Save the file lookup path for future dialog boxes. - m_lastSheetDir = pathInfo.absolutePath(); - } - } - m_ui.treeView->expandAll(); - } - else if(selectedItem->text() == "Remove parent") - { - NLGEORGES::CForm *form = static_cast(m_form); - QString parentFileName = item->data(0).toString(); + // // Save the file lookup path for future dialog boxes. + // m_lastSheetDir = pathInfo.absolutePath(); + // } + // } + // m_ui.treeView->expandAll(); + // } + // else if(selectedItem->text() == "Remove parent") + // { + // NLGEORGES::CForm *form = static_cast(m_form); + // QString parentFileName = item->data(0).toString(); - for(uint num = 0; num < form->getParentCount(); num++) - { - QString curParentName = form->getParent(num)->getFilename().c_str(); - if(parentFileName == curParentName) - { - form->removeParent(num); - m->removeParentForm(parentFileName); - break; - } - } + // for(uint num = 0; num < form->getParentCount(); num++) + // { + // QString curParentName = form->getParent(num)->getFilename().c_str(); + // if(parentFileName == curParentName) + // { + // form->removeParent(num); + // m->removeParentForm(parentFileName); + // break; + // } + // } - m_ui.treeView->expandAll(); - } + // m_ui.treeView->expandAll(); + // } - } // if selected context menu item is valid. - } // if 'm' model valid. + // } // if selected context menu item is valid. + //} // if 'm' model valid. - if(structContext) - delete structContext; + //if(structContext) + // delete structContext; } } /* namespace GeorgesQt */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui index 8d53bfdd6..0bf52a3ea 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 564 + 525 @@ -18,8 +18,8 @@ - 199 - 165 + 280 + 242 @@ -29,9 +29,21 @@ - + + + 0 + 0 + + + + + + 0 + 0 + + QTabWidget::West @@ -39,60 +51,40 @@ 0 - - Qt::NoFocus - Form - - - 0 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - true - - - - - - - Parent - - - - - + + + Qt::Horizontal - - - 40 - 20 - - - - - - - - Defaults - + + + + 0 + 0 + + + + + 0 + 0 + + + + true + + + + + + 0 + 0 + + + @@ -126,8 +118,14 @@ - - - + + + QtTreePropertyBrowser + QWidget +

qttreepropertybrowser.h
+ 1 + + + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index b8c9f56ff..9a329f396 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -53,7 +53,7 @@ namespace GeorgesQt { m_form = form; m_rootData << "Value" << "Data" << "Extra";// << "Type"; - m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_rootItem = new CFormItem(); m_dependencies = deps; m_comments = comment; m_parents = parents; @@ -81,144 +81,12 @@ namespace GeorgesQt { return getItem(p_index)->data(p_index.column()); } - case Qt::BackgroundRole: - { - QBrush defaultBrush = QBrush(QColor(255,0,0,30)); - QBrush parentBrush = QBrush(QColor(0,255,0,30)); - - // if elm not existing it must be some kind of default or type value - if(!getItem(p_index)->getFormElm()) - { - return defaultBrush; - } - - // else it might be some parent elm - switch (getItem(p_index)->nodeFrom()) - { - case NLGEORGES::UFormElm::NodeParentForm: - { - return parentBrush; - } - case NLGEORGES::UFormElm::NodeForm: - { - switch (getItem(p_index)->valueFrom()) - { - case NLGEORGES::UFormElm::ValueParentForm: - { - return parentBrush; - } - default: - { - // parent status test kindof ugly, testing only 2 steps deep - // only needed for colorization as treeview default hides childs - // when parent is hidden - CFormItem *parent = getItem(p_index)->parent(); - if (parent) - { - if (parent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - - CFormItem *parentParent = parent->parent(); - if (parentParent) - { - if (parentParent->nodeFrom() == NLGEORGES::UFormElm::NodeParentForm) - { - return parentBrush; - } - } // endif parentParent - } // endif parent - } // end default - } // end switch valueFrom - } // end case nodeForm - } // end switch nodeFrom - return QVariant(); - } - case Qt::DecorationRole: - { - if (p_index.column() == 2) - { - //p_index. - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - - QString value = item->data(1).toString(); - //QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - return QIcon(path); - } - } - return QVariant(); - break; - } - case Qt::ToolTipRole: - { - if (p_index.column() == 2) - { - QModelIndex in = index(p_index.row(),p_index.column()-1,p_index.parent()); - CFormItem *item = getItem(in); - QString value = item->data(1).toString(); - - /*if (value.contains(".shape")) - { - if (Modules::objViewInt()) - { - QIcon *icon = Modules::objViewInt()->saveOneImage(value.toStdString()); - if (icon) - { - if(icon->isNull()) - return QIcon(":/images/pqrticles.png"); - else - return QIcon(*icon); - } - else - { - return QIcon(); - } - } - }*/ - if(value.contains(".tga") || value.contains(".png")) - { - QString path = NLMISC::CPath::lookup(value.toStdString(),false).c_str(); - if(path.isEmpty()) - { - path = ":/images/pqrticles.png"; - } - - QString imageTooltip = QString("").arg(path); - - return imageTooltip; - } - } - return QVariant(); - break; - } + case Qt::DecorationRole: + { + // Based on the _Type return a QIcon from resources. + CFormItem *item = getItem(p_index); + return item->getItemImage(m_rootItem); + } default: return QVariant(); } @@ -239,14 +107,17 @@ namespace GeorgesQt /******************************************************************************/ - bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, - int role) + bool CGeorgesFormModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role != Qt::EditRole) return false; + + CFormItem *item = getItem(index); - CFormItem *item = getItem(index); + if(!item->isEditable(index.column())) + return false; + bool result = item->setData(index.column(), value); Q_EMIT dataChanged(index, index); @@ -264,8 +135,12 @@ namespace GeorgesQt Qt::ItemFlags returnValue = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if(index.column() == 1) - returnValue |= Qt::ItemIsEditable; + CFormItem *item = getItem(index); + + if(item->isEditable(index.column())) + { + returnValue |= Qt::ItemIsEditable; + } return returnValue; @@ -383,223 +258,7 @@ namespace GeorgesQt /******************************************************************************/ void CGeorgesFormModel::loadFormData(UFormElm *root, CFormItem *parent) { - - if (!root) - return; - - uint num = 0; - - - if (root->isStruct()) - { - //((CFormElm*)root)->getForm()->getComment(); - uint structSize = 0; - root->getStructSize(structSize); - while (num < structSize) - { - UFormElm::TWhereIsNode *whereN = new UFormElm::TWhereIsNode; - UFormElm::TWhereIsValue *whereV = new UFormElm::TWhereIsValue; - // Append a new item to the current parent's list of children. - std::string elmName; - if(root->getStructNodeName(num, elmName)) - { - QList columnData; - //QVariant value; - std::string value; - //NLMISC::CRGBA value_color; - //uint value_uint; - //sint value_sint; - //double value_double; - QString elmtType = ""; - UFormElm *elmt = 0; - if(root->getNodeByName(&elmt, elmName.c_str(), whereN, true)) - { - if (elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) - elmtType = "Struct"; - if (elmt->isAtom()) - { - elmtType = "Atom"; - uint numDefinitions = 0; - const UType *type = elmt->getType(); - if (type) - { - numDefinitions = type->getNumDefinition(); - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (type->getType()) - { - case UType::UnsignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_uint");break; - case UType::SignedInt: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble()).toStdString(); - elmtType.append("_sint");break; - case UType::Double: - value = QString("%1").arg(QString("%1").arg(value.c_str()).toDouble(),0,'f',1).toStdString(); - elmtType.append("_double");break; - case UType::String: - elmtType.append("_string");break; - case UType::Color: - elmtType.append("_color");break; - default: - elmtType.append("_unknownType"); - } - } - else - { - elmtType.append("_noType"); - } - - if (numDefinitions) - { - std::string l, v; - QString tmpLabel, tmpValue; - for (uint i = 0; i < numDefinitions; i++) - { - type->getDefinition(i,l,v); - tmpLabel = l.c_str(); - tmpValue = v.c_str(); - if (type->getType() == UType::SignedInt) - { - if (QString("%1").arg(value.c_str()).toDouble() == tmpValue.toDouble()) { - value = l; - break; - } - } - if (type->getType() == UType::String) - { - if (QString(value.c_str()) == tmpValue) - { - value = l; - break; - } - } - } - } - } - if (elmt->isVirtualStruct()) - { - root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - elmtType = "VirtualStruct"; - } - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - //if (parents.last()->childCount() > 0) { - // parents << parents.last()->child(parents.last()->childCount()-1); - //} - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - else - { - // add Defaults - // TODO: spams warnings for non ATOM values but i dont get type of non existing nodes - bool success = root->getValueByName(value, elmName.c_str(),UFormElm::Eval,whereV); - switch (*whereN) - { - case UFormElm::NodeForm: - elmtType.append("_fromForm"); break; - case UFormElm::NodeParentForm: - elmtType.append("_fromParentForm"); break; - case UFormElm::NodeDfn: - elmtType.append("_isDFN"); break; - case UFormElm::NodeType: - elmtType.append("_isType"); break; - default: - elmtType.append("_noNode"); - } - switch (*whereV) - { - case UFormElm::ValueForm: - elmtType.append("_formValue"); break; - case UFormElm::ValueParentForm: - elmtType.append("_parentValue"); break; - case UFormElm::ValueDefaultDfn: - elmtType.append("_dfnValue"); break; - case UFormElm::ValueDefaultType: - elmtType.append("_typeValue"); break; - default: - elmtType.append("_noValue"); - } - - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent, *whereV, *whereN)); - } - } - else - { - nlinfo("getNodeByName returned false"); - } - } - num++; - } - } - if (root->isArray()) - { - uint arraySize = 0; - root->getArraySize(arraySize); - while (num < arraySize) - { - std::string elmName; - if(root->getArrayNodeName(elmName, num)) - { - QList columnData; - std::string value; - QString elmtType = ""; - - UFormElm *elmt = 0; - if(root->getArrayNode(&elmt,0) && elmt) - { - if (elmt->isArray()) - elmtType = "Array"; - if (elmt->isStruct()) { - elmtType = "Struct"; - } - if (elmt->isAtom()) - { - elmt->getValue(value); - elmtType = "Atom"; - } - if (elmt->isVirtualStruct()) - elmtType = "VirtualStruct"; - - elmtType.append("_arrayValue"); - columnData << QString(elmName.c_str()) << QString(value.c_str()) << "";// << elmtType; - parent->appendChild(new CFormItem(elmt, columnData, parent)); - loadFormData(elmt, parent->child(parent->childCount()-1)); - } - } - num++; - } - } + return; } CFormItem *CGeorgesFormModel::addStruct (CFormItem *parent, @@ -614,8 +273,9 @@ namespace GeorgesQt NLGEORGES::CForm *formPtr = static_cast(m_form); // Add the new node -// CFormItem *newNode = parent->add(/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); - CFormItem *newNode = parent->add(_struct, name); + CFormItem *newNode = parent->add(CFormItem::Form, name, structId, formName, slot, m_form); + + nlinfo("Added form %s : %s", name, formName); // Can be NULL in virtual DFN if (parentDfn) @@ -750,8 +410,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, uint slot) { // Add the new node - //CFormItem *newNode = parent->add (/*CGeorgesEditDocSub::Form,*/ name, structId, formName, slot); - CFormItem *newNode = parent->add (array, name); + CFormItem *newNode = parent->add (CFormItem::Form, name, structId, formName, slot, m_form); // The array exist if (array) @@ -778,14 +437,13 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, if (rootDfn) { // Get struct ptr - NLGEORGES::CFormElmStruct *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; + NLGEORGES::CFormElmStruct *elmPtr = array->Elements[elm].Element ? static_cast(array->Elements[elm].Element) : NULL; addStruct (newNode, elmPtr, rootDfn, formArrayName, elm, formArrayElmName, slot); } else { - NLGEORGES::CFormElmArray *elmPtr = array->Elements[elm].Element ? NLMISC::safe_cast(array->Elements[elm].Element) : NULL; - newNode->add (elmPtr, formArrayElmName); - //newNode->add (/*CGeorgesEditDocSub::Form,*/ formArrayName, elm, formArrayElmName, slot); + NLGEORGES::CFormElmArray *elmPtr = array->Elements[elm].Element ? static_cast(array->Elements[elm].Element) : NULL; + newNode->add (CFormItem::Form, formArrayName, elm, formArrayElmName, slot, m_form); } } } @@ -800,7 +458,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, void CGeorgesFormModel::loadFormHeader() { - if (m_parents.size()) + /* if (m_parents.size()) { CFormItem *fi_pars = new CFormItem(m_rootElm, QList() << "parents" << "" << "", m_rootItem); m_rootItem->appendChild(fi_pars); @@ -809,7 +467,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, { fi_pars->appendChild(new CFormItem(m_rootElm, QList() << str << "" << "", fi_pars)); } - } + }*/ /*QStringList dfns = _dependencies["dfn"]; QStringList typs = _dependencies["typ"]; @@ -851,7 +509,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, { m_rootElm = &((NLGEORGES::CForm*)m_form)->Elements; NLGEORGES::CFormElmStruct *rootstruct = &((NLGEORGES::CForm*)m_form)->Elements; - loadFormHeader(); + //loadFormHeader(); addStruct(m_rootItem, rootstruct, rootstruct->FormDfn, "Content", 0xffffffff, "", 0); //loadFormData(m_rootElm, m_rootItem); } @@ -875,7 +533,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, beginResetModel(); m_parents.push_back(parentForm); delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_rootItem = new CFormItem(); setupModelData(); endResetModel(); } @@ -886,7 +544,7 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, m_parents.removeOne(parentForm); delete m_rootItem; - m_rootItem = new CFormItem(m_rootElm, m_rootData); + m_rootItem = new CFormItem(); setupModelData(); endResetModel(); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp index 8b13ca8ba..81179f61c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp @@ -23,6 +23,8 @@ #include "georgesform_proxy_model.h" #include "georgesform_model.h" +#if 0 + namespace GeorgesQt { @@ -78,4 +80,5 @@ namespace GeorgesQt } } /* namespace GeorgesQt */ +#endif // 0 /* end of file */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h index cfe7fcca6..f4c968f80 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h @@ -20,6 +20,7 @@ // Qt includes #include +#if 0 namespace GeorgesQt { @@ -41,5 +42,5 @@ namespace GeorgesQt };/* class CGeorgesFormProxyModel */ } /* namespace GeorgesQt */ - +#endif // 0 #endif // GEORGESFORM_PROXY_MODEL_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico new file mode 100644 index 0000000000000000000000000000000000000000..923bec0bd09d868ebfdca30d953af70b87b2b084 GIT binary patch literal 1406 zcmd6mp=(@05XQfwDI6stF{dKhs78-ESKw5?6sr2(o87nH+nw+CX5W(roI5+JM68E~W@v_HUCZ?pM|X5b zcXUVZ%Nlw^ZwwlGL#I=q2YR3fLZBz(WSmjXMr-&RiHt?2RN2!Q3E!?a=0U}|_b9yXFRyc^!N9p#OVf5X4w-?ymY->6N4p~29oL*F*4Qg4q!PusVV z8U%g;Tfhq9NWMMMN z$>EG0j;!2$j_Z{^>GbqelgUJ9XJUsMx_2RDwvmTF)a~~hl{}<06o{r*q8a`~`>vfnu`}g<* Dvj*rN literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico new file mode 100644 index 0000000000000000000000000000000000000000..5ebb3632a07b0c55caa0d98e80995f28fed84db5 GIT binary patch literal 318 zcmZvXAr8YZ3`KvnsTrz@h6i`7qH3rL3tZ67m7^3DMulbBb6Qmcv-AJ6>^M@ShV1)Z z7SBey8UdQuTipC5~d;fm14_1Z`02Q7Kj-(pqL`xIjdy((fz>10+K5Q_gvD zZ{NY}f^UrjbK?vrxHzwF8OID;I1TLA3-C66UPFD(Y~#Nx{M9+6h=&q1&4*U@wu|%y D2y;=Y literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico new file mode 100644 index 0000000000000000000000000000000000000000..4b7f115f14d79bc4e7230fe0c3bcb20ef74c1230 GIT binary patch literal 318 zcmbu4p$>vE41~XBBuJ*vNc;?rS3zNa6wLigely1_^{p@@<2sNS!nJqTwQ06NP^6S_ z>;r7wMeppyz)A`>^qW*rQtR8KDls#;5Bf-Y_exZF%jJWZ2Z*H!3vr$_mS4}pALsc5 e8|~l9qpTOmhx;XGzqK`qMLk=8{*}J>Ji-eO5lbil literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico new file mode 100644 index 0000000000000000000000000000000000000000..3fa430766f5ef9080292ee358fc478f056ff4f5f GIT binary patch literal 318 zcmb7dGVc?i*Tas;^FM*`YIpgt6aCa4a z^AHkeF|@(|sDO%6Ld0r?LTgQijl#@3LFp@}-_UZc-ObA6+PQ=-%wt}{?_d8Kehr_= Wbc5Y?Wghd};{_kx-}Nt)({XHRBT$t9 literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico new file mode 100644 index 0000000000000000000000000000000000000000..a184d8a37697585d06f3ed0083f5484f969decd1 GIT binary patch literal 318 zcmbV`F%rTs3RQ=mD#m(4qaKsyoTSu{w4ex ZKC|ftyY9*|=FQ^?AKl;eFO<`9ya8ugQ@sEH literal 0 HcmV?d00001 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico new file mode 100644 index 0000000000000000000000000000000000000000..ad6bbb7564f9209ac1902598373a757275d144b4 GIT binary patch literal 2238 zcmZ`*3s}?j8h$5(!5GGH?0{o9hYCY(ZeSbAMMY4vU~*9jMNbSx%PVMs!6X5XAeTYJ zxM&?IAW+L;8W>GGqKU_V6wPjG7Uy*6B&VIuuhHS(Z;(8o^zC`~UEcTmewRJ}|1*F^ zKN1N>tkD(_(#VTKLJ>~E0xeS0vPazL7i-krG7aF?Kp(o8E?oJ(hk89)?{=f`UMKWj z4D`bcPTX!qbzd6}_co*US`8|$6r#5&A`KckGqvj~(!M=|l$-JFrd;xc*N}AWAQC$B5Ph)> zQ6H5cwdyL;oARNlszOpnCDf-1k#yn!)>P+1Ue$#s&*fwH`JH&KI|r$Bzp2KxNbKH+ zwHNmw{>m<_>fB1#lVizcPi#8787c2>LB^RF>^Zp<&$lOI+uQMUwg$0{Td=Y{8_Qd_ zV@bh}YnKIezTL<=DwI&r^}}idu&~At3o2v?e$@kkWwQ|aN+3cG`XHpl1FF24m|r*t zf%!AxQ|^tq#Zm-Ui?OhD29)JO1nNWxst_Qc#sLbQ1LQgmLW)FC6p5iIp?sbjX{ZK`0Tyai#zc zbHw1z=FomAL}C&6Vj+Y=S2*$caBks|Ct)=?^01X7kt()6i#x=(X9EX}ZQt2j2GSS^pq6+BzIn|xRHirs6kJM8Nu!={4Trf{o_gXzyF88$TxWaO6^EmE#*vvoy*>ho6WP`BiH7pJfGeDy@jVnC4`W#lb;+3Dma z*Oc+hu7j3?J!U`O?;@(6Ufm}{(!`kZ6AO=ICe@RsZzf%QL`XhY zxqW)P=Z^$LtWp_zLQnM4yLx2sXxeY!e9j3y6~h)x%9EQ0+t40^LC`)qt;xIoZqG@B zVbbZOU*jy)-0bfaU!M{)d4J3@XJPwwBAhZs*#G$c2wTvvSxlEE0yg_`0TIwm_usTM zl9Bk42@}pdA$deNF=ZZDF^rME3be?f;1K$E;SPN_7%8-)U{P;H!7`3=tY2wv(NfG{ tj4Xz^LuZgD80Oa;3hD`mVII(#gyO;Pyw>7rZj|IO2X^EzB^EKm{08(sjoSbK literal 0 HcmV?d00001 From 02a9f4d9206814a23594411707614063708fa47d Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 27 Sep 2012 08:22:50 -0500 Subject: [PATCH 012/220] Added: #1306 Added undo/redo action for renaming array entry names --- .../src/plugins/georges_editor/actions.cpp | 82 ++++++++++++++++++- .../src/plugins/georges_editor/actions.h | 23 ++++++ .../src/plugins/georges_editor/formitem.cpp | 58 +++++++------ .../src/plugins/georges_editor/formitem.h | 5 ++ .../georges_editor/georges_editor_form.cpp | 7 +- .../georges_editor/georges_editor_form.h | 3 +- 6 files changed, 148 insertions(+), 30 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index dba45fb96..2a7780eb4 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -14,4 +14,84 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -#include "actions.h" \ No newline at end of file +// Project includes +#include "actions.h" +#include "formitem.h" + +// Qt includes + +// NeL includes +#include +#include +#include +#include +#include +#include +#include + +namespace GeorgesQt +{ + + CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent) + : QUndoCommand("Rename Form Array", parent), m_item(item), m_newValue(newValue), m_elementId(elementId) + { } + + void CUndoFormArrayRenameCommand::redo() + { + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool isArray; + bool vdfnArray; + NLGEORGES::CForm *form=static_cast(m_item->form()); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + if (node) + { + nlinfo("doing array rename"); + NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); + if(array->Elements[m_elementId].Name.empty()) + { + m_oldValue.append("#"); + m_oldValue.append(QString("%1").arg(m_elementId)); + } + else + { + m_oldValue = array->Elements[m_elementId].Name.c_str(); + } + + array->Elements[m_elementId].Name = m_newValue.toStdString(); + m_item->setName(m_newValue.toStdString()); + } + + } + + void CUndoFormArrayRenameCommand::undo() + { + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool isArray; + bool vdfnArray; + NLGEORGES::CForm *form=static_cast(m_item->form()); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + if (node) + { + NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); + //m_oldValue = array->Elements[m_elementId].Name.c_str(); + array->Elements[m_elementId].Name = m_oldValue.toStdString(); + m_item->setName(m_oldValue.toStdString()); + } + + } + +} \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h index c646adc72..c0e0d3b8e 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -17,4 +17,27 @@ #ifndef ACTIONS_H #define ACTIONS_H +#include + +namespace GeorgesQt +{ + class CFormItem; + + class CUndoFormArrayRenameCommand : public QUndoCommand + { + public: + CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent = 0); + ~CUndoFormArrayRenameCommand() {} + + void redo(); + void undo(); + + protected: + CFormItem *m_item; + QString m_newValue; + QString m_oldValue; + uint m_elementId; + }; +} + #endif // ACTIONS_H \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index 98bffa7e2..39545afde 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -14,7 +14,10 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +// Project includes #include "formitem.h" +#include "actions.h" +#include "georges_editor_form.h" // Qt includes #include @@ -81,34 +84,39 @@ namespace GeorgesQt bool CFormItem::setData(int column, const QVariant &value) { - if (column != 0) - return false; - - bool deleteInsert = false; - - - - // Get the parent node - const NLGEORGES::CFormDfn *parentDfn; - uint indexDfn; - const NLGEORGES::CFormDfn *nodeDfn; - const NLGEORGES::CType *nodeType; - NLGEORGES::CFormElm *parentNode; - NLGEORGES::UFormDfn::TEntryType type; - bool array; - bool parentVDfnArray; - NLGEORGES::CForm *form=static_cast(m_form); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); - - if (parentItem && parentItem->nodeType () == CFormItem::Form) + if(isEditable(column)) { - std::string newName = value.toString().toStdString(); - _Name = newName; + nlinfo("form item is editable."); + // Ensure that it is a child. + if (parentItem && parentItem->nodeType () == CFormItem::Form) + { + nlinfo("retrieving node information for data change."); + // Get the parent node + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *parentNode; + NLGEORGES::UFormDfn::TEntryType type; + bool isArray; + bool parentVDfnArray; + NLGEORGES::CForm *form=static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - // Create an action to update the form. + // Lets check the parent first, for arrays. + nlverify ( elm->getNodeByName (parentItem->formName().c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, isArray, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(isArray && parentNode) + { + nlinfo( "is array and a child, generate rename command"); + CUndoFormArrayRenameCommand *cmd = new CUndoFormArrayRenameCommand(this,value.toString(), _StructId); + GeorgesEditorForm::UndoStack->push(cmd); + return true; + } + } } - return true; + + return false; } bool CFormItem::isEditable(int column) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index e08a198bd..2acda42bb 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -58,9 +58,14 @@ namespace GeorgesQt TSub nodeType() { return _Type; } std::string formName() { return _FormName; } + std::string name() { return _Name; } + void setName(std::string name) { _Name = name; } + uint structId() { return _StructId; } + NLGEORGES::UForm *form() { return m_form; } + bool isEditable(int column); QIcon getItemImage(CFormItem *rootItem); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp index a36f411e0..f42d6bc6b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp @@ -35,6 +35,7 @@ namespace GeorgesQt { + QUndoStack *GeorgesEditorForm::UndoStack = NULL; GeorgesEditorForm::GeorgesEditorForm(QWidget *parent) : QMainWindow(parent), @@ -61,7 +62,7 @@ namespace GeorgesQt m_mainDock->setDockNestingEnabled(true); layout->addWidget(m_mainDock); - m_undoStack = new QUndoStack(this); + UndoStack = new QUndoStack(this); Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); m_openAction = menuManager->action(Core::Constants::OPEN); @@ -114,7 +115,7 @@ namespace GeorgesQt QUndoStack *GeorgesEditorForm::undoStack() const { - return m_undoStack; + return UndoStack; } void GeorgesEditorForm::open() @@ -211,7 +212,7 @@ namespace GeorgesQt } CGeorgesTreeViewDialog *dock = new CGeorgesTreeViewDialog(m_mainDock); - dock->setUndoStack(m_undoStack); + dock->setUndoStack(UndoStack); m_lastActiveDock = dock; m_dockedWidgets.append(dock); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h index 77fdd1ec8..c9cef964c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h @@ -38,6 +38,8 @@ public: QUndoStack *undoStack() const; + static QUndoStack *UndoStack; + public Q_SLOTS: void open(); void loadFile(const QString fileName); @@ -54,7 +56,6 @@ private: void readSettings(); void writeSettings(); - QUndoStack *m_undoStack; Ui::GeorgesEditorForm m_ui; CGeorgesDirTreeDialog *m_georgesDirTreeDialog; From e918468ef8c10aa404f5b208cbbd87bf0b5ff354 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 28 Sep 2012 07:33:51 -0500 Subject: [PATCH 013/220] Changed: #1306 Moved creation of undo command for form array renames to the model. --- .../src/plugins/georges_editor/actions.cpp | 100 +++++++++++------- .../src/plugins/georges_editor/actions.h | 10 +- .../src/plugins/georges_editor/formitem.cpp | 33 +----- .../georges_editor/georgesform_model.cpp | 7 +- .../georges_editor/georgesform_model.h | 5 +- 5 files changed, 80 insertions(+), 75 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index 2a7780eb4..a55bc389a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -17,9 +17,11 @@ // Project includes #include "actions.h" #include "formitem.h" +#include "georgesform_model.h" // Qt includes + // NeL includes #include #include @@ -32,12 +34,30 @@ namespace GeorgesQt { - CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent) - : QUndoCommand("Rename Form Array", parent), m_item(item), m_newValue(newValue), m_elementId(elementId) - { } + CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent) + : QUndoCommand(parent), m_model(model), m_elementId(elementId) + { + m_row = index.row(); + m_col = index.column(); + + m_newValue = value.toString(); + } void CUndoFormArrayRenameCommand::redo() { + update(true); + } + + void CUndoFormArrayRenameCommand::undo() + { + update(false); + } + + void CUndoFormArrayRenameCommand::update(bool redo) + { + QModelIndex index = m_model->index(m_row, m_col); + CFormItem *item = m_model->getItem(index); + // Get the parent node const NLGEORGES::CFormDfn *parentDfn; uint indexDfn; @@ -47,13 +67,33 @@ namespace GeorgesQt NLGEORGES::UFormDfn::TEntryType type; bool isArray; bool vdfnArray; - NLGEORGES::CForm *form=static_cast(m_item->form()); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + NLGEORGES::CForm *form=static_cast(item->form()); + if(!form) + { + nlinfo("failed to convert form."); + return; + } + + NLGEORGES::CFormElm *elm = static_cast(&form->Elements); + + if(!elm) + nlwarning("Failed to convert elm!"); + + nlverify ( elm->getNodeByName (item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); if (node) { - nlinfo("doing array rename"); - NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); + std::string tmpName; + node->getFormName(tmpName); + nlinfo("doing array rename on '%s'", tmpName.c_str()); + + NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); + if(!array) + nlwarning("the array is invalid."); + + // In the redo stage save the old value, just in case. + if(redo) + { + // If the name of the element is empty then give it a nice default. if(array->Elements[m_elementId].Name.empty()) { m_oldValue.append("#"); @@ -61,37 +101,21 @@ namespace GeorgesQt } else { - m_oldValue = array->Elements[m_elementId].Name.c_str(); + m_oldValue = QString::fromStdString(array->Elements[m_elementId].Name); } + } - array->Elements[m_elementId].Name = m_newValue.toStdString(); - m_item->setName(m_newValue.toStdString()); - } - + QString value; + if(redo) + value = m_newValue; + else + value = m_oldValue; + + + array->Elements[m_elementId].Name = value.toStdString(); + item->setName(value.toStdString()); + + m_model->emitDataChanged(index); + } } - - void CUndoFormArrayRenameCommand::undo() - { - // Get the parent node - const NLGEORGES::CFormDfn *parentDfn; - uint indexDfn; - const NLGEORGES::CFormDfn *nodeDfn; - const NLGEORGES::CType *nodeType; - NLGEORGES::CFormElm *node; - NLGEORGES::UFormDfn::TEntryType type; - bool isArray; - bool vdfnArray; - NLGEORGES::CForm *form=static_cast(m_item->form()); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); - if (node) - { - NLGEORGES::CFormElmArray* array = NLMISC::safe_cast (node->getParent ()); - //m_oldValue = array->Elements[m_elementId].Name.c_str(); - array->Elements[m_elementId].Name = m_oldValue.toStdString(); - m_item->setName(m_oldValue.toStdString()); - } - - } - } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h index c0e0d3b8e..43a19257d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -18,22 +18,28 @@ #define ACTIONS_H #include +#include namespace GeorgesQt { class CFormItem; + class CGeorgesFormModel; class CUndoFormArrayRenameCommand : public QUndoCommand { public: - CUndoFormArrayRenameCommand(CFormItem *item, QString newValue, uint elementId, QUndoCommand *parent = 0); + CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent = 0); ~CUndoFormArrayRenameCommand() {} void redo(); void undo(); + void update(bool redo); + protected: - CFormItem *m_item; + int m_row, m_col; + CGeorgesFormModel *m_model; + QString m_newValue; QString m_oldValue; uint m_elementId; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index 39545afde..f053719c2 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -84,38 +84,7 @@ namespace GeorgesQt bool CFormItem::setData(int column, const QVariant &value) { - if(isEditable(column)) - { - nlinfo("form item is editable."); - // Ensure that it is a child. - if (parentItem && parentItem->nodeType () == CFormItem::Form) - { - nlinfo("retrieving node information for data change."); - // Get the parent node - const NLGEORGES::CFormDfn *parentDfn; - uint indexDfn; - const NLGEORGES::CFormDfn *nodeDfn; - const NLGEORGES::CType *nodeType; - NLGEORGES::CFormElm *parentNode; - NLGEORGES::UFormDfn::TEntryType type; - bool isArray; - bool parentVDfnArray; - NLGEORGES::CForm *form=static_cast(m_form); - NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); - - // Lets check the parent first, for arrays. - nlverify ( elm->getNodeByName (parentItem->formName().c_str(), &parentDfn, indexDfn, &nodeDfn, &nodeType, &parentNode, type, isArray, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); - - if(isArray && parentNode) - { - nlinfo( "is array and a child, generate rename command"); - CUndoFormArrayRenameCommand *cmd = new CUndoFormArrayRenameCommand(this,value.toString(), _StructId); - GeorgesEditorForm::UndoStack->push(cmd); - return true; - } - } - } - + nlwarning("This should not be called anymore."); return false; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index 9a329f396..b9511231b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -42,6 +42,8 @@ // project includes #include "formitem.h" +#include "georges_editor_form.h" +#include "actions.h" using namespace NLGEORGES; @@ -118,12 +120,13 @@ namespace GeorgesQt if(!item->isEditable(index.column())) return false; - bool result = item->setData(index.column(), value); + //bool result = item->setData(index.column(), value); + GeorgesEditorForm::UndoStack->push(new CUndoFormArrayRenameCommand(this,index,value,item->structId())); Q_EMIT dataChanged(index, index); //setupModelData(); - return result; + return true; } /******************************************************************************/ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h index 493f672dd..6c6c2817d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h @@ -40,7 +40,6 @@ namespace GeorgesQt class CGeorgesFormModel : public QAbstractItemModel { - public: CGeorgesFormModel(NLGEORGES::UForm *form, QMap< QString, QStringList> deps, QString comment, QStringList parents, bool* expanded, QObject *parent = 0); @@ -70,6 +69,10 @@ namespace GeorgesQt CFormItem *addArray(CFormItem *parent, NLGEORGES::CFormElmArray *array, NLGEORGES::CFormDfn *rootDfn, const char *name, uint structId, const char *formName, uint slot); + void emitDataChanged(const QModelIndex &index) + { + Q_EMIT dataChanged(index, index); + } private: void setupModelData(); void loadFormData(NLGEORGES::UFormElm *rootElm, CFormItem *parent); From a419c51a81fa8aa2edc36b334c45e5338267dab6 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 28 Sep 2012 09:50:44 -0500 Subject: [PATCH 014/220] Changed: #1306 Fixed index bug with form array rename. --- .../src/plugins/georges_editor/actions.cpp | 40 +++++-------------- .../src/plugins/georges_editor/actions.h | 5 +-- .../georges_editor/georgesform_model.cpp | 15 ++++--- .../georges_editor/georgesform_model.h | 1 + 4 files changed, 24 insertions(+), 37 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index a55bc389a..9fe3b0fa6 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -34,12 +34,9 @@ namespace GeorgesQt { - CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent) - : QUndoCommand(parent), m_model(model), m_elementId(elementId) + CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, CFormItem *item, const QVariant &value, QUndoCommand *parent) + : QUndoCommand("Rename Form Array Member", parent), m_model(model), m_item(item) { - m_row = index.row(); - m_col = index.column(); - m_newValue = value.toString(); } @@ -54,10 +51,7 @@ namespace GeorgesQt } void CUndoFormArrayRenameCommand::update(bool redo) - { - QModelIndex index = m_model->index(m_row, m_col); - CFormItem *item = m_model->getItem(index); - + { // Get the parent node const NLGEORGES::CFormDfn *parentDfn; uint indexDfn; @@ -67,41 +61,29 @@ namespace GeorgesQt NLGEORGES::UFormDfn::TEntryType type; bool isArray; bool vdfnArray; - NLGEORGES::CForm *form=static_cast(item->form()); - if(!form) - { - nlinfo("failed to convert form."); - return; - } - + NLGEORGES::CForm *form=static_cast(m_item->form()); NLGEORGES::CFormElm *elm = static_cast(&form->Elements); - if(!elm) - nlwarning("Failed to convert elm!"); - - nlverify ( elm->getNodeByName (item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); + nlverify ( elm->getNodeByName (m_item->formName().c_str (), &parentDfn, indexDfn, &nodeDfn, &nodeType, &node, type, isArray, vdfnArray, true, NLGEORGES_FIRST_ROUND) ); if (node) { std::string tmpName; node->getFormName(tmpName); - nlinfo("doing array rename on '%s'", tmpName.c_str()); NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); - if(!array) - nlwarning("the array is invalid."); // In the redo stage save the old value, just in case. if(redo) { // If the name of the element is empty then give it a nice default. - if(array->Elements[m_elementId].Name.empty()) + if(array->Elements[m_item->structId()].Name.empty()) { m_oldValue.append("#"); - m_oldValue.append(QString("%1").arg(m_elementId)); + m_oldValue.append(QString("%1").arg(m_item->structId())); } else { - m_oldValue = QString::fromStdString(array->Elements[m_elementId].Name); + m_oldValue = QString::fromStdString(array->Elements[m_item->structId()].Name); } } @@ -112,10 +94,10 @@ namespace GeorgesQt value = m_oldValue; - array->Elements[m_elementId].Name = value.toStdString(); - item->setName(value.toStdString()); + array->Elements[m_item->structId()].Name = value.toStdString(); + m_item->setName(value.toStdString()); - m_model->emitDataChanged(index); + m_model->emitDataChanged(m_model->index(m_item->row(), 0, m_item)); } } } \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h index 43a19257d..0c57b0577 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h @@ -28,7 +28,7 @@ namespace GeorgesQt class CUndoFormArrayRenameCommand : public QUndoCommand { public: - CUndoFormArrayRenameCommand(CGeorgesFormModel *model, const QModelIndex &index, const QVariant &value, uint elementId, QUndoCommand *parent = 0); + CUndoFormArrayRenameCommand(CGeorgesFormModel *model, CFormItem *item, const QVariant &value, QUndoCommand *parent = 0); ~CUndoFormArrayRenameCommand() {} void redo(); @@ -37,12 +37,11 @@ namespace GeorgesQt void update(bool redo); protected: - int m_row, m_col; + CFormItem *m_item; CGeorgesFormModel *m_model; QString m_newValue; QString m_oldValue; - uint m_elementId; }; } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp index b9511231b..387bc8917 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp @@ -119,9 +119,8 @@ namespace GeorgesQt if(!item->isEditable(index.column())) return false; - - //bool result = item->setData(index.column(), value); - GeorgesEditorForm::UndoStack->push(new CUndoFormArrayRenameCommand(this,index,value,item->structId())); + + GeorgesEditorForm::UndoStack->push(new CUndoFormArrayRenameCommand(this,item,value)); Q_EMIT dataChanged(index, index); @@ -214,6 +213,14 @@ namespace GeorgesQt return QModelIndex(); } + QModelIndex CGeorgesFormModel::index(int row, int column, CFormItem *item) const + { + if(item == m_rootItem) + return QModelIndex(); + + return createIndex(row, 0, item); + } + /******************************************************************************/ QModelIndex CGeorgesFormModel::parent(const QModelIndex &index) const @@ -278,8 +285,6 @@ namespace GeorgesQt // Add the new node CFormItem *newNode = parent->add(CFormItem::Form, name, structId, formName, slot, m_form); - nlinfo("Added form %s : %s", name, formName); - // Can be NULL in virtual DFN if (parentDfn) { diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h index 6c6c2817d..07589b63c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h @@ -50,6 +50,7 @@ namespace GeorgesQt Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int row, int column, CFormItem *item) const; QModelIndex parent(const QModelIndex &index) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; From bc2ecb6023e6eccba190aa401f37b2f0e00724ec Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 18 Oct 2012 20:56:31 -0500 Subject: [PATCH 015/220] GEQt Plugin: Starting to add the context menu back. --- .../src/plugins/georges_editor/formitem.cpp | 31 +++++++++++++- .../src/plugins/georges_editor/formitem.h | 2 + .../georges_treeview_dialog.cpp | 42 ++++++++++--------- 3 files changed, 55 insertions(+), 20 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp index f053719c2..9281bad2e 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp @@ -98,6 +98,36 @@ namespace GeorgesQt if (column != 0) return false; + if(isArrayMember()) + return true; + + return false; + } + + bool CFormItem::isArray() + { + // If it wasn't a root node then lets check the node type. + const NLGEORGES::CFormDfn *parentDfn; + uint indexDfn; + const NLGEORGES::CFormDfn *nodeDfn; + const NLGEORGES::CType *nodeType; + NLGEORGES::CFormElm *node; + NLGEORGES::UFormDfn::TEntryType type; + bool array; + bool parentVDfnArray; + NLGEORGES::CForm *form = static_cast(m_form); + NLGEORGES::CFormElm *elm = static_cast(&form->getRootNode()); + nlverify ( elm->getNodeByName (_FormName.c_str(), &parentDfn, indexDfn, + &nodeDfn, &nodeType, &node, type, array, parentVDfnArray, true, NLGEORGES_FIRST_ROUND) ); + + if(array && node) + return true; + + return false; + } + + bool CFormItem::isArrayMember() + { CFormItem *parent = this->parent(); // If it wasn't a root node then lets check the node type. @@ -118,7 +148,6 @@ namespace GeorgesQt return true; return false; - } QIcon CFormItem::getItemImage(CFormItem *rootItem) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index 2acda42bb..258a339db 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -67,6 +67,8 @@ namespace GeorgesQt NLGEORGES::UForm *form() { return m_form; } bool isEditable(int column); + bool isArray(); + bool isArrayMember(); QIcon getItemImage(CFormItem *rootItem); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index aa289a4aa..c058e6a20 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -460,26 +460,23 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::showContextMenu(const QPoint &pos) { - //QMenu contextMenu; - //QMenu *structContext = NULL; - //QPoint globalPos = this->mapToGlobal(pos); - // - //// Fisrt we're going to see if we've right clicked on a new item and select it. - //const QModelIndex &index = this->m_ui.treeView->currentIndex(); + QMenu contextMenu; + QMenu *structContext = NULL; + QPoint globalPos = this->mapToGlobal(pos); - //if(!index.isValid()) - // return; + // Fisrt we're going to see if we've right clicked on a new item and select it. + const QModelIndex &index = this->m_ui.treeView->currentIndex(); - //CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); - //CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); - //QModelIndex sourceIndex = mp->mapToSource(index); + if(!index.isValid()) + return; - //if (m) - //{ - // - // CFormItem *item = m->getItem(sourceIndex); + CGeorgesFormModel *m = dynamic_cast(m_ui.treeView->model()); - // // Right click on the "parents" item + if(m) + { + CFormItem *item = m->getItem(index); + + // Right click on the "parents" item // if (item->data(0) == "parents") // contextMenu.addAction("Add parent..."); // // Right click on a parent item @@ -488,8 +485,15 @@ namespace GeorgesQt // contextMenu.addAction("Add parent..."); // contextMenu.addAction("Remove parent"); // } - // else if(item->getFormElm()->isArray()) - // contextMenu.addAction("Add array entry..."); + if(item->isArray()) + { + contextMenu.addAction("Append array entry..."); + } + else if(item->isArrayMember()) + { + contextMenu.addAction("Delete array entry..."); + contextMenu.addAction("Insert after array entry..."); + } // else if(item->getFormElm()->isStruct()) // { // QMenu *structContext = new QMenu("Add struct element...", this); @@ -569,7 +573,7 @@ namespace GeorgesQt // } // } // if selected context menu item is valid. - //} // if 'm' model valid. + } // if 'm' model valid. //if(structContext) // delete structContext; From 098c6b96ebfe0492f4287f6686dcd4d73d43a3f8 Mon Sep 17 00:00:00 2001 From: mattraykowski Date: Sun, 21 Oct 2012 13:48:02 -0700 Subject: [PATCH 016/220] Changed: Enabled custom context menu signal to open a menu at the mouse position. --- .../src/plugins/georges_editor/formitem.h | 182 +++++++++--------- .../georges_treeview_dialog.cpp | 6 +- 2 files changed, 96 insertions(+), 92 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h index 258a339db..cc2dafece 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h @@ -1,91 +1,91 @@ -// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework -// Copyright (C) 2011 Adrian Jaekel -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef FORMITEM_H -#define FORMITEM_H - -// NeL includes -#include -#include - -// Qt includes -#include -#include - -namespace GeorgesQt -{ - - class CFormItem - { - public: - // What is the sub object ? - enum TSub - { - Null, // Nothing in this node (root ?) - Header, // Header node - Type, // This node is a type - Dfn, // This node is a dfn - Form, // This node is a form - }; - - CFormItem(); - ~CFormItem(); - - void appendChild(CFormItem *child); - - CFormItem *add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr); - - CFormItem *child(int row); - int childCount() const; - int columnCount() const; - QVariant data(int column) const; - int row() const; - CFormItem *parent(); - bool setData(int column, const QVariant &value); - - TSub nodeType() { return _Type; } - std::string formName() { return _FormName; } - - std::string name() { return _Name; } - void setName(std::string name) { _Name = name; } - - uint structId() { return _StructId; } - - NLGEORGES::UForm *form() { return m_form; } - - bool isEditable(int column); - bool isArray(); - bool isArrayMember(); - - QIcon getItemImage(CFormItem *rootItem); - - private: - QList childItems; - QList itemData; - CFormItem *parentItem; - NLGEORGES::UFormElm* formElm; - NLGEORGES::UForm *m_form; - - uint _StructId; - std::string _Name; - std::string _FormName; - TSub _Type; - uint _Slot; - - }; // CFormItem - -} -#endif // FORMITEM_H +// Object Viewer Qt - Georges Editor Plugin - MMORPG Framework +// Copyright (C) 2011 Adrian Jaekel +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef FORMITEM_H +#define FORMITEM_H + +// NeL includes +#include +#include + +// Qt includes +#include +#include + +namespace GeorgesQt +{ + + class CFormItem + { + public: + // What is the sub object ? + enum TSub + { + Null, // Nothing in this node (root ?) + Header, // Header node + Type, // This node is a type + Dfn, // This node is a dfn + Form, // This node is a form + }; + + CFormItem(); + ~CFormItem(); + + void appendChild(CFormItem *child); + + CFormItem *add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr); + + CFormItem *child(int row); + int childCount() const; + int columnCount() const; + QVariant data(int column) const; + int row() const; + CFormItem *parent(); + bool setData(int column, const QVariant &value); + + TSub nodeType() { return _Type; } + std::string formName() { return _FormName; } + + std::string name() { return _Name; } + void setName(std::string name) { _Name = name; } + + uint structId() { return _StructId; } + + NLGEORGES::UForm *form() { return m_form; } + + bool isEditable(int column); + bool isArray(); + bool isArrayMember(); + + QIcon getItemImage(CFormItem *rootItem); + + private: + QList childItems; + QList itemData; + CFormItem *parentItem; + NLGEORGES::UFormElm* formElm; + NLGEORGES::UForm *m_form; + + uint _StructId; + std::string _Name; + std::string _FormName; + TSub _Type; + uint _Slot; + + }; // CFormItem + +} +#endif // FORMITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index c058e6a20..b2db0edb1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -74,6 +74,10 @@ namespace GeorgesQt m_form = 0; + m_ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(m_ui.treeView, SIGNAL(customContextMenuRequested(const QPoint&)), + this, SLOT(showContextMenu(const QPoint&))); connect(m_ui.treeView, SIGNAL(doubleClicked (QModelIndex)), this, SLOT(doubleClicked (QModelIndex))); connect(m_header, SIGNAL(headerClicked(int)), @@ -522,7 +526,7 @@ namespace GeorgesQt // else if(item->getFormElm()->isAtom() && item->valueFrom() == NLGEORGES::UFormElm::ValueForm) // contextMenu.addAction("Revert to parent/default..."); - // QAction *selectedItem = contextMenu.exec(globalPos); + QAction *selectedItem = contextMenu.exec(QCursor::pos()); // if(selectedItem) // { // if(selectedItem->text() == "Add parent...") From b78dfebff294822e4833efd22e3a3f4dab3aec10 Mon Sep 17 00:00:00 2001 From: mattraykowski Date: Sun, 21 Oct 2012 13:58:44 -0700 Subject: [PATCH 017/220] Changed: if-statements for context menu selection - no logic --- .../georges_treeview_dialog.cpp | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index b2db0edb1..690e5106b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -491,7 +491,7 @@ namespace GeorgesQt // } if(item->isArray()) { - contextMenu.addAction("Append array entry..."); + contextMenu.addAction("Append array entry..."); } else if(item->isArrayMember()) { @@ -527,8 +527,23 @@ namespace GeorgesQt // contextMenu.addAction("Revert to parent/default..."); QAction *selectedItem = contextMenu.exec(QCursor::pos()); - // if(selectedItem) - // { + if(selectedItem) + { + if(selectedItem->text() == "Append array entry...") + { + + + } // Append an array entry... + else if(selectedItem->text() == "Delete array entry...") + { + + } + else if(selectedItem->text() == "Insert after array entry...") + { + + } + + // if(selectedItem->text() == "Add parent...") // { // // Get the file extension of the form so we can build a dialog pattern. @@ -576,7 +591,7 @@ namespace GeorgesQt // m_ui.treeView->expandAll(); // } - // } // if selected context menu item is valid. + } // if selected context menu item is valid. } // if 'm' model valid. //if(structContext) From 324aa7f8519e8576ede4ad88a510f487fba376ff Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Apr 2014 00:49:17 +0200 Subject: [PATCH 018/220] Build fixes. --- .../src/plugins/georges_editor/actions.cpp | 6 +-- .../georges_treeview_dialog.cpp | 46 +++++++++---------- .../src/plugins/tile_editor/tile_item.cpp | 4 +- .../plugins/tile_editor/tile_item_delegate.h | 2 - 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp index 9fe3b0fa6..c96bca95c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp @@ -83,7 +83,7 @@ namespace GeorgesQt } else { - m_oldValue = QString::fromStdString(array->Elements[m_item->structId()].Name); + m_oldValue = QString(array->Elements[m_item->structId()].Name.c_str()); } } @@ -94,8 +94,8 @@ namespace GeorgesQt value = m_oldValue; - array->Elements[m_item->structId()].Name = value.toStdString(); - m_item->setName(value.toStdString()); + array->Elements[m_item->structId()].Name = value.toAscii().data(); + m_item->setName(value.toAscii().data()); m_model->emitDataChanged(m_model->index(m_item->row(), 0, m_item)); } diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp index fa417019b..f1819f52a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -108,30 +108,30 @@ namespace GeorgesQt NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByName(const QString formName) { - if(NLMISC::CPath::exists(formName.toStdString())) + if(NLMISC::CPath::exists(formName.toAscii().data())) { - //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toStdString())); - return (NLGEORGES::CForm *)m_georges->loadForm(formName.toStdString()); + //NLGEORGES::CForm *form = dynamic_cast(m_georges->loadForm(formName.toAscii().data())); + return (NLGEORGES::CForm *)m_georges->loadForm(formName.toAscii().data()); } //else //{ // CForm *form = 0; // // Load the DFN - // std::string extStr = NLMISC::CFile::getExtension( formName.toStdString() ); + // std::string extStr = NLMISC::CFile::getExtension( formName.toAscii().data() ); // QString dfnName = QString("%1.dfn").arg(extStr.c_str()); // UFormDfn *formdfn; - // if (NLMISC::CPath::exists(dfnName.toStdString())) + // if (NLMISC::CPath::exists(dfnName.toAscii().data())) // { - // formdfn = _georges->loadFormDfn (dfnName.toStdString()); + // formdfn = _georges->loadFormDfn (dfnName.toAscii().data()); // if (!formdfn) // { - // nlwarning("Failed to load dfn: %s", dfnName.toStdString().c_str()); + // nlwarning("Failed to load dfn: %s", dfnName.toAscii().data()); // return 0; // } // } // else // { - // nlwarning("Cannot find dfn: %s", dfnName.toStdString().c_str()); + // nlwarning("Cannot find dfn: %s", dfnName.toAscii().data()); // return 0; // } @@ -147,20 +147,20 @@ namespace GeorgesQt // } // return form; //} - nlinfo("File '%s' does not exist!", formName.toStdString().c_str()); + nlinfo("File '%s' does not exist!", formName.toAscii().data()); return 0; } NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByDfnName(const QString dfnName) { - if(NLMISC::CPath::exists(dfnName.toStdString())) + if(NLMISC::CPath::exists(dfnName.toAscii().data())) { // Create a new form object. NLGEORGES::CForm *form = new NLGEORGES::CForm(); m_form = form; // Retrieve a copy of the root definition. - NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toStdString())); + NLGEORGES::CFormDfn *formDfn = dynamic_cast(m_georges->loadFormDfn(dfnName.toAscii().data())); // Next we'll use the root node to build a new form. NLGEORGES::CFormElmStruct *fes = dynamic_cast(getRootNode(0)); @@ -175,7 +175,7 @@ namespace GeorgesQt return form; } - nlinfo("File '%s' does not exist!", dfnName.toStdString().c_str()); + nlinfo("File '%s' does not exist!", dfnName.toAscii().data()); return NULL; } @@ -243,7 +243,7 @@ namespace GeorgesQt nlinfo("typ's %d",deps["typ"].count()); nlinfo("dfn's %d",deps["dfn"].count()); - //nlwarning(strList.join(";").toStdString().c_str()); + //nlwarning(strList.join(";").toAscii().data()); if (root) { loadedForm = m_form->getFilename().c_str(); @@ -263,7 +263,7 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::addParentForm(QString parentFormNm) { // Try to load the form - NLGEORGES::UForm *uParentForm = m_georges->loadForm(parentFormNm.toStdString()); + NLGEORGES::UForm *uParentForm = m_georges->loadForm(parentFormNm.toAscii().data()); NLGEORGES::CForm *parentForm = dynamic_cast(uParentForm); NLGEORGES::CForm *mainForm = static_cast(m_form); @@ -277,11 +277,11 @@ namespace GeorgesQt if (parentForm->Elements.FormDfn == mainForm->Elements.FormDfn) { // This is the parent form selector - if(!mainForm->insertParent(mainForm->getParentCount(),parentFormNm.toStdString().c_str(), parentForm)) - nlwarning("Failed to add parent form: %s", parentFormNm.toStdString().c_str()); + if(!mainForm->insertParent(mainForm->getParentCount(),parentFormNm.toAscii().data(), parentForm)) + nlwarning("Failed to add parent form: %s", parentFormNm.toAscii().data()); else { - nlinfo("Successfullyadded parent form: %s", parentFormNm.toStdString().c_str()); + nlinfo("Successfullyadded parent form: %s", parentFormNm.toAscii().data()); model->addParentForm(parentFormNm); } } @@ -303,7 +303,7 @@ namespace GeorgesQt { NLMISC::COFile file; - std::string s = NLMISC::CPath::lookup(loadedForm.toStdString(), false); + std::string s = NLMISC::CPath::lookup(loadedForm.toAscii().data(), false); if(file.open (s)) { try @@ -387,7 +387,7 @@ namespace GeorgesQt //if (item->parent() && item->parent()->data(0) == "parents") //{ - // Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toStdString(),false).c_str()); + // Q_EMIT changeFile(CPath::lookup(item->data(0).toString().toAscii().data(),false).c_str()); //} //// col containing additional stuff like icons @@ -397,7 +397,7 @@ namespace GeorgesQt // CFormItem *item = m->getItem(in2); // QString value = item->data(1).toString(); - // QString path = CPath::lookup(value.toStdString(),false).c_str(); + // QString path = CPath::lookup(value.toAscii().data(),false).c_str(); // if(value.contains(".tga") || value.contains(".png")) // { @@ -425,7 +425,7 @@ namespace GeorgesQt // { // Modules::objViewInt()->resetScene(); // //Modules::config().configRemapExtensions(); - // Modules::objViewInt()->loadMesh(path.toStdString(),""); + // Modules::objViewInt()->loadMesh(path.toAscii().data(),""); // } // return; // } @@ -551,7 +551,7 @@ namespace GeorgesQt // file = file.remove(0,file.indexOf(".")+1); // QString filePattern = "Parent Sheets (*."+file+")"; // - // nlinfo("parent defn name '%s'", file.toStdString().c_str()); + // nlinfo("parent defn name '%s'", file.toAscii().data()); // QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select parent sheets..."), m_lastSheetDir, filePattern); // if(!fileNames.isEmpty()) // { @@ -561,7 +561,7 @@ namespace GeorgesQt // QFileInfo pathInfo( fileToParent ); // QString tmpFileName( pathInfo.fileName() ); - // nlinfo("requesting to add parent form '%s'", tmpFileName.toStdString().c_str()); + // nlinfo("requesting to add parent form '%s'", tmpFileName.toAscii().data()); // // // Call to add the form and load it into the Georges form. // addParentForm(tmpFileName); diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp index fcd14a61b..9d9418561 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp @@ -223,7 +223,7 @@ TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString { m_tileFilename[channel] = filename; m_parentItem = parent; - //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toStdString().c_str()); + //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); } TileItemNode::~TileItemNode() @@ -255,7 +255,7 @@ QVariant TileItemNode::data(int column, int role) const QPixmap pixmap;// = new QPixmap(); if(!pixmap.load(tileFilename)) - nlinfo("failed to load %s", tileFilename.toStdString().c_str()); + nlinfo("failed to load %s", tileFilename.toAscii().data()); if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) tileSize *= 2; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h index 1b7058b48..90c831fb8 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h @@ -20,8 +20,6 @@ #include #include -#include "ui_tile_widget.h" - #include class TileItemDelegate : public QStyledItemDelegate From c83ccc76bb96dfbdbe4d17c1f81c329f1168a69c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Apr 2014 02:10:14 +0200 Subject: [PATCH 019/220] Tile Editor crash fixes. --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 2 -- .../src/plugins/tile_editor/tile_editor_plugin.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp index 930ae9d8b..d1199ebc9 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -147,8 +147,6 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_ui; delete m_undoStack; delete m_rotationMenu; - delete m_zoomMenu; - delete m_tileDisplayMenu; delete m_tileEditorMenu; diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h index 2398be2c4..cb7be7fc1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h @@ -68,7 +68,7 @@ public: virtual ~TileEditorContext() { - delete m_tileEditorMainWindow; + m_tileEditorMainWindow = NULL; } virtual QString id() const From f32545dda861787c489b0eb08da5c4d1589514cf Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 6 May 2014 01:30:28 +0200 Subject: [PATCH 020/220] Moved ovqt to /code/studio --- code/CMakeLists.txt | 4 + code/CMakeModules/nel.cmake | 4 + code/nel/tools/3d/CMakeLists.txt | 1 - .../src/plugins/core/CMakeLists.txt | 73 --- .../src/plugins/core/context_manager.cpp | 167 ------ .../src/plugins/core/context_manager.h | 76 --- .../src/plugins/core/core.cpp | 77 --- .../object_viewer_qt/src/plugins/core/core.h | 54 -- .../src/plugins/core/core.qrc | 21 - .../src/plugins/core/core_constants.h | 121 ----- .../src/plugins/core/core_global.h | 30 -- .../src/plugins/core/core_plugin.cpp | 104 ---- .../src/plugins/core/core_plugin.h | 74 --- .../plugins/core/general_settings_page.cpp | 241 --------- .../src/plugins/core/general_settings_page.h | 74 --- .../src/plugins/core/general_settings_page.ui | 233 --------- .../src/plugins/core/icons/ic_nel_crash.png | Bin 6630 -> 0 bytes .../src/plugins/core/icons/ic_nel_new.png | Bin 21396 -> 0 bytes .../core/icons/ic_nel_path_settings.png | Bin 4557 -> 0 bytes .../src/plugins/core/icons/ic_nel_redo.png | Bin 4694 -> 0 bytes .../src/plugins/core/icons/ic_nel_save.png | Bin 43738 -> 0 bytes .../src/plugins/core/icons/ic_nel_save_as.png | Bin 52871 -> 0 bytes .../src/plugins/core/icons/ic_nel_undo.png | Bin 4714 -> 0 bytes .../src/plugins/core/icontext.h | 76 --- .../object_viewer_qt/src/plugins/core/icore.h | 70 --- .../src/plugins/core/icore_listener.h | 63 --- .../src/plugins/core/images/preferences.png | Bin 10286 -> 0 bytes .../src/plugins/core/ioptions_page.h | 75 --- .../src/plugins/core/main_window.cpp | 492 ------------------ .../src/plugins/core/main_window.h | 147 ------ .../src/plugins/core/menu_manager.cpp | 96 ---- .../src/plugins/core/menu_manager.h | 67 --- .../src/plugins/core/ovqt_plugin_core.xml | 7 - .../src/plugins/core/plugin_view_dialog.cpp | 108 ---- .../src/plugins/core/plugin_view_dialog.h | 58 --- .../src/plugins/core/plugin_view_dialog.ui | 135 ----- .../src/plugins/core/qtwin.cpp | 241 --------- .../object_viewer_qt/src/plugins/core/qtwin.h | 37 -- .../core/search_paths_settings_page.cpp | 219 -------- .../plugins/core/search_paths_settings_page.h | 74 --- .../core/search_paths_settings_page.ui | 198 ------- .../src/plugins/core/settings_dialog.cpp | 182 ------- .../src/plugins/core/settings_dialog.h | 75 --- .../src/plugins/core/settings_dialog.ui | 126 ----- .../images/ic_nel_generic_settings.png | Bin 5633 -> 0 bytes .../object_viewer/icons/ic_nel_down_item.png | Bin 3812 -> 0 bytes .../object_viewer/icons/ic_nel_pill.png | Bin 9291 -> 0 bytes .../object_viewer/icons/ic_nel_reset_all.png | Bin 5938 -> 0 bytes .../object_viewer/icons/ic_nel_up_item.png | Bin 3304 -> 0 bytes .../tile_editor/images/ic_nel_add_item.png | Bin 3270 -> 0 bytes .../tile_editor/images/ic_nel_delete_item.png | Bin 1496 -> 0 bytes .../tile_editor/images/ic_nel_open.png | Bin 4310 -> 0 bytes .../src/plugins/tile_editor/images/nel.png | Bin 15587 -> 0 bytes .../CMakeLists.txt | 0 .../data/andbasr.ttf | Bin .../doc/html/cdirection_widget.png | Bin .../doc/html/cedit_color_widget.png | Bin .../doc/html/cedit_range_float_widget.png | Bin .../doc/html/cedit_range_int_widget.png | Bin .../doc/html/gui_struct.png | Bin .../doc/html/object_viewer_qt_window.png | Bin .../doc/make_ovqt_dox.bat | 0 .../doc/make_ovqt_dox.sh | 0 .../object_viewer_qt => studio}/doc/ovqt.dox | 0 .../ovqt_config.h.cmake | 0 .../src/3rdparty/CMakeLists.txt | 0 .../3rdparty/qtpropertybrowser/CMakeLists.txt | 0 .../qtpropertybrowser/LGPL_EXCEPTION.txt | 0 .../3rdparty/qtpropertybrowser/LICENSE.GPL3 | 0 .../3rdparty/qtpropertybrowser/LICENSE.LGPL | 0 .../QtAbstractEditorFactoryBase | 0 .../QtAbstractPropertyBrowser | 0 .../QtAbstractPropertyManager | 0 .../qtpropertybrowser/QtBoolPropertyManager | 0 .../3rdparty/qtpropertybrowser/QtBrowserItem | 0 .../qtpropertybrowser/QtButtonPropertyBrowser | 0 .../qtpropertybrowser/QtCharEditorFactory | 0 .../qtpropertybrowser/QtCharPropertyManager | 0 .../qtpropertybrowser/QtCheckBoxFactory | 0 .../qtpropertybrowser/QtColorEditorFactory | 0 .../qtpropertybrowser/QtColorPropertyManager | 0 .../qtpropertybrowser/QtCursorEditorFactory | 0 .../qtpropertybrowser/QtCursorPropertyManager | 0 .../qtpropertybrowser/QtDateEditFactory | 0 .../qtpropertybrowser/QtDatePropertyManager | 0 .../qtpropertybrowser/QtDateTimeEditFactory | 0 .../QtDateTimePropertyManager | 0 .../qtpropertybrowser/QtDoublePropertyManager | 0 .../qtpropertybrowser/QtDoubleSpinBoxFactory | 0 .../qtpropertybrowser/QtEnumEditorFactory | 0 .../qtpropertybrowser/QtEnumPropertyManager | 0 .../qtpropertybrowser/QtFlagPropertyManager | 0 .../qtpropertybrowser/QtFontEditorFactory | 0 .../qtpropertybrowser/QtFontPropertyManager | 0 .../QtGroupBoxPropertyBrowser | 0 .../qtpropertybrowser/QtGroupPropertyManager | 0 .../qtpropertybrowser/QtIntPropertyManager | 0 .../QtKeySequenceEditorFactory | 0 .../QtKeySequencePropertyManager | 0 .../qtpropertybrowser/QtLineEditFactory | 0 .../qtpropertybrowser/QtLocalePropertyManager | 0 .../qtpropertybrowser/QtPointFPropertyManager | 0 .../qtpropertybrowser/QtPointPropertyManager | 0 .../src/3rdparty/qtpropertybrowser/QtProperty | 0 .../qtpropertybrowser/QtRectFPropertyManager | 0 .../qtpropertybrowser/QtRectPropertyManager | 0 .../qtpropertybrowser/QtScrollBarFactory | 0 .../qtpropertybrowser/QtSizeFPropertyManager | 0 .../QtSizePolicyPropertyManager | 0 .../qtpropertybrowser/QtSizePropertyManager | 0 .../qtpropertybrowser/QtSliderFactory | 0 .../qtpropertybrowser/QtSpinBoxFactory | 0 .../qtpropertybrowser/QtStringPropertyManager | 0 .../qtpropertybrowser/QtTimeEditFactory | 0 .../qtpropertybrowser/QtTimePropertyManager | 0 .../qtpropertybrowser/QtTreePropertyBrowser | 0 .../qtpropertybrowser/QtVariantEditorFactory | 0 .../qtpropertybrowser/QtVariantProperty | 0 .../QtVariantPropertyManager | 0 .../src/3rdparty/qtpropertybrowser/README.TXT | 0 .../qtpropertybrowser/images/cursor-arrow.png | Bin .../qtpropertybrowser/images/cursor-busy.png | Bin .../images/cursor-closedhand.png | Bin .../qtpropertybrowser/images/cursor-cross.png | Bin .../images/cursor-forbidden.png | Bin .../qtpropertybrowser/images/cursor-hand.png | Bin .../images/cursor-hsplit.png | Bin .../qtpropertybrowser/images/cursor-ibeam.png | Bin .../images/cursor-openhand.png | Bin .../images/cursor-sizeall.png | Bin .../qtpropertybrowser/images/cursor-sizeb.png | Bin .../qtpropertybrowser/images/cursor-sizef.png | Bin .../qtpropertybrowser/images/cursor-sizeh.png | Bin .../qtpropertybrowser/images/cursor-sizev.png | Bin .../images/cursor-uparrow.png | Bin .../images/cursor-vsplit.png | Bin .../qtpropertybrowser/images/cursor-wait.png | Bin .../images/cursor-whatsthis.png | Bin .../images/resetproperty.png | Bin .../qtbuttonpropertybrowser.cpp | 0 .../qtbuttonpropertybrowser.h | 0 .../qtpropertybrowser/qteditorfactory.cpp | 0 .../qtpropertybrowser/qteditorfactory.h | 0 .../qtgroupboxpropertybrowser.cpp | 0 .../qtgroupboxpropertybrowser.h | 0 .../qtpropertybrowser/qtpropertybrowser.cpp | 0 .../qtpropertybrowser/qtpropertybrowser.h | 0 .../qtpropertybrowser/qtpropertybrowser.pri | 0 .../qtpropertybrowser/qtpropertybrowser.qrc | 0 .../qtpropertybrowserutils.cpp | 0 .../qtpropertybrowserutils_p.h | 0 .../qtpropertybrowser/qtpropertymanager.cpp | 0 .../qtpropertybrowser/qtpropertymanager.h | 0 .../qttreepropertybrowser.cpp | 0 .../qtpropertybrowser/qttreepropertybrowser.h | 0 .../qtpropertybrowser/qtvariantproperty.cpp | 0 .../qtpropertybrowser/qtvariantproperty.h | 0 .../src/CMakeLists.txt | 0 .../src/description.h | 0 .../src/extension_system/iplugin.h | 0 .../src/extension_system/iplugin_manager.h | 0 .../src/extension_system/iplugin_spec.h | 0 .../src/extension_system/plugin_manager.cpp | 0 .../src/extension_system/plugin_manager.h | 0 .../src/extension_system/plugin_spec.cpp | 0 .../src/extension_system/plugin_spec.h | 0 .../src/ic_nel_pill.ico | Bin .../src/images/nel_ide_load.png | Bin .../object_viewer_qt => studio}/src/main.cpp | 0 .../src/object_viewer_qt.qrc | 0 .../src/object_viewer_qt.rc | 0 .../src/plugins/CMakeLists.txt | 0 .../src/plugins/bnp_manager/CMakeLists.txt | 0 .../bnp_manager/bnp_dirtree_dialog.cpp | 0 .../plugins/bnp_manager/bnp_dirtree_dialog.h | 0 .../plugins/bnp_manager/bnp_dirtree_form.ui | 0 .../src/plugins/bnp_manager/bnp_file.cpp | 0 .../src/plugins/bnp_manager/bnp_file.h | 0 .../bnp_manager/bnp_filelist_dialog.cpp | 0 .../plugins/bnp_manager/bnp_filelist_dialog.h | 0 .../bnp_manager/bnp_filelist_dialog.ui | 0 .../bnp_manager/bnp_filesystem_model.cpp | 0 .../bnp_manager/bnp_filesystem_model.h | 0 .../src/plugins/bnp_manager/bnp_manager.qrc | 0 .../bnp_manager/bnp_manager_constants.h | 0 .../bnp_manager/bnp_manager_plugin.cpp | 0 .../plugins/bnp_manager/bnp_manager_plugin.h | 0 .../bnp_manager/bnp_manager_window.cpp | 0 .../plugins/bnp_manager/bnp_manager_window.h | 0 .../plugins/bnp_manager/bnp_manager_window.ui | 0 .../plugins/bnp_manager/bnp_proxy_model.cpp | 0 .../src/plugins/bnp_manager/bnp_proxy_model.h | 0 .../bnp_manager/images/ic_nel_add_item.png | Bin .../bnp_manager/images/ic_nel_bnp_make.png | Bin .../bnp_manager/images/ic_nel_delete_item.png | Bin .../bnp_manager/images/ic_nel_export.png | Bin .../plugins/bnp_manager/images/ic_nel_new.png | Bin .../bnp_manager/images/ic_nel_reset_all.png | Bin .../bnp_manager/ovqt_plugin_bnp_manager.xml | 0 .../src/plugins/disp_sheet_id/CMakeLists.txt | 0 .../disp_sheet_id/disp_sheet_id_plugin.cpp | 0 .../disp_sheet_id/disp_sheet_id_plugin.h | 0 .../ovqt_plugin_disp_sheet_id.xml | 0 .../plugins/disp_sheet_id/sheet_id_view.cpp | 0 .../src/plugins/disp_sheet_id/sheet_id_view.h | 0 .../plugins/disp_sheet_id/sheet_id_view.ui | 0 .../src/plugins/example/CMakeLists.txt | 0 .../src/plugins/example/example_plugin.cpp | 0 .../src/plugins/example/example_plugin.h | 0 .../plugins/example/example_settings_page.cpp | 0 .../plugins/example/example_settings_page.h | 0 .../plugins/example/example_settings_page.ui | 0 .../plugins/example/ovqt_plugin_example.xml | 0 .../src/plugins/example/qnel_widget.cpp | 0 .../src/plugins/example/qnel_widget.h | 0 .../src/plugins/example/simple_viewer.cpp | 0 .../src/plugins/example/simple_viewer.h | 0 .../src/plugins/georges_editor/CMakeLists.txt | 0 .../src/plugins/georges_editor/actions.cpp | 0 .../src/plugins/georges_editor/actions.h | 0 .../georges_editor/expandable_headerview.cpp | 0 .../georges_editor/expandable_headerview.h | 0 .../plugins/georges_editor/formdelegate.cpp | 0 .../src/plugins/georges_editor/formdelegate.h | 0 .../src/plugins/georges_editor/formitem.cpp | 0 .../src/plugins/georges_editor/formitem.h | 0 .../src/plugins/georges_editor/georges.cpp | 0 .../src/plugins/georges_editor/georges.h | 0 .../georges_editor/georges_dirtree_dialog.cpp | 0 .../georges_editor/georges_dirtree_dialog.h | 0 .../georges_editor/georges_dirtree_form.ui | 0 .../plugins/georges_editor/georges_editor.qrc | 0 .../georges_editor/georges_editor_constants.h | 0 .../georges_editor/georges_editor_form.cpp | 0 .../georges_editor/georges_editor_form.h | 0 .../georges_editor/georges_editor_form.ui | 0 .../georges_editor/georges_editor_plugin.cpp | 0 .../georges_editor/georges_editor_plugin.h | 0 .../georges_filesystem_model.cpp | 0 .../georges_editor/georges_filesystem_model.h | 0 .../georges_treeview_dialog.cpp | 0 .../georges_editor/georges_treeview_dialog.h | 0 .../georges_editor/georges_treeview_form.ui | 0 .../georges_editor/georgesform_model.cpp | 0 .../georges_editor/georgesform_model.h | 0 .../georgesform_proxy_model.cpp | 0 .../georges_editor/georgesform_proxy_model.h | 0 .../plugins/georges_editor/images/array.ico | Bin .../plugins/georges_editor/images/header.ico | Bin .../plugins/georges_editor/images/hold.ico | Bin .../images/ic_nel_georges_editor.png | Bin .../plugins/georges_editor/images/root.ico | Bin .../plugins/georges_editor/images/struct.ico | Bin .../plugins/georges_editor/images/vstruct.ico | Bin .../plugins/georges_editor/images/zfee51.ico | Bin .../ovqt_plugin_georges_editor.xml | 0 .../src/plugins/georges_editor/stdpch.cpp | 0 .../src/plugins/georges_editor/stdpch.h | 0 .../src/plugins/gui_editor/CMakeLists.txt | 0 .../src/plugins/gui_editor/action_editor.cpp | 0 .../src/plugins/gui_editor/action_editor.h | 0 .../src/plugins/gui_editor/action_editor.ui | 0 .../plugins/gui_editor/add_widget_widget.cpp | 0 .../plugins/gui_editor/add_widget_widget.h | 0 .../plugins/gui_editor/add_widget_widget.ui | 0 .../gui_editor/editor_message_processor.cpp | 0 .../gui_editor/editor_message_processor.h | 0 .../gui_editor/editor_selection_watcher.cpp | 0 .../gui_editor/editor_selection_watcher.h | 0 .../plugins/gui_editor/gui_editor_constants.h | 0 .../plugins/gui_editor/gui_editor_context.cpp | 0 .../plugins/gui_editor/gui_editor_context.h | 0 .../gui_editor/gui_editor_core_listener.cpp | 0 .../gui_editor/gui_editor_core_listener.h | 0 .../plugins/gui_editor/gui_editor_global.h | 0 .../plugins/gui_editor/gui_editor_plugin.cpp | 0 .../plugins/gui_editor/gui_editor_plugin.h | 0 .../plugins/gui_editor/gui_editor_window.cpp | 0 .../plugins/gui_editor/gui_editor_window.h | 0 .../plugins/gui_editor/gui_editor_window.ui | 0 .../src/plugins/gui_editor/link_editor.cpp | 0 .../src/plugins/gui_editor/link_editor.h | 0 .../src/plugins/gui_editor/link_editor.ui | 0 .../src/plugins/gui_editor/link_list.cpp | 0 .../src/plugins/gui_editor/link_list.h | 0 .../src/plugins/gui_editor/link_list.ui | 0 .../src/plugins/gui_editor/nel3d_widget.cpp | 0 .../src/plugins/gui_editor/nel3d_widget.h | 0 .../src/plugins/gui_editor/nelgui_widget.cpp | 0 .../src/plugins/gui_editor/nelgui_widget.h | 0 .../gui_editor/new_property_widget.cpp | 0 .../plugins/gui_editor/new_property_widget.h | 0 .../plugins/gui_editor/new_property_widget.ui | 0 .../plugins/gui_editor/new_widget_widget.cpp | 0 .../plugins/gui_editor/new_widget_widget.h | 0 .../plugins/gui_editor/new_widget_widget.ui | 0 .../gui_editor/ovqt_plugin_gui_editor.xml | 0 .../src/plugins/gui_editor/proc_editor.cpp | 0 .../src/plugins/gui_editor/proc_editor.h | 0 .../src/plugins/gui_editor/proc_editor.ui | 0 .../src/plugins/gui_editor/proc_list.cpp | 0 .../src/plugins/gui_editor/proc_list.h | 0 .../src/plugins/gui_editor/proc_list.ui | 0 .../gui_editor/project_file_parser.cpp | 0 .../plugins/gui_editor/project_file_parser.h | 0 .../gui_editor/project_file_serializer.cpp | 0 .../gui_editor/project_file_serializer.h | 0 .../src/plugins/gui_editor/project_files.h | 0 .../gui_editor/project_files/login.xml | 0 .../src/plugins/gui_editor/project_window.cpp | 0 .../src/plugins/gui_editor/project_window.h | 0 .../src/plugins/gui_editor/project_window.ui | 0 .../gui_editor/property_browser_ctrl.cpp | 0 .../gui_editor/property_browser_ctrl.h | 0 .../plugins/gui_editor/widget_hierarchy.cpp | 0 .../src/plugins/gui_editor/widget_hierarchy.h | 0 .../plugins/gui_editor/widget_hierarchy.ui | 0 .../src/plugins/gui_editor/widget_info.h | 0 .../gui_editor/widget_info_serializer.cpp | 0 .../gui_editor/widget_info_serializer.h | 0 .../src/plugins/gui_editor/widget_info_tree.h | 0 .../gui_editor/widget_info_tree_node.h | 0 .../gui_editor/widget_info_tree_visitor.h | 0 .../plugins/gui_editor/widget_properties.cpp | 0 .../plugins/gui_editor/widget_properties.h | 0 .../plugins/gui_editor/widget_properties.ui | 0 .../gui_editor/widget_properties_parser.cpp | 0 .../gui_editor/widget_properties_parser.h | 0 .../plugins/gui_editor/widget_serializer.cpp | 0 .../plugins/gui_editor/widget_serializer.h | 0 .../plugins/gui_editor/widgets/CtrlBase.xml | 0 .../gui_editor/widgets/CtrlBaseButton.xml | 0 .../plugins/gui_editor/widgets/CtrlButton.xml | 0 .../gui_editor/widgets/CtrlColPick.xml | 0 .../plugins/gui_editor/widgets/CtrlScroll.xml | 0 .../gui_editor/widgets/CtrlTabButton.xml | 0 .../gui_editor/widgets/CtrlTextButton.xml | 0 .../widgets/DBGroupSelectNumber.xml | 0 .../plugins/gui_editor/widgets/DBViewBar.xml | 0 .../plugins/gui_editor/widgets/DBViewBar3.xml | 0 .../gui_editor/widgets/DBViewDigit.xml | 0 .../gui_editor/widgets/DBViewNumber.xml | 0 .../gui_editor/widgets/DBViewQuantity.xml | 0 .../plugins/gui_editor/widgets/GroupCell.xml | 0 .../gui_editor/widgets/GroupContainer.xml | 0 .../gui_editor/widgets/GroupEditBox.xml | 0 .../plugins/gui_editor/widgets/GroupFrame.xml | 0 .../plugins/gui_editor/widgets/GroupHTML.xml | 0 .../gui_editor/widgets/GroupHeader.xml | 0 .../plugins/gui_editor/widgets/GroupList.xml | 0 .../plugins/gui_editor/widgets/GroupMenu.xml | 0 .../plugins/gui_editor/widgets/GroupModal.xml | 0 .../gui_editor/widgets/GroupParagraph.xml | 0 .../gui_editor/widgets/GroupScrollText.xml | 0 .../plugins/gui_editor/widgets/GroupTab.xml | 0 .../plugins/gui_editor/widgets/GroupTable.xml | 0 .../plugins/gui_editor/widgets/GroupTree.xml | 0 .../gui_editor/widgets/InterfaceElement.xml | 0 .../gui_editor/widgets/InterfaceGroup.xml | 0 .../widgets/InterfaceGroupWheel.xml | 0 .../plugins/gui_editor/widgets/RootGroup.xml | 0 .../plugins/gui_editor/widgets/ViewBitmap.xml | 0 .../gui_editor/widgets/ViewBitmapCombo.xml | 0 .../plugins/gui_editor/widgets/ViewText.xml | 0 .../gui_editor/widgets/ViewTextFormated.xml | 0 .../plugins/gui_editor/widgets/ViewTextID.xml | 0 .../gui_editor/widgets/ViewTextIDFormated.xml | 0 .../plugins/landscape_editor/CMakeLists.txt | 0 .../plugins/landscape_editor/builder_zone.cpp | 0 .../plugins/landscape_editor/builder_zone.h | 0 .../landscape_editor/builder_zone_base.cpp | 0 .../landscape_editor/builder_zone_base.h | 0 .../landscape_editor/builder_zone_region.cpp | 0 .../landscape_editor/builder_zone_region.h | 0 .../landscape_editor/icons/ic_grid.png | Bin .../icons/ic_nel_landscape_item.png | Bin .../icons/ic_nel_landscape_settings.png | Bin .../icons/ic_nel_transition_land.png | Bin .../icons/ic_nel_world_editor.png | Bin .../landscape_editor/icons/ic_nel_zone.png | Bin .../landscape_editor/icons/ic_nel_zonel.png | Bin .../landscape_editor/icons/ic_nel_zones.png | Bin .../landscape_editor/icons/ic_snapshot.png | Bin .../landscape_editor/landscape_actions.cpp | 0 .../landscape_editor/landscape_actions.h | 0 .../landscape_editor/landscape_editor.qrc | 0 .../landscape_editor_constants.h | 0 .../landscape_editor_global.h | 0 .../landscape_editor_plugin.cpp | 0 .../landscape_editor_plugin.h | 0 .../landscape_editor_window.cpp | 0 .../landscape_editor_window.h | 0 .../landscape_editor_window.ui | 0 .../landscape_editor/landscape_scene.cpp | 0 .../landscape_editor/landscape_scene.h | 0 .../landscape_editor/landscape_scene_base.cpp | 0 .../landscape_editor/landscape_scene_base.h | 0 .../landscape_editor/landscape_view.cpp | 0 .../plugins/landscape_editor/landscape_view.h | 0 .../landscape_editor/list_zones_model.cpp | 0 .../landscape_editor/list_zones_model.h | 0 .../landscape_editor/list_zones_widget.cpp | 0 .../landscape_editor/list_zones_widget.h | 0 .../landscape_editor/list_zones_widget.ui | 0 .../ovqt_plugin_landscape_editor.xml | 0 .../landscape_editor/pixmap_database.cpp | 0 .../landscape_editor/pixmap_database.h | 0 .../project_settings_dialog.cpp | 0 .../project_settings_dialog.h | 0 .../project_settings_dialog.ui | 0 .../landscape_editor/shapshot_dialog.ui | 0 .../landscape_editor/snapshot_dialog.cpp | 0 .../landscape_editor/snapshot_dialog.h | 0 .../landscape_editor/zone_region_editor.cpp | 0 .../landscape_editor/zone_region_editor.h | 0 .../src/plugins/log/CMakeLists.txt | 0 .../src/plugins/log/log_form.ui | 0 .../src/plugins/log/log_plugin.cpp | 0 .../src/plugins/log/log_plugin.h | 0 .../src/plugins/log/log_settings_page.cpp | 0 .../src/plugins/log/log_settings_page.h | 0 .../src/plugins/log/log_settings_page.ui | 0 .../src/plugins/log/ovqt_plugin_log.xml | 0 .../src/plugins/log/qt_displayer.cpp | 0 .../src/plugins/log/qt_displayer.h | 0 .../plugins/mission_compiler/CMakeLists.txt | 0 .../mission_compiler/images/arrow-left-2.png | Bin .../images/arrow-left-double-2.png | Bin .../mission_compiler/images/arrow-right-2.png | Bin .../images/arrow-right-double-2.png | Bin .../images/document-export-4.png | Bin .../images}/ic_nel_add_item.png | Bin .../images}/ic_nel_delete_item.png | Bin .../images}/ic_nel_down_item.png | Bin .../images}/ic_nel_generic_settings.png | Bin .../images}/ic_nel_reset_all.png | Bin .../images}/ic_nel_up_item.png | Bin .../images/news-subscribe-2.png | Bin .../mission_compiler/images/run-build-2.png | Bin .../mission_compiler/mission_compiler.qrc | 0 .../mission_compiler_main_window.cpp | 0 .../mission_compiler_main_window.h | 0 .../mission_compiler_main_window.ui | 0 .../mission_compiler_plugin.cpp | 0 .../mission_compiler_plugin.h | 0 .../mission_compiler_plugin_constants.h | 0 .../mission_compiler_settings_page.cpp | 0 .../mission_compiler_settings_page.h | 0 .../mission_compiler_settings_page.ui | 0 .../ovqt_plugin_mission_compiler.xml | 0 .../mission_compiler/server_entry_dialog.cpp | 0 .../mission_compiler/server_entry_dialog.h | 0 .../mission_compiler/server_entry_dialog.ui | 0 .../mission_compiler/validation_file.cpp | 0 .../mission_compiler/validation_file.h | 0 .../src/plugins/object_viewer/CMakeLists.txt | 0 .../object_viewer/graphics_settings_page.cpp | 0 .../object_viewer/graphics_settings_page.h | 0 .../object_viewer/graphics_settings_page.ui | 0 .../object_viewer/graphics_viewport.cpp | 0 .../plugins/object_viewer/graphics_viewport.h | 0 .../object_viewer/icons}/ic_nel_add_item.png | Bin .../object_viewer/icons/ic_nel_anim.png | Bin .../object_viewer/icons/ic_nel_animset.png | Bin .../icons/ic_nel_append_item.png | Bin .../object_viewer/icons/ic_nel_bgcolor.png | Bin .../icons/ic_nel_camera_3dedit.png | Bin .../object_viewer/icons/ic_nel_camera_add.png | Bin .../object_viewer/icons/ic_nel_camera_del.png | Bin .../object_viewer/icons/ic_nel_camera_fps.png | Bin .../object_viewer/icons/ic_nel_daynight.png | Bin .../icons}/ic_nel_delete_item.png | Bin .../object_viewer/icons}/ic_nel_down_item.png | Bin .../object_viewer/icons/ic_nel_framedelay.png | Bin .../icons/ic_nel_insert_item.png | Bin .../object_viewer/icons/ic_nel_mixer.png | Bin .../object_viewer/icons/ic_nel_mrm_mesh.png | Bin .../object_viewer/icons/ic_nel_new.png | Bin .../object_viewer}/icons/ic_nel_open.png | Bin .../icons/ic_nel_particle_system.png | Bin .../icons/ic_nel_particle_system_close.png | Bin .../object_viewer/icons/ic_nel_particles.png | Bin .../object_viewer}/icons/ic_nel_pill.png | Bin .../object_viewer/icons}/ic_nel_reset_all.png | Bin .../icons/ic_nel_reset_camera.png | Bin .../object_viewer/icons/ic_nel_save.png | Bin .../object_viewer/icons/ic_nel_save_as.png | Bin .../object_viewer/icons/ic_nel_skelscale.png | Bin .../object_viewer/icons/ic_nel_sound.png | Bin .../object_viewer/icons}/ic_nel_up_item.png | Bin .../object_viewer/icons/ic_nel_veget.png | Bin .../object_viewer/icons/ic_nel_vegetset.png | Bin .../object_viewer/icons/ic_nel_water.png | Bin .../object_viewer/icons/ic_nel_wind.png | Bin .../icons/ic_nel_workspace_item.png | Bin .../ic_nel_collision_zone_item_24.png | Bin .../ic_nel_emitter_item_24.png | Bin .../ic_nel_force_item_24.png | Bin .../ic_nel_instance_item_24.png | Bin .../ic_nel_light_item_24.png | Bin .../ic_nel_located_item_24.png | Bin .../ic_nel_particle_item_24.png | Bin .../ic_nel_particle_system_24.png | Bin .../ic_nel_particle_system_close_24.png | Bin .../ic_nel_sound_item_24.png | Bin .../ic_nel_workspace_item_24.png | Bin .../plugins/object_viewer/images/dqynight.png | Bin .../object_viewer/images/ico_mrm_mesh.png | Bin .../plugins/object_viewer/images/mixer.png | Bin .../src/plugins/object_viewer}/images/nel.png | Bin .../plugins/object_viewer/images/pause.png | Bin .../src/plugins/object_viewer/images/play.png | Bin .../plugins/object_viewer/images/polymode.png | Bin .../object_viewer/images/pqrticles.png | Bin .../plugins/object_viewer/images/refresh.png | Bin .../plugins/object_viewer/images/rmfill.png | Bin .../plugins/object_viewer/images/rmline.png | Bin .../plugins/object_viewer/images/rmpoints.png | Bin .../object_viewer/images/seek-backward.png | Bin .../object_viewer/images/seek-forward.png | Bin .../object_viewer/images/skip-backward.png | Bin .../object_viewer/images/skip-forward.png | Bin .../plugins/object_viewer/images/sound.png | Bin .../src/plugins/object_viewer/images/stop.png | Bin .../plugins/object_viewer/images/water.png | Bin .../src/plugins/object_viewer/images/wind.png | Bin .../src/plugins/object_viewer/main_window.cpp | 0 .../src/plugins/object_viewer/main_window.h | 0 .../src/plugins/object_viewer/modules.cpp | 0 .../src/plugins/object_viewer/modules.h | 0 .../plugins/object_viewer/object_viewer.cpp | 0 .../src/plugins/object_viewer/object_viewer.h | 0 .../plugins/object_viewer/object_viewer.qrc | 0 .../object_viewer/object_viewer_constants.h | 0 .../object_viewer/object_viewer_plugin.cpp | 0 .../object_viewer/object_viewer_plugin.h | 0 .../ovqt_plugin_object_viewer.xml | 0 .../particle_system/attrib_form.ui | 0 .../particle_system/attrib_widget.cpp | 0 .../particle_system/attrib_widget.h | 0 .../particle_system/auto_lod_dialog.cpp | 0 .../particle_system/auto_lod_dialog.h | 0 .../particle_system/auto_lod_form.ui | 0 .../particle_system/basic_edit_form.ui | 0 .../particle_system/basic_edit_widget.cpp | 0 .../particle_system/basic_edit_widget.h | 0 .../particle_system/bin_op_dialog.cpp | 0 .../particle_system/bin_op_dialog.h | 0 .../particle_system/constraint_mesh_form.ui | 0 .../constraint_mesh_widget.cpp | 0 .../particle_system/constraint_mesh_widget.h | 0 .../particle_system/curve_dialog.cpp | 0 .../particle_system/curve_dialog.h | 0 .../particle_system/curve_form.ui | 0 .../particle_system/direction_form.ui | 0 .../particle_system/direction_widget.cpp | 0 .../particle_system/direction_widget.h | 0 .../object_viewer/particle_system/dup_ps.cpp | 0 .../object_viewer/particle_system/dup_ps.h | 0 .../particle_system/emitter_form.ui | 0 .../particle_system/emitter_page.cpp | 0 .../particle_system/emitter_page.h | 0 .../particle_system/follow_path_dialog.cpp | 0 .../particle_system/follow_path_dialog.h | 0 .../particle_system/located_bindable_form.ui | 0 .../particle_system/located_bindable_page.cpp | 0 .../particle_system/located_bindable_page.h | 0 .../particle_system/located_form.ui | 0 .../particle_system/located_page.cpp | 0 .../particle_system/located_page.h | 0 .../particle_system/mesh_form.ui | 0 .../particle_system/mesh_widget.cpp | 0 .../particle_system/mesh_widget.h | 0 .../particle_system/morph_mesh_dialog.cpp | 0 .../particle_system/morph_mesh_dialog.h | 0 .../particle_system/morph_mesh_form.ui | 0 .../particle_system/multi_tex_dialog.cpp | 0 .../particle_system/multi_tex_dialog.h | 0 .../particle_system/multi_tex_form.ui | 0 .../particle_control_dialog.cpp | 0 .../particle_system/particle_control_dialog.h | 0 .../particle_system/particle_control_form.ui | 0 .../particle_system/particle_editor.cpp | 0 .../particle_system/particle_editor.h | 0 .../particle_system/particle_force_form.ui | 0 .../particle_system/particle_force_page.cpp | 0 .../particle_system/particle_force_page.h | 0 .../particle_system/particle_light_form.ui | 0 .../particle_system/particle_light_page.cpp | 0 .../particle_system/particle_light_page.h | 0 .../particle_link_skeleton_dialog.cpp | 0 .../particle_link_skeleton_dialog.h | 0 .../particle_link_skeleton_form.ui | 0 .../particle_system/particle_node.cpp | 0 .../particle_system/particle_node.h | 0 .../particle_property_dialog.cpp | 0 .../particle_property_dialog.h | 0 .../particle_system/particle_sound_form.ui | 0 .../particle_system/particle_sound_page.cpp | 0 .../particle_system/particle_sound_page.h | 0 .../particle_system/particle_system_form.ui | 0 .../particle_system/particle_system_page.cpp | 0 .../particle_system/particle_system_page.h | 0 .../particle_texture_anim_form.ui | 0 .../particle_texture_anim_widget.cpp | 0 .../particle_texture_anim_widget.h | 0 .../particle_system/particle_texture_form.ui | 0 .../particle_texture_widget.cpp | 0 .../particle_system/particle_texture_widget.h | 0 .../particle_system/particle_tree_model.cpp | 0 .../particle_system/particle_tree_model.h | 0 .../particle_workspace_dialog.cpp | 0 .../particle_workspace_dialog.h | 0 .../particle_workspace_form.ui | 0 .../particle_workspace_page.cpp | 0 .../particle_system/particle_workspace_page.h | 0 .../particle_system/particle_zone_form.ui | 0 .../particle_system/particle_zone_page.cpp | 0 .../particle_system/particle_zone_page.h | 0 .../particle_system/ps_initial_pos.cpp | 0 .../particle_system/ps_initial_pos.h | 0 .../particle_system/ps_mover_form.ui | 0 .../particle_system/ps_mover_page.cpp | 0 .../particle_system/ps_mover_page.h | 0 .../particle_system/ps_wrapper.h | 0 .../particle_system/scheme_bank_dialog.cpp | 0 .../particle_system/scheme_bank_dialog.h | 0 .../particle_system/scheme_bank_form.ui | 0 .../particle_system/scheme_manager.cpp | 0 .../particle_system/scheme_manager.h | 0 .../particle_system/spinner_dialog.cpp | 0 .../particle_system/spinner_dialog.h | 0 .../particle_system/tail_form.ui | 0 .../particle_system/tail_particle_widget.cpp | 0 .../particle_system/tail_particle_widget.h | 0 .../particle_system/value_blender_dialog.cpp | 0 .../particle_system/value_blender_dialog.h | 0 .../value_from_emitter_dialog.cpp | 0 .../value_from_emitter_dialog.h | 0 .../particle_system/value_gradient_dialog.cpp | 0 .../particle_system/value_gradient_dialog.h | 0 .../particle_system/value_gradient_form.ui | 0 .../particle_system/workspace_form.ui | 0 .../object_viewer/scene/animation_dialog.cpp | 0 .../object_viewer/scene/animation_dialog.h | 0 .../object_viewer/scene/animation_form.ui | 0 .../scene/animation_set_dialog.cpp | 0 .../scene/animation_set_dialog.h | 0 .../object_viewer/scene/animation_set_form.ui | 0 .../object_viewer/scene/camera_control.cpp | 0 .../object_viewer/scene/camera_control.h | 0 .../object_viewer/scene/day_night_dialog.cpp | 0 .../object_viewer/scene/day_night_dialog.h | 0 .../object_viewer/scene/day_night_form.ui | 0 .../plugins/object_viewer/scene/entity.cpp | 0 .../src/plugins/object_viewer/scene/entity.h | 0 .../scene/global_wind_dialog.cpp | 0 .../object_viewer/scene/global_wind_dialog.h | 0 .../object_viewer/scene/global_wind_form.ui | 0 .../object_viewer/scene/setup_fog_dialog.cpp | 0 .../object_viewer/scene/setup_fog_dialog.h | 0 .../object_viewer/scene/setup_fog_form.ui | 0 .../scene/skeleton_scale_dialog.cpp | 0 .../scene/skeleton_scale_dialog.h | 0 .../scene/skeleton_scale_form.ui | 0 .../scene/skeleton_tree_model.cpp | 0 .../object_viewer/scene/skeleton_tree_model.h | 0 .../plugins/object_viewer/scene/slot_form.ui | 0 .../scene/slot_manager_dialog.cpp | 0 .../object_viewer/scene/slot_manager_dialog.h | 0 .../object_viewer/scene/sun_color_dialog.cpp | 0 .../object_viewer/scene/sun_color_dialog.h | 0 .../object_viewer/scene/sun_color_form.ui | 0 .../object_viewer/scene/tune_mrm_dialog.cpp | 0 .../object_viewer/scene/tune_mrm_dialog.h | 0 .../object_viewer/scene/tune_mrm_form.ui | 0 .../object_viewer/scene/tune_timer_dialog.cpp | 0 .../object_viewer/scene/tune_timer_dialog.h | 0 .../object_viewer/scene/tune_timer_form.ui | 0 .../object_viewer/scene/water_pool_dialog.cpp | 0 .../object_viewer/scene/water_pool_dialog.h | 0 .../object_viewer/scene/water_pool_form.ui | 0 .../object_viewer/sound_settings_page.cpp | 0 .../object_viewer/sound_settings_page.h | 0 .../object_viewer/sound_settings_page.ui | 0 .../plugins/object_viewer/sound_system.cpp | 0 .../src/plugins/object_viewer/sound_system.h | 0 .../src/plugins/object_viewer/stdpch.cpp | 0 .../src/plugins/object_viewer/stdpch.h | 0 .../vegetable/vegetable_appearance_page.cpp | 0 .../vegetable/vegetable_appearance_page.h | 0 .../vegetable/vegetable_apperance_form.ui | 0 .../vegetable/vegetable_density_form.ui | 0 .../vegetable/vegetable_density_page.cpp | 0 .../vegetable/vegetable_density_page.h | 0 .../vegetable/vegetable_dialog.cpp | 0 .../vegetable/vegetable_dialog.h | 0 .../vegetable/vegetable_dialog_form.ui | 0 .../vegetable/vegetable_editor.cpp | 0 .../vegetable/vegetable_editor.h | 0 .../vegetable/vegetable_landscape_form.ui | 0 .../vegetable/vegetable_landscape_page.cpp | 0 .../vegetable/vegetable_landscape_page.h | 0 .../vegetable/vegetable_node.cpp | 0 .../object_viewer/vegetable/vegetable_node.h | 0 .../vegetable/vegetable_noise_value_form.ui | 0 .../vegetable_noise_value_widget.cpp | 0 .../vegetable/vegetable_noise_value_widget.h | 0 .../vegetable/vegetable_rotate_form.ui | 0 .../vegetable/vegetable_rotate_page.cpp | 0 .../vegetable/vegetable_rotate_page.h | 0 .../vegetable/vegetable_scale_form.ui | 0 .../vegetable/vegetable_scale_page.cpp | 0 .../vegetable/vegetable_scale_page.h | 0 .../object_viewer/vegetable_settings_page.cpp | 0 .../object_viewer/vegetable_settings_page.h | 0 .../object_viewer/vegetable_settings_page.ui | 0 .../object_viewer/widgets/color_edit_form.ui | 0 .../widgets/color_edit_widget.cpp | 0 .../object_viewer/widgets/color_edit_widget.h | 0 .../widgets/edit_range_float_form.ui | 0 .../widgets/edit_range_uint_form.ui | 0 .../widgets/edit_range_widget.cpp | 0 .../object_viewer/widgets/edit_range_widget.h | 0 .../object_viewer/widgets/hoverpoints.cpp | 0 .../object_viewer/widgets/hoverpoints.h | 0 .../plugins/ovqt_sheet_builder/CMakeLists.txt | 0 .../ovqt_plugin_sheet_builder.xml | 0 .../ovqt_sheet_builder/ovqt_sheet_builder.cpp | 0 .../ovqt_sheet_builder/ovqt_sheet_builder.h | 0 .../ovqt_sheet_builder/ovqt_sheet_builder.pro | 0 .../plugins/ovqt_sheet_builder/sheetbuilder.h | 0 .../sheetbuilderconfgdialog.cpp | 0 .../sheetbuilderconfgdialog.h | 0 .../ovqt_sheet_builder/sheetbuilderdialog.cpp | 0 .../ovqt_sheet_builder/sheetbuilderdialog.h | 0 .../src/plugins/tile_editor/CMakeLists.txt | 0 .../plugins/tile_editor/images/add_tile.png | Bin .../tile_editor/images/delete_image.png | Bin .../tile_editor/images/delete_tile.png | Bin .../src/plugins/tile_editor/images/down.png | Bin .../tile_editor/images/empty_image.png | Bin .../tile_editor/images}/ic_nel_add_item.png | Bin .../images}/ic_nel_delete_item.png | Bin .../plugins/tile_editor/images/ic_nel_new.png | Bin .../tile_editor/images}/ic_nel_open.png | Bin .../tile_editor/images/ic_nel_save.png | Bin .../tile_editor/images/ic_nel_save_as.png | Bin .../src/plugins/tile_editor/images/left.png | Bin .../src/plugins/tile_editor}/images/nel.png | Bin .../tile_editor/images/replace_image.png | Bin .../src/plugins/tile_editor/images/reset.png | Bin .../src/plugins/tile_editor/images/right.png | Bin .../plugins/tile_editor/images/rotation0.png | Bin .../tile_editor/images/rotation180.png | Bin .../tile_editor/images/rotation270.png | Bin .../plugins/tile_editor/images/rotation90.png | Bin .../src/plugins/tile_editor/images/up.png | Bin .../tile_editor/ovqt_plugin_tile_editor.xml | 0 .../src/plugins/tile_editor/tile_editor.qrc | 0 .../tile_editor/tile_editor_main_window.cpp | 0 .../tile_editor/tile_editor_main_window.h | 0 .../tile_editor/tile_editor_main_window.ui | 0 .../tile_editor/tile_editor_plugin.cpp | 0 .../plugins/tile_editor/tile_editor_plugin.h | 0 .../src/plugins/tile_editor/tile_item.cpp | 0 .../src/plugins/tile_editor/tile_item.h | 0 .../tile_editor/tile_item_delegate.cpp | 0 .../plugins/tile_editor/tile_item_delegate.h | 0 .../src/plugins/tile_editor/tile_model.cpp | 0 .../src/plugins/tile_editor/tile_model.h | 0 .../translation_manager/CMakeLists.txt | 0 .../src/plugins/translation_manager/README | 0 .../translation_manager/editor_phrase.cpp | 0 .../translation_manager/editor_phrase.h | 0 .../translation_manager/editor_worksheet.cpp | 0 .../translation_manager/editor_worksheet.h | 0 .../translation_manager/extract_bot_names.cpp | 0 .../translation_manager/extract_bot_names.h | 0 .../extract_new_sheet_names.cpp | 0 .../extract_new_sheet_names.h | 0 .../translation_manager/ftp_selection.cpp | 0 .../translation_manager/ftp_selection.h | 0 .../translation_manager/ftp_selection.qrc | 0 .../translation_manager/ftp_selection.ui | 0 .../translation_manager/images/cdtoparent.png | Bin .../translation_manager/images/dir.png | Bin .../translation_manager/images/file.png | Bin .../ovqt_plugin_translation_manager.xml | 0 .../translation_manager/source_selection.cpp | 0 .../translation_manager/source_selection.h | 0 .../translation_manager/source_selection.ui | 0 .../translation_manager_constants.h | 0 .../translation_manager_editor.h | 0 .../translation_manager_main_window.cpp | 0 .../translation_manager_main_window.h | 0 .../translation_manager_main_window.ui | 0 .../translation_manager_plugin.cpp | 0 .../translation_manager_plugin.h | 0 .../translation_manager_settings_page.cpp | 0 .../translation_manager_settings_page.h | 0 .../translation_manager_settings_page.ui | 0 .../src/plugins/world_editor/CMakeLists.txt | 0 .../world_editor/icons/ic_nel_move.png | Bin .../world_editor/icons/ic_nel_rotate.png | Bin .../world_editor/icons/ic_nel_scale.png | Bin .../world_editor/icons/ic_nel_select.png | Bin .../world_editor/icons/ic_nel_turn.png | Bin .../icons/ic_nel_world_editor.png | Bin .../world_editor/ovqt_plugin_world_editor.xml | 0 .../plugins/world_editor/primitive_item.cpp | 0 .../src/plugins/world_editor/primitive_item.h | 0 .../plugins/world_editor/primitives_model.cpp | 0 .../plugins/world_editor/primitives_model.h | 0 .../plugins/world_editor/primitives_view.cpp | 0 .../plugins/world_editor/primitives_view.h | 0 .../world_editor/project_settings_dialog.cpp | 0 .../world_editor/project_settings_dialog.h | 0 .../world_editor/project_settings_dialog.ui | 0 .../world_editor/property_editor_widget.cpp | 0 .../world_editor/property_editor_widget.h | 0 .../world_editor/property_editor_widget.ui | 0 .../src/plugins/world_editor/world_editor.qrc | 0 .../world_editor/world_editor_actions.cpp | 0 .../world_editor/world_editor_actions.h | 0 .../world_editor/world_editor_constants.h | 0 .../world_editor/world_editor_global.h | 0 .../world_editor/world_editor_misc.cpp | 0 .../plugins/world_editor/world_editor_misc.h | 0 .../world_editor/world_editor_plugin.cpp | 0 .../world_editor/world_editor_plugin.h | 0 .../world_editor/world_editor_scene.cpp | 0 .../plugins/world_editor/world_editor_scene.h | 0 .../world_editor/world_editor_scene_item.cpp | 0 .../world_editor/world_editor_scene_item.h | 0 .../world_editor_settings_page.cpp | 0 .../world_editor/world_editor_settings_page.h | 0 .../world_editor_settings_page.ui | 0 .../world_editor/world_editor_window.cpp | 0 .../world_editor/world_editor_window.h | 0 .../world_editor/world_editor_window.ui | 0 .../src/plugins/zone_painter/CMakeLists.txt | 0 .../zone_painter/images/color-fill.png | Bin .../images/color-picker-black.png | Bin .../plugins/zone_painter/images/colorize.png | Bin .../zone_painter/images/draw-brush.png | Bin .../plugins/zone_painter/images/go-down-7.png | Bin .../plugins/zone_painter/images/go-jump-4.png | Bin .../plugins/zone_painter/images/lock-6.png | Bin .../zone_painter/images/lock-silver.png | Bin .../zone_painter/ovqt_plugin_zone_painter.xml | 0 .../zone_painter/painter_dock_widget.cpp | 0 .../zone_painter/painter_dock_widget.h | 0 .../zone_painter/painter_dock_widget.ui | 0 .../src/plugins/zone_painter/qnel_widget.cpp | 0 .../src/plugins/zone_painter/qnel_widget.h | 0 .../src/plugins/zone_painter/zone_painter.qrc | 0 .../zone_painter/zone_painter_main_window.cpp | 0 .../zone_painter/zone_painter_main_window.h | 0 .../zone_painter/zone_painter_main_window.ui | 0 .../zone_painter/zone_painter_model.cpp | 0 .../plugins/zone_painter/zone_painter_model.h | 0 .../zone_painter/zone_painter_plugin.cpp | 0 .../zone_painter/zone_painter_plugin.h | 0 .../zone_painter_settings_page.cpp | 0 .../zone_painter/zone_painter_settings_page.h | 0 .../zone_painter_settings_page.ui | 0 .../src/translations/object_viewer_qt_de.ts | 0 .../src/translations/object_viewer_qt_en.ts | 0 .../src/translations/object_viewer_qt_fr.ts | 0 .../src/translations/object_viewer_qt_ru.ts | 0 .../src/translations/translations.qrc | 0 872 files changed, 8 insertions(+), 3892 deletions(-) delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_crash.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_new.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_path_settings.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_redo.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save_as.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_undo.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icontext.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/preferences.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/ioptions_page.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_generic_settings.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_down_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_pill.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_reset_all.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_up_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_add_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png delete mode 100644 code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/nel.png rename code/{nel/tools/3d/object_viewer_qt => studio}/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/data/andbasr.ttf (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cdirection_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cedit_color_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cedit_range_float_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/cedit_range_int_widget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/gui_struct.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/html/object_viewer_qt_window.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/make_ovqt_dox.bat (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/make_ovqt_dox.sh (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/doc/ovqt.dox (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/ovqt_config.h.cmake (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/LICENSE.LGPL (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtBrowserItem (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCharEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCharPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtColorEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtColorPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDateEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDatePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtFontEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtFontPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtIntPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtLineEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtPointPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtProperty (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtRectPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtScrollBarFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSizePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSliderFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtStringPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtTimeEditFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtTimePropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtVariantProperty (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/README.TXT (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-busy.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-cross.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-hand.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-wait.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/images/resetproperty.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qteditorfactory.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtpropertymanager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/3rdparty/qtpropertybrowser/qtvariantproperty.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/description.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/iplugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/iplugin_manager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/iplugin_spec.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_manager.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_manager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_spec.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/extension_system/plugin_spec.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/ic_nel_pill.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/images/nel_ide_load.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/main.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/object_viewer_qt.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/object_viewer_qt.rc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_dirtree_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_dirtree_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_file.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_file.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filelist_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filelist_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filelist_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filesystem_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_filesystem_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_manager_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_proxy_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/bnp_proxy_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_bnp_make.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_export.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_new.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/images/ic_nel_reset_all.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/sheet_id_view.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/sheet_id_view.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/disp_sheet_id/sheet_id_view.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/example_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/ovqt_plugin_example.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/qnel_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/qnel_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/simple_viewer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/example/simple_viewer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/actions.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/actions.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/expandable_headerview.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/expandable_headerview.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formdelegate.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formdelegate.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formitem.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/formitem.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_dirtree_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_dirtree_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_dirtree_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_form.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_form.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_filesystem_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_filesystem_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_treeview_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_treeview_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georges_treeview_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_proxy_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/georgesform_proxy_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/array.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/header.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/hold.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/ic_nel_georges_editor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/root.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/struct.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/vstruct.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/images/zfee51.ico (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/stdpch.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/georges_editor/stdpch.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/action_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/action_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/action_editor.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/add_widget_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/add_widget_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/add_widget_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_message_processor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_message_processor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_selection_watcher.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/editor_selection_watcher.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_context.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_context.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_core_listener.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_core_listener.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_global.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/gui_editor_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_editor.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_list.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_list.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/link_list.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nel3d_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nel3d_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nelgui_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/nelgui_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_property_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_property_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_property_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_widget_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_widget_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/new_widget_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_editor.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_list.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_list.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/proc_list.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_parser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_parser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_serializer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_file_serializer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_files.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_files/login.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/project_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/property_browser_ctrl.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/property_browser_ctrl.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_hierarchy.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_hierarchy.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_hierarchy.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_serializer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_serializer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_tree.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_tree_node.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_info_tree_visitor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties_parser.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_properties_parser.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_serializer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widget_serializer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlBase.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlBaseButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlColPick.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlScroll.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlTabButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/CtrlTextButton.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewBar.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewBar3.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewDigit.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewNumber.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/DBViewQuantity.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupCell.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupContainer.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupEditBox.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupFrame.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupHTML.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupHeader.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupList.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupMenu.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupModal.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupParagraph.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupScrollText.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupTab.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupTable.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/GroupTree.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/InterfaceElement.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/InterfaceGroup.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/RootGroup.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewBitmap.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewText.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewTextFormated.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewTextID.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_base.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_base.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_region.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/builder_zone_region.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_grid.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_transition_land.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_world_editor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_zone.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_zonel.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_nel_zones.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/icons/ic_snapshot.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_actions.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_actions.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_global.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_editor_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene_base.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_scene_base.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_view.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/landscape_view.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/list_zones_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/pixmap_database.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/pixmap_database.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/project_settings_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/project_settings_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/project_settings_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/shapshot_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/snapshot_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/snapshot_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/zone_region_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/landscape_editor/zone_region_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/log_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/ovqt_plugin_log.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/qt_displayer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/log/qt_displayer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-left-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-left-double-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-right-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/arrow-right-double-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/document-export-4.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_down_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_generic_settings.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_reset_all.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core/icons => studio/src/plugins/mission_compiler/images}/ic_nel_up_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/news-subscribe-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/images/run-build-2.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_plugin_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/mission_compiler_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/server_entry_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/server_entry_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/server_entry_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/validation_file.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/mission_compiler/validation_file.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_viewport.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/graphics_viewport.h (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_anim.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_animset.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_append_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_bgcolor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_add.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_del.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_camera_fps.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_daynight.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_down_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_framedelay.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_insert_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_mixer.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_new.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core => studio/src/plugins/object_viewer}/icons/ic_nel_open.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_particle_system.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_particles.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core => studio/src/plugins/object_viewer}/icons/ic_nel_pill.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_reset_all.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_reset_camera.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_save.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_save_as.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_skelscale.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_sound.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images => studio/src/plugins/object_viewer/icons}/ic_nel_up_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_veget.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_vegetset.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_water.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_wind.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/ic_nel_workspace_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/dqynight.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/ico_mrm_mesh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/mixer.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/core => studio/src/plugins/object_viewer}/images/nel.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/pause.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/play.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/polymode.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/pqrticles.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/refresh.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/rmfill.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/rmline.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/rmpoints.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/seek-backward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/seek-forward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/skip-backward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/skip-forward.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/sound.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/stop.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/water.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/images/wind.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/modules.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/modules.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/object_viewer_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/attrib_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/attrib_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/attrib_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/auto_lod_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/auto_lod_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/basic_edit_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/basic_edit_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/bin_op_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/curve_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/curve_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/curve_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/direction_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/direction_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/direction_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/dup_ps.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/dup_ps.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/emitter_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/emitter_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/emitter_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/follow_path_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_bindable_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_bindable_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_bindable_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/located_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/mesh_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/mesh_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/mesh_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/morph_mesh_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/multi_tex_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/multi_tex_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_control_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_control_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_force_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_force_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_force_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_light_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_light_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_light_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_node.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_node.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_property_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_sound_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_sound_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_sound_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_system_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_system_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_system_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_texture_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_tree_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_tree_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_workspace_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_zone_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_zone_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/particle_zone_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_initial_pos.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_mover_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_mover_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_mover_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/ps_wrapper.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_bank_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_manager.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/scheme_manager.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/spinner_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/spinner_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/tail_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/tail_particle_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_blender_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_gradient_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/value_gradient_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/particle_system/workspace_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_set_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_set_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/animation_set_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/camera_control.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/camera_control.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/day_night_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/day_night_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/day_night_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/entity.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/entity.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/global_wind_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/global_wind_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/global_wind_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/setup_fog_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/setup_fog_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/setup_fog_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_scale_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_scale_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_tree_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/skeleton_tree_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/slot_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/slot_manager_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/slot_manager_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/sun_color_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/sun_color_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/sun_color_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_mrm_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_mrm_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_timer_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_timer_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/tune_timer_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/water_pool_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/water_pool_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/scene/water_pool_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_system.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/sound_system.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/stdpch.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/stdpch.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_density_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_density_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_editor.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_node.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_node.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable/vegetable_scale_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/vegetable_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/color_edit_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/color_edit_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/color_edit_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_float_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_uint_form.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/edit_range_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/hoverpoints.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/object_viewer/widgets/hoverpoints.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilder.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/add_tile.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/delete_image.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/delete_tile.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/down.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/empty_image.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons => studio/src/plugins/tile_editor/images}/ic_nel_add_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons => studio/src/plugins/tile_editor/images}/ic_nel_delete_item.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/ic_nel_new.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons => studio/src/plugins/tile_editor/images}/ic_nel_open.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/ic_nel_save.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/ic_nel_save_as.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/left.png (100%) rename code/{nel/tools/3d/object_viewer_qt/src/plugins/object_viewer => studio/src/plugins/tile_editor}/images/nel.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/replace_image.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/reset.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/right.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation0.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation180.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation270.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/rotation90.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/images/up.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item_delegate.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_item_delegate.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/tile_editor/tile_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/README (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_phrase.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_phrase.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_worksheet.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/editor_worksheet.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_bot_names.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_bot_names.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_new_sheet_names.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/extract_new_sheet_names.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ftp_selection.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/images/cdtoparent.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/images/dir.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/images/file.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/source_selection.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/source_selection.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/source_selection.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_editor.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/translation_manager/translation_manager_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_move.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_rotate.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_scale.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_select.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_turn.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/icons/ic_nel_world_editor.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/ovqt_plugin_world_editor.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitive_item.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitive_item.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_view.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/primitives_view.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/project_settings_dialog.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/project_settings_dialog.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/project_settings_dialog.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/property_editor_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/property_editor_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/property_editor_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_actions.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_actions.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_constants.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_global.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_misc.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_misc.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene_item.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_scene_item.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/world_editor/world_editor_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/CMakeLists.txt (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/color-fill.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/color-picker-black.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/colorize.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/draw-brush.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/go-down-7.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/go-jump-4.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/lock-6.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/images/lock-silver.png (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/painter_dock_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/painter_dock_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/painter_dock_widget.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/qnel_widget.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/qnel_widget.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter.qrc (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_main_window.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_main_window.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_main_window.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_model.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_model.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_plugin.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_plugin.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_settings_page.cpp (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_settings_page.h (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/plugins/zone_painter/zone_painter_settings_page.ui (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_de.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_en.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_fr.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/object_viewer_qt_ru.ts (100%) rename code/{nel/tools/3d/object_viewer_qt => studio}/src/translations/translations.qrc (100%) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 4f0439dfd..ba40d803e 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -190,6 +190,10 @@ IF(WITH_TOOLS) ADD_SUBDIRECTORY(tool) ENDIF(WITH_TOOLS) +IF(WITH_STUDIO) + ADD_SUBDIRECTORY(studio) +ENDIF(WITH_STUDIO) + # To build the documention, you will have to enable it # and then do the equivalent of "make DoxygenDoc". IF(BUILD_DOCUMENTATION) diff --git a/code/CMakeModules/nel.cmake b/code/CMakeModules/nel.cmake index b194b5ff9..36b813fa2 100644 --- a/code/CMakeModules/nel.cmake +++ b/code/CMakeModules/nel.cmake @@ -229,6 +229,10 @@ Remove the CMakeCache.txt file and try again from another folder, e.g.: ENDMACRO(CHECK_OUT_OF_SOURCE) MACRO(NL_SETUP_DEFAULT_OPTIONS) + IF(WITH_QT) + OPTION(WITH_STUDIO "Build Core Studio" OFF ) + ENDIF(WITH_QT) + ### # Features ### diff --git a/code/nel/tools/3d/CMakeLists.txt b/code/nel/tools/3d/CMakeLists.txt index cc3b54f02..c9981e276 100644 --- a/code/nel/tools/3d/CMakeLists.txt +++ b/code/nel/tools/3d/CMakeLists.txt @@ -56,7 +56,6 @@ IF(WITH_NEL_TOOLS) IF(WITH_QT) ADD_SUBDIRECTORY(tile_edit_qt) - ADD_SUBDIRECTORY(object_viewer_qt) ADD_SUBDIRECTORY(object_viewer_widget) ENDIF(WITH_QT) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt deleted file mode 100644 index 5a20ba46c..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt +++ /dev/null @@ -1,73 +0,0 @@ -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES}) - -FILE(GLOB SRC *.cpp *.h) -SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) - -SET(OVQT_CORE_PLUGIN_HDR - icore.h - icontext.h - icore_listener.h - ioptions_page.h - core_plugin.h - core.h - main_window.h - menu_manager.h - context_manager.h - settings_dialog.h - search_paths_settings_page.h - general_settings_page.h - plugin_view_dialog.h -) - -SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui - plugin_view_dialog.ui - general_settings_page.ui - search_paths_settings_page.ui -) - -SET(OVQT_CORE_PLUGIN_RCS core.qrc) - -SET(QT_USE_QTGUI TRUE) -SET(QT_USE_QTOPENGL TRUE) - -QT4_ADD_RESOURCES(OVQT_CORE_PLUGIN_RC_SRCS ${OVQT_CORE_PLUGIN_RCS}) -QT4_WRAP_CPP(OVQT_CORE_PLUGIN_MOC_SRC ${OVQT_CORE_PLUGIN_HDR}) -QT4_WRAP_UI(OVQT_CORE_PLUGIN_UI_HDRS ${OVQT_CORE_PLUGIN_UIS}) - -SOURCE_GROUP(QtResources FILES ${OVQT_CORE_PLUGIN_UIS} ${OVQT_CORE_PLUGIN_RCS}) -SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_CORE_PLUGIN_UI_HDRS}) -SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) -SOURCE_GROUP("Core Plugin" FILES ${SRC}) -SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) - -ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) - -TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) - -NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) -NL_ADD_LIB_SUFFIX(ovqt_plugin_core) - -ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) - -IF(WIN32) - IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) - ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) - ENDIF(WITH_INSTALL_LIBRARIES) -ELSE(WIN32) - IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) - ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) - ENDIF(WITH_INSTALL_LIBRARIES) -ENDIF(WIN32) - -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp deleted file mode 100644 index 8355b5cb8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "context_manager.h" -#include "icontext.h" -#include "main_window.h" - -// NeL includes -#include - -// Qt includes -#include -#include - -namespace Core -{ - -struct ContextManagerPrivate -{ - explicit ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget); - Core::MainWindow *m_mainWindow; - QTabWidget *m_tabWidget; - QVector m_contexts; - int m_oldCurrent; -}; - -ContextManagerPrivate::ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget) - : m_mainWindow(mainWindow), - m_tabWidget(tabWidget), - m_oldCurrent(-1) -{ -} - -ContextManager::ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget) - : d(new ContextManagerPrivate(mainWindow, tabWidget)) -{ - QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(objectAdded(QObject *)), - this, SLOT(objectAdded(QObject *))); - QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(aboutToRemoveObject(QObject *)), - this, SLOT(aboutToRemoveObject(QObject *))); - - QObject::connect(d->m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); -} - -ContextManager::~ContextManager() -{ - delete d; -} - -Core::IContext *ContextManager::currentContext() const -{ - int currentIndex = d->m_tabWidget->currentIndex(); - if (currentIndex < 0) - return 0; - return d->m_contexts.at(currentIndex); -} - -Core::IContext *ContextManager::context(const QString &id) const -{ - const int index = indexOf(id); - if (index >= 0) - return d->m_contexts.at(index); - return 0; -} - -void ContextManager::registerUndoStack(QUndoStack *stack) -{ - nlassert(stack); - d->m_mainWindow->undoGroup()->addStack(stack); -} - -void ContextManager::unregisterUndoStack(QUndoStack *stack) -{ - nlassert(stack); - d->m_mainWindow->undoGroup()->removeStack(stack); -} - -void ContextManager::activateContext(const QString &id) -{ - const int index = indexOf(id); - if (index >= 0) - d->m_tabWidget->setCurrentIndex(index); -} - -void ContextManager::updateCurrentContext() -{ - d->m_mainWindow->updateContext(currentContext()); -} - -void ContextManager::objectAdded(QObject *obj) -{ - IContext *context = qobject_cast(obj); - if (context) - addContextObject(context); -} - -void ContextManager::aboutToRemoveObject(QObject *obj) -{ - IContext *context = qobject_cast(obj); - if (context) - removeContextObject(context); -} - -void ContextManager::addContextObject(IContext *context) -{ - d->m_contexts.push_back(context); - d->m_mainWindow->addContextObject(context); - - QWidget *tabWidget = new QWidget(d->m_tabWidget); - d->m_tabWidget->addTab(tabWidget, context->icon(), context->trName()); - QGridLayout *gridLayout = new QGridLayout(tabWidget); - gridLayout->setObjectName(QString::fromUtf8("gridLayout_") + context->id()); - gridLayout->setContentsMargins(0, 0, 0, 0); - gridLayout->addWidget(context->widget(), 0, 0, 1, 1); -} - -void ContextManager::removeContextObject(IContext *context) -{ - d->m_mainWindow->removeContextObject(context); - - const int index = indexOf(context->id()); - QWidget *widget = d->m_tabWidget->widget(index); - d->m_tabWidget->removeTab(index); - d->m_contexts.remove(index); - delete widget; -} - -void ContextManager::currentTabChanged(int index) -{ - if (index >= 0) - { - IContext *context = d->m_contexts.at(index); - IContext *oldContext = 0; - if (d->m_oldCurrent >= 0) - oldContext = d->m_contexts.at(d->m_oldCurrent); - d->m_oldCurrent = index; - Q_EMIT currentContextChanged(context, oldContext); - } -} - -int ContextManager::indexOf(const QString &id) const -{ - for (int i = 0; i < d->m_contexts.count(); ++i) - { - if (d->m_contexts.at(i)->id() == id) - return i; - } - nlwarning(QString("Warning, no such context: %1").arg(id).toUtf8().constData()); - return -1; -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h deleted file mode 100644 index 8151648e7..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/context_manager.h +++ /dev/null @@ -1,76 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CONTEXT_MANAGER_H -#define CONTEXT_MANAGER_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include - -QT_BEGIN_NAMESPACE -class QTabWidget; -class QUndoStack; -QT_END_NAMESPACE - -namespace Core -{ -class IContext; -class MainWindow; -struct ContextManagerPrivate; - -class CORE_EXPORT ContextManager : public QObject -{ - Q_OBJECT - -public: - explicit ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget); - virtual ~ContextManager(); - - Core::IContext *currentContext() const; - Core::IContext *context(const QString &id) const; - - // temporary solution for multiple undo stacks per context - void registerUndoStack(QUndoStack *stack); - void unregisterUndoStack(QUndoStack *stack); - -Q_SIGNALS: - // the default argument '=0' is important for connects without the oldContext argument. - void currentContextChanged(Core::IContext *context, Core::IContext *oldContext = 0); - -public Q_SLOTS: - void activateContext(const QString &id); - void updateCurrentContext(); - -private Q_SLOTS: - void objectAdded(QObject *obj); - void aboutToRemoveObject(QObject *obj); - void addContextObject(IContext *context); - void removeContextObject(IContext *context); - void currentTabChanged(int index); - -private: - int indexOf(const QString &id) const; - - ContextManagerPrivate *d; -}; - -} // namespace Core - -#endif // CONTEXT_MANAGER_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp deleted file mode 100644 index b21d934c8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "core.h" -#include "context_manager.h" -#include "main_window.h" -#include "../../extension_system/iplugin_manager.h" - -static Core::CoreImpl *m_coreInstance = 0; - -namespace Core -{ - -ICore *ICore::instance() -{ - return m_coreInstance; -} - -CoreImpl::CoreImpl(MainWindow *mainWindow) -{ - m_mainWindow = mainWindow; - m_coreInstance = this; -} - -CoreImpl::~CoreImpl() -{ - m_coreInstance = 0; -} - -bool CoreImpl::showOptionsDialog(const QString &group, - const QString &page, - QWidget *parent) -{ - return m_mainWindow->showOptionsDialog(group, page, parent); -} - -MenuManager *CoreImpl::menuManager() const -{ - return m_mainWindow->menuManager(); -} - -ContextManager *CoreImpl::contextManager() const -{ - return m_mainWindow->contextManager(); -} - -QSettings *CoreImpl::settings() const -{ - return m_mainWindow->settings(); -} - -QMainWindow *CoreImpl::mainWindow() const -{ - return m_mainWindow; -} - -ExtensionSystem::IPluginManager *CoreImpl::pluginManager() const -{ - return m_mainWindow->pluginManager(); -} - -} // namespace Core diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h deleted file mode 100644 index f34dd6ae6..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.h +++ /dev/null @@ -1,54 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_H -#define CORE_H - -#include "icore.h" - -namespace Core -{ -class MainWindow; - -class CoreImpl : public ICore -{ - Q_OBJECT - -public: - explicit CoreImpl(MainWindow *mainWindow); - virtual ~CoreImpl(); - - virtual bool showOptionsDialog(const QString &group = QString(), - const QString &page = QString(), - QWidget *parent = 0); - - virtual MenuManager *menuManager() const; - virtual ContextManager *contextManager() const; - - virtual QSettings *settings() const; - virtual QMainWindow *mainWindow() const; - - virtual ExtensionSystem::IPluginManager *pluginManager() const; -private: - MainWindow *m_mainWindow; - friend class MainWindow; -}; - -} // namespace Core - -#endif // CORE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc deleted file mode 100644 index 68b6ad141..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core.qrc +++ /dev/null @@ -1,21 +0,0 @@ - - - icons/ic_nel_add_item.png - icons/ic_nel_redo.png - icons/ic_nel_undo.png - icons/ic_nel_crash.png - icons/ic_nel_delete_item.png - icons/ic_nel_down_item.png - icons/ic_nel_generic_settings.png - icons/ic_nel_open.png - icons/ic_nel_new.png - icons/ic_nel_save.png - icons/ic_nel_save_as.png - icons/ic_nel_path_settings.png - icons/ic_nel_pill.png - icons/ic_nel_reset_all.png - icons/ic_nel_up_item.png - images/nel.png - images/preferences.png - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h deleted file mode 100644 index 8bf6d5fcd..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_constants.h +++ /dev/null @@ -1,121 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2010 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_CONSTANTS_H -#define CORE_CONSTANTS_H - -namespace Core -{ -namespace Constants -{ - -const char *const OVQT_VERSION_LONG = "0.8"; -const char *const OVQT_VENDOR = "Ryzom Core"; -const char *const OVQT_YEAR = "2010, 2011"; -const char *const OVQT_CORE_PLUGIN = "Core"; - -//mainwindow -const char *const MAIN_WINDOW = "ObjectViewerQt.MainWindow"; - -//menubar -const char *const MENU_BAR = "ObjectViewerQt.MenuBar"; - -//menus -const char *const M_FILE = "ObjectViewerQt.Menu.File"; -const char *const M_EDIT = "ObjectViewerQt.Menu.Edit"; -const char *const M_VIEW = "ObjectViewerQt.Menu.View"; -const char *const M_SCENE = "ObjectViewerQt.Menu.Scene"; -const char *const M_TOOLS = "ObjectViewerQt.Menu.Tools"; -const char *const M_WINDOW = "ObjectViewerQt.Menu.Window"; -const char *const M_HELP = "ObjectViewerQt.Menu.Help"; - -const char *const M_FILE_RECENTFILES = "ObjectViewerQt.Menu.File.RecentFiles"; -const char *const M_SHEET = "ObjectViewerQt.Menu.Sheet"; - -//actions -const char *const NEW = "ObjectViewerQt.New"; -const char *const OPEN = "ObjectViewerQt.Open"; -const char *const SAVE = "ObjectViewerQt.Save"; -const char *const SAVE_AS = "ObjectViewerQt.SaveAs"; -const char *const SAVE_ALL = "ObjectViewerQt.SaveAll"; -const char *const EXIT = "ObjectViewerQt.Exit"; - -const char *const UNDO = "ObjectViewerQt.Undo"; -const char *const REDO = "ObjectViewerQt.Redo"; -const char *const CUT = "ObjectViewerQt.Cut"; -const char *const COPY = "ObjectViewerQt.Copy"; -const char *const PASTE = "ObjectViewerQt.Paste"; -const char *const DEL = "ObjectViewerQt.Del"; -const char *const FIND = "ObjectViewerQt.Find"; -const char *const SELECT_ALL = "ObjectViewerQt.SelectAll"; -const char *const GOTO_POS = "ObjectViewerQt.Goto"; - -const char *const SETTINGS = "ObjectViewerQt.Settings"; -const char *const TOGGLE_FULLSCREEN = "ObjectViewerQt.ToggleFullScreen"; - -const char *const CLOSE = "ObjectViewerQt.Close"; -const char *const CLOSEALL = "ObjectViewerQt.CloseAll"; -const char *const CLOSEOTHERS = "ObjectViewerQt.CloseOthers"; -const char *const ABOUT = "ObjectViewerQt.About"; -const char *const ABOUT_PLUGINS = "ObjectViewerQt.AboutPlugins"; -const char *const ABOUT_QT = "ObjectViewerQt.AboutQt"; - -//settings -const char *const SETTINGS_CATEGORY_GENERAL = "general"; -const char *const SETTINGS_CATEGORY_GENERAL_ICON = ":/icons/ic_nel_generic_settings.png"; -const char *const SETTINGS_TR_CATEGORY_GENERAL = QT_TR_NOOP("General"); - -const char *const MAIN_WINDOW_SECTION = "MainWindow"; -const char *const MAIN_WINDOW_STATE = "WindowState"; -const char *const MAIN_WINDOW_GEOMETRY = "WindowGeometry"; -const char *const QT_STYLE = "QtStyle"; -const char *const QT_PALETTE = "QtPalette"; - -const char *const LANGUAGE = "Language"; -const char *const PLUGINS_PATH = "PluginPath"; -const char *const DATA_PATH_SECTION = "DataPath"; -const char *const SEARCH_PATHS = "SearchPaths"; -const char *const RECURSIVE_SEARCH_PATHS = "RecursiveSearchPathes"; -const char *const LEVELDESIGN_PATH = "LevelDesignPath"; -const char *const PRIMITIVES_PATH = "PrimitivesPath"; -const char *const ASSETS_PATH = "AssetsPath"; -const char *const LIGOCONFIG_FILE = "LigoConfigFile"; -const char *const REMAP_EXTENSIONS = "RemapExtensions"; - -const char *const LOG_SECTION = "LogSettings"; -const char *const LOG_ERROR = "LogError"; -const char *const LOG_WARNING = "LogWarning"; -const char *const LOG_DEBUG = "LogDebug"; -const char *const LOG_ASSERT = "LogAssert"; -const char *const LOG_INFO = "LogInfo"; - -//resources -const char *const ICON_NEL = ":/core/images/nel.png"; -const char *const ICON_SETTINGS = ":/core/images/preferences.png"; -const char *const ICON_PILL = ":/core/icons/ic_nel_pill.png"; -const char *const ICON_OPEN = ":/core/icons/ic_nel_open.png"; -const char *const ICON_NEW = ":/core/icons/ic_nel_new.png"; -const char *const ICON_SAVE = ":/core/icons/ic_nel_save.png"; -const char *const ICON_SAVE_AS = ":/core/icons/ic_nel_save_as.png"; -const char *const ICON_CRASH = ":/core/icons/ic_nel_crash.png"; -const char *const ICON_UNDO = ":/core/icons/ic_nel_undo.png"; -const char *const ICON_REDO = ":/core/icons/ic_nel_redo.png"; - -} // namespace Constants -} // namespace Core - -#endif // CORE_CONSTANTS_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h deleted file mode 100644 index 48fe0ece9..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_global.h +++ /dev/null @@ -1,30 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_GLOBAL_H -#define CORE_GLOBAL_H - -#include - -#if defined(CORE_LIBRARY) -# define CORE_EXPORT Q_DECL_EXPORT -#else -# define CORE_EXPORT Q_DECL_IMPORT -#endif - -#endif // CORE_GLOBAL_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp deleted file mode 100644 index a72a68ccc..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2010 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "core_plugin.h" -#include "settings_dialog.h" -#include "core_constants.h" -#include "search_paths_settings_page.h" -#include "general_settings_page.h" -#include "../../extension_system/iplugin_spec.h" - -// NeL includes -#include "nel/misc/debug.h" - -// Qt includes -#include -#include -#include -#include -#include -#include - -using namespace Core; - -CorePlugin::CorePlugin() - : m_plugMan(0), - m_mainWindow(0) -{ -} - -CorePlugin::~CorePlugin() -{ - Q_FOREACH(QObject *obj, m_autoReleaseObjects) - { - m_plugMan->removeObject(obj); - } - qDeleteAll(m_autoReleaseObjects); - m_autoReleaseObjects.clear(); - - if (m_mainWindow) - delete m_mainWindow; -} - -bool CorePlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) -{ - Q_UNUSED(errorString); - m_plugMan = pluginManager; - - m_mainWindow = new MainWindow(pluginManager); - bool success = m_mainWindow->initialize(errorString); - - GeneralSettingsPage *generalSettings = new GeneralSettingsPage(this); - SearchPathsSettingsPage *searchPathPage = new SearchPathsSettingsPage(false, this); - SearchPathsSettingsPage *recureseSearchPathPage = new SearchPathsSettingsPage(true, this); - - generalSettings->applyGeneralSettings(); - searchPathPage->applySearchPaths(); - recureseSearchPathPage->applySearchPaths(); - addAutoReleasedObject(generalSettings); - addAutoReleasedObject(searchPathPage); - addAutoReleasedObject(recureseSearchPathPage); - return success; -} - -void CorePlugin::extensionsInitialized() -{ - m_mainWindow->extensionsInitialized(); -} - -void CorePlugin::shutdown() -{ -} - -void CorePlugin::setNelContext(NLMISC::INelContext *nelContext) -{ -#ifdef NL_OS_WINDOWS - // Ensure that a context doesn't exist yet. - // This only applies to platforms without PIC, e.g. Windows. - nlassert(!NLMISC::INelContext::isContextInitialised()); -#endif // NL_OS_WINDOWS - m_libContext = new NLMISC::CLibraryContext(*nelContext); -} - -void CorePlugin::addAutoReleasedObject(QObject *obj) -{ - m_plugMan->addObject(obj); - m_autoReleaseObjects.prepend(obj); -} - -Q_EXPORT_PLUGIN(CorePlugin) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h deleted file mode 100644 index 5062227e3..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/core_plugin.h +++ /dev/null @@ -1,74 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2010 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CORE_PLUGIN_H -#define CORE_PLUGIN_H - -#include "../../extension_system/iplugin.h" -#include "main_window.h" - -#include "nel/misc/app_context.h" - -#include - -namespace NLMISC -{ -class CLibraryContext; -} - -namespace ExtensionSystem -{ -class IPluginSpec; -} - -namespace Core -{ - -class CorePlugin : public QObject, public ExtensionSystem::IPlugin -{ - Q_OBJECT - Q_INTERFACES(ExtensionSystem::IPlugin) -public: - - CorePlugin(); - virtual ~CorePlugin(); - - bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); - void extensionsInitialized(); - void shutdown(); - - void setNelContext(NLMISC::INelContext *nelContext); - - void addAutoReleasedObject(QObject *obj); - - ExtensionSystem::IPluginManager *pluginManager() const - { - return m_plugMan; - } - -protected: - NLMISC::CLibraryContext *m_libContext; - -private: - ExtensionSystem::IPluginManager *m_plugMan; - MainWindow *m_mainWindow; - QList m_autoReleaseObjects; -}; - -} // namespace Core - -#endif // CORE_PLUGIN_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp deleted file mode 100644 index bfbb06d66..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "general_settings_page.h" -#include "core_constants.h" -#include "icore.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -namespace Core -{ - -GeneralSettingsPage::GeneralSettingsPage(QObject *parent) - : IOptionsPage(parent), - m_page(0) -{ - m_originalPalette = QApplication::palette(); -} - -GeneralSettingsPage::~GeneralSettingsPage() -{ -} - -QString GeneralSettingsPage::id() const -{ - return QLatin1String("general_settings"); -} - -QString GeneralSettingsPage::trName() const -{ - return tr("General"); -} - -QString GeneralSettingsPage::category() const -{ - return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); -} - -QString GeneralSettingsPage::trCategory() const -{ - return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); -} - -QIcon GeneralSettingsPage::categoryIcon() const -{ - return QIcon(); -} - -void GeneralSettingsPage::applyGeneralSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - - settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - QApplication::setStyle(QStyleFactory::create(settings->value(Constants::QT_STYLE, "").toString())); - - if (settings->value(Constants::QT_PALETTE, true).toBool()) - QApplication::setPalette(QApplication::style()->standardPalette()); - else - QApplication::setPalette(m_originalPalette); - settings->endGroup(); - - QString levelDesignPrefix; -#if defined(_DEBUG) && defined(NL_OS_WINDOWS) - levelDesignPrefix = "l:"; -#else - levelDesignPrefix = QString("%1/data_leveldesign").arg(RYZOM_SHARE_PREFIX); -#endif - - // Add primitives path and ligo config file to CPath - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - QString primitivePath = settings->value(Core::Constants::PRIMITIVES_PATH, QString("%1/primitives").arg(levelDesignPrefix)).toString(); - QString ligoConfigFile = settings->value(Core::Constants::LIGOCONFIG_FILE, QString("%1/leveldesign/world_editor_files/world_editor_classes.xml").arg(levelDesignPrefix)).toString(); - QString leveldesignPath = settings->value(Core::Constants::LEVELDESIGN_PATH, QString("%1/leveldesign").arg(levelDesignPrefix)).toString(); - NLMISC::CPath::addSearchPath(primitivePath.toUtf8().constData(), true, false); - NLMISC::CPath::display(); - NLMISC::CPath::addSearchFile(ligoConfigFile.toUtf8().constData()); - NLMISC::CPath::addSearchPath(leveldesignPath.toUtf8().constData(), true, false); - settings->endGroup(); -} - -QWidget *GeneralSettingsPage::createPage(QWidget *parent) -{ - m_page = new QWidget(parent); - m_ui.setupUi(m_page); - - readSettings(); - connect(m_ui.languageComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(changeLanguage(QString))); - connect(m_ui.pluginsPathButton, SIGNAL(clicked()), this, SLOT(setPluginsPath())); - connect(m_ui.leveldesignPathButton, SIGNAL(clicked()), this, SLOT(setLevelDesignPath())); - connect(m_ui.assetsPathButton, SIGNAL(clicked()), this, SLOT(setAssetsPath())); - connect(m_ui.primitivesPathButton, SIGNAL(clicked()), this, SLOT(setPrimitivesPath())); - connect(m_ui.ligoConfigFileButton, SIGNAL(clicked()), this, SLOT(setLigoConfigFile())); - return m_page; -} - -void GeneralSettingsPage::apply() -{ - writeSettings(); - applyGeneralSettings(); -} - -void GeneralSettingsPage::finish() -{ - delete m_page; - m_page = 0; -} - -void GeneralSettingsPage::changeLanguage(const QString &lang) -{ - QMessageBox::information(0, tr("Restart required"), - tr("The language change will take effect after a restart of Object Viewer Qt.")); -} - -void GeneralSettingsPage::setPluginsPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the plugins path"), - m_ui.pluginsPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.pluginsPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::setLevelDesignPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the level design path"), - m_ui.leveldesignPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.leveldesignPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::setPrimitivesPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the primitives path"), - m_ui.primitivesPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.primitivesPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::setLigoConfigFile() -{ - QString newFile = QFileDialog::getOpenFileName(0, tr("Set the ligo config file"), - m_ui.ligoConfigFileLineEdit->text()); - if (!newFile.isEmpty()) - { - m_ui.ligoConfigFileLineEdit->setText(newFile); - } -} - - -void GeneralSettingsPage::setAssetsPath() -{ - QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the assets path"), - m_ui.assetsPathLineEdit->text()); - if (!newPath.isEmpty()) - { - m_ui.assetsPathLineEdit->setText(newPath); - } -} - -void GeneralSettingsPage::readSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - - m_ui.pluginsPathLineEdit->setText(settings->value(Core::Constants::PLUGINS_PATH, "./plugins").toString()); - - settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - m_ui.styleComboBox->addItems(QStyleFactory::keys()); - QString style = settings->value(Constants::QT_STYLE, "").toString(); - if (style == "") - m_ui.styleComboBox->setCurrentIndex(0); - else - m_ui.styleComboBox->setCurrentIndex(m_ui.styleComboBox->findText(style)); - m_ui.paletteCheckBox->setChecked(settings->value(Constants::QT_PALETTE, true).toBool()); - settings->endGroup(); - - QStringList paths; - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - m_ui.leveldesignPathLineEdit->setText(settings->value(Core::Constants::LEVELDESIGN_PATH, "l:/leveldesign").toString()); - m_ui.assetsPathLineEdit->setText(settings->value(Core::Constants::ASSETS_PATH, "w:/database").toString()); - m_ui.primitivesPathLineEdit->setText(settings->value(Core::Constants::PRIMITIVES_PATH, "l:/primitives").toString()); - m_ui.ligoConfigFileLineEdit->setText(settings->value(Core::Constants::LIGOCONFIG_FILE, "l:/leveldesign/world_editor_files/world_editor_classes.xml").toString()); - settings->endGroup(); -} - -void GeneralSettingsPage::writeSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - - settings->setValue(Core::Constants::PLUGINS_PATH, m_ui.pluginsPathLineEdit->text()); - - settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - if (m_ui.styleComboBox->currentIndex() == 0) - settings->setValue(Constants::QT_STYLE, ""); - else - settings->setValue(Constants::QT_STYLE, m_ui.styleComboBox->currentText()); - settings->setValue(Constants::QT_PALETTE, m_ui.paletteCheckBox->isChecked()); - settings->endGroup(); - - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - settings->setValue(Core::Constants::LEVELDESIGN_PATH, m_ui.leveldesignPathLineEdit->text()); - settings->setValue(Core::Constants::ASSETS_PATH, m_ui.assetsPathLineEdit->text()); - settings->setValue(Core::Constants::PRIMITIVES_PATH, m_ui.primitivesPathLineEdit->text()); - settings->setValue(Core::Constants::LIGOCONFIG_FILE, m_ui.ligoConfigFileLineEdit->text()); - settings->endGroup(); - settings->sync(); -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h deleted file mode 100644 index 66eacd189..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.h +++ /dev/null @@ -1,74 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef GENERAL_SETTINGS_PAGE_H -#define GENERAL_SETTINGS_PAGE_H - -#include - -#include "ioptions_page.h" - -#include "ui_general_settings_page.h" - -class QWidget; - -namespace Core -{ -/** -@class GeneralSettingsPage -*/ -class GeneralSettingsPage : public Core::IOptionsPage -{ - Q_OBJECT - -public: - explicit GeneralSettingsPage(QObject *parent = 0); - ~GeneralSettingsPage(); - - QString id() const; - QString trName() const; - QString category() const; - QString trCategory() const; - QIcon categoryIcon() const; - QWidget *createPage(QWidget *parent); - - void apply(); - void finish(); - - void applyGeneralSettings(); - -private Q_SLOTS: - void changeLanguage(const QString &lang); - void setPluginsPath(); - void setLevelDesignPath(); - void setAssetsPath(); - void setPrimitivesPath(); - void setLigoConfigFile(); - -private: - void readSettings(); - void writeSettings(); - - QPalette m_originalPalette; - QWidget *m_page; - Ui::GeneralSettingsPage m_ui; -}; - -} // namespace Core - -#endif // GENERAL_SETTINGS_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui deleted file mode 100644 index 7d40b65df..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/general_settings_page.ui +++ /dev/null @@ -1,233 +0,0 @@ - - - GeneralSettingsPage - - - - 0 - 0 - 267 - 282 - - - - Form - - - - 6 - - - 3 - - - - - Qt Style - - - - 6 - - - 6 - - - - - - default - - - - - - - - Use style's standard palette - - - - - - - - - - Language - - - - 6 - - - - - false - - - - English - - - - - German - - - - - French - - - - - Russian - - - - - - - - - - - Paths - - - - 6 - - - 6 - - - - - Plugins - - - - - - - - 0 - 0 - - - - - - - - ... - - - - - - - Sheets - - - - - - - - 0 - 0 - - - - - - - - ... - - - - - - - Assets Database: - - - - - - - - 0 - 0 - - - - - - - - ... - - - - - - - Primitives - - - - - - - - - - ... - - - - - - - - - - Ligo Config File - - - - - - - ... - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_crash.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_crash.png deleted file mode 100644 index 5e1f6380bad86acca278838ce7a1c6499eb2660f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6630 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 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_path_settings.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_path_settings.png deleted file mode 100644 index 8f344111275abb152ae1a8d1aeabde4627ddeab0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4557 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 rVX-&<{98FWQhbW?9;ba!ELWdKlNX>N2bPDNB8 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 %I{nv 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 diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save_as.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_save_as.png deleted file mode 100644 index 6cb71a33436e58801b73476821800b1b95a1018e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52871 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 -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ICONTEXT_H -#define ICONTEXT_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include -#include -#include - -QT_BEGIN_NAMESPACE -class QWidget; -class QUndoStack; -QT_END_NAMESPACE - -namespace Core -{ -/** -@interface IContext -@brief The IContext is an interface for providing tab pages in main window. -@details You need to subclass this interface and put an instance of your subclass - into the plugin manager object pool. -*/ -class CORE_EXPORT IContext: public QObject -{ - Q_OBJECT -public: - IContext(QObject *parent = 0): QObject(parent) {} - virtual ~IContext() {} - - /// id() is a unique identifier for referencing this page - virtual QString id() const = 0; - - /// trName() is the (translated) name for display. - virtual QString trName() const = 0; - - /// icon() is the icon for display - virtual QIcon icon() const = 0; - - /// The widget will be destroyed by the widget hierarchy when the main window closes - virtual QWidget *widget() = 0; - - virtual QUndoStack *undoStack() = 0; - - virtual void open() = 0; - - virtual void save(){} - - virtual void saveAs(){} - - virtual void newDocument(){} - - virtual void close(){} -}; - -} // namespace Core - -#endif // ICONTEXT_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h deleted file mode 100644 index 4f1ee474f..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore.h +++ /dev/null @@ -1,70 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ICORE_H -#define ICORE_H - -#include "core_global.h" - -#include - -QT_BEGIN_NAMESPACE -class QMainWindow; -class QSettings; -QT_END_NAMESPACE - -namespace ExtensionSystem -{ -class IPluginManager; -} - -namespace Core -{ -class MenuManager; -class ContextManager; - -class CORE_EXPORT ICore : public QObject -{ - Q_OBJECT - -public: - ICore() {} - virtual ~ICore() {} - - static ICore *instance(); - - virtual bool showOptionsDialog(const QString &group = QString(), - const QString &page = QString(), - QWidget *parent = 0) = 0; - - virtual MenuManager *menuManager() const = 0; - virtual ContextManager *contextManager() const = 0; - - virtual QSettings *settings() const = 0; - virtual QMainWindow *mainWindow() const = 0; - - virtual ExtensionSystem::IPluginManager *pluginManager() const = 0; - -Q_SIGNALS: - void changeSettings(); - void closeMainWindow(); -}; - -} // namespace Core - -#endif // ICORE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h deleted file mode 100644 index c27e40242..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icore_listener.h +++ /dev/null @@ -1,63 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ICORE_LISTENER_H -#define ICORE_LISTENER_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include - -QT_BEGIN_NAMESPACE -class QWidget; -QT_END_NAMESPACE - -namespace Core -{ -/** -@interface ICoreListener -@brief The ICoreListener is an interface for providing a hook for plugins to veto on close event emitted from -the core plugin. -@details You implement this interface if you want to prevent the closing of the whole application. -If the application window requests a close, then first ICoreListener::closeMainWindow() is called -(in arbitrary order) on all registered objects implementing this interface. -If one if these calls returns false, the process is aborted and the event is ignored. If all calls return -true, the corresponding signal is emitted and the event is accepted/performed. - -You need to add your implementing object to the plugin managers objects: -PluginManager->addObject(yourImplementingObject); -Don't forget to remove the object again at deconstruction (e.g. in the destructor of -your plugin) -*/ -class CORE_EXPORT ICoreListener: public QObject -{ - Q_OBJECT -public: - ICoreListener(QObject *parent = 0): QObject(parent) {} - virtual ~ICoreListener() {} - - /// Return false from the implemented method if you want to prevent the event. - virtual bool closeMainWindow() const = 0; -}; - -} // namespace Core - - -#endif // ICORE_LISTENER_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/preferences.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/preferences.png deleted file mode 100644 index 729bc039355928ae3b0c39969f6dbfea6154a125..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10286 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 -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef IOPTIONS_PAGE_H -#define IOPTIONS_PAGE_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include - -QT_BEGIN_NAMESPACE -class QWidget; -class QIcon; -QT_END_NAMESPACE - -namespace Core -{ -/** -@interface IOptionsPage -@brief The IOptionsPage is an interface for providing options pages. -@details You need to subclass this interface and put an instance of your subclass - into the plugin manager object pool. -*/ -class CORE_EXPORT IOptionsPage: public QObject -{ - Q_OBJECT -public: - IOptionsPage(QObject *parent = 0): QObject(parent) {} - virtual ~IOptionsPage() {} - - /// id() is a unique identifier for referencing this page - virtual QString id() const = 0; - - /// trName() is the (translated) name for display. - virtual QString trName() const = 0; - - /// category() is the unique id for the category that the page should be displayed in - virtual QString category() const = 0; - - /// trCategory() is the translated category - virtual QString trCategory() const = 0; - - virtual QIcon categoryIcon() const = 0; - - /// createPage() is called to retrieve the widget to show in the preferences dialog - /// The widget will be destroyed by the widget hierarchy when the dialog closes - virtual QWidget *createPage(QWidget *parent) = 0; - - /// apply() is called to store the settings. It should detect if any changes have been made and store those. - virtual void apply() = 0; - - /// finish() is called directly before the preferences dialog closes - virtual void finish() = 0; -}; - -} // namespace Core - -#endif // IOPTIONS_PAGE_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp deleted file mode 100644 index a90e67bc0..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.cpp +++ /dev/null @@ -1,492 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "main_window.h" -#include "icontext.h" -#include "icore_listener.h" -#include "menu_manager.h" -#include "context_manager.h" -#include "core.h" -#include "core_constants.h" -#include "settings_dialog.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include - -namespace Core -{ - -MainWindow::MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) - : QMainWindow(parent), - m_pluginManager(0), - m_menuManager(0), - m_contextManager(0), - m_coreImpl(0), - m_lastDir("."), - m_undoGroup(0), - m_settings(0) -{ - QCoreApplication::setApplicationName(QLatin1String("ObjectViewerQt")); - QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::OVQT_VERSION_LONG)); - QCoreApplication::setOrganizationName(QLatin1String("RyzomCore")); - - setObjectName(Constants::MAIN_WINDOW); - setWindowIcon(QIcon(Constants::ICON_PILL)); - setWindowTitle(tr("Object Viewer Qt")); - - m_pluginManager = pluginManager; - m_settings = m_pluginManager->settings(); - m_coreImpl = new CoreImpl(this); - -#ifdef Q_WS_MAC - m_menuBar = new QMenuBar(0); -#else - m_menuBar = new QMenuBar(this); - setMenuBar(m_menuBar); -#endif - - m_menuManager = new MenuManager(m_menuBar, this); - - m_tabWidget = new QTabWidget(this); - m_tabWidget->setTabPosition(QTabWidget::South); - m_tabWidget->setMovable(false); - m_tabWidget->setDocumentMode(true); - setCentralWidget(m_tabWidget); - - m_contextManager = new ContextManager(this, m_tabWidget); - - setDockNestingEnabled(true); - m_originalPalette = QApplication::palette(); - m_undoGroup = new QUndoGroup(this); - - createDialogs(); - createActions(); - createMenus(); - createStatusBar(); - resize(1024, 768); -} - -MainWindow::~MainWindow() -{ - m_pluginManager->removeObject(m_coreImpl); - m_pluginManager->removeObject(m_menuManager); - - delete m_coreImpl; - m_coreImpl = 0; -} - -bool MainWindow::initialize(QString *errorString) -{ - Q_UNUSED(errorString); - m_pluginManager->addObject(m_coreImpl); - m_pluginManager->addObject(m_menuManager); - return true; -} - -void MainWindow::extensionsInitialized() -{ - readSettings(); - connect(m_contextManager, SIGNAL(currentContextChanged(Core::IContext *)), - this, SLOT(updateContext(Core::IContext *))); - if (m_contextManager->currentContext() != NULL) - updateContext(m_contextManager->currentContext()); - show(); -} - -MenuManager *MainWindow::menuManager() const -{ - return m_menuManager; -} - -ContextManager *MainWindow::contextManager() const -{ - return m_contextManager; -} - -QSettings *MainWindow::settings() const -{ - return m_settings; -} - -QUndoGroup *MainWindow::undoGroup() const -{ - return m_undoGroup; -} - -ExtensionSystem::IPluginManager *MainWindow::pluginManager() const -{ - return m_pluginManager; -} - -void MainWindow::addContextObject(IContext *context) -{ - QUndoStack *stack = context->undoStack(); - if (stack) - m_undoGroup->addStack(stack); -} - -void MainWindow::removeContextObject(IContext *context) -{ - QUndoStack *stack = context->undoStack(); - if (stack) - m_undoGroup->removeStack(stack); -} - -void MainWindow::open() -{ - m_contextManager->currentContext()->open(); -} - -void MainWindow::newFile() -{ - m_contextManager->currentContext()->newDocument(); -} - -void MainWindow::save() -{ - m_contextManager->currentContext()->save(); -} - -void MainWindow::saveAs() -{ - m_contextManager->currentContext()->saveAs(); -} - -void MainWindow::saveAll() -{ -} - -void MainWindow::closeDocument() -{ - m_contextManager->currentContext()->close(); -} - - -void MainWindow::cut() -{ -} - -void MainWindow::copy() -{ -} - -void MainWindow::paste() -{ -} - -void MainWindow::del() -{ -} - -void MainWindow::find() -{ -} - -void MainWindow::gotoPos() -{ -} - -void MainWindow::setFullScreen(bool enabled) -{ - if (bool(windowState() & Qt::WindowFullScreen) == enabled) - return; - if (enabled) - setWindowState(windowState() | Qt::WindowFullScreen); - else - setWindowState(windowState() & ~Qt::WindowFullScreen); -} - -bool MainWindow::showOptionsDialog(const QString &group, - const QString &page, - QWidget *parent) -{ - if (!parent) - parent = this; - SettingsDialog settingsDialog(m_pluginManager, group, page, parent); - settingsDialog.show(); - bool ok = settingsDialog.execDialog(); - if (ok) - Q_EMIT m_coreImpl->changeSettings(); - return ok; -} - -void MainWindow::about() -{ - QMessageBox::about(this, tr("About Object Viewer Qt"), - tr("

Object Viewer Qt

" - "

Ryzom Core team

Compiled on %1 %2").arg(__DATE__).arg(__TIME__)); -} - -void MainWindow::updateContext(Core::IContext *context) -{ - m_undoGroup->setActiveStack(context->undoStack()); -} - -void MainWindow::closeEvent(QCloseEvent *event) -{ - QList listeners = m_pluginManager->getObjects(); - Q_FOREACH(ICoreListener *listener, listeners) - { - if (!listener->closeMainWindow()) - { - event->ignore(); - return; - } - } - Q_EMIT m_coreImpl->closeMainWindow(); - - writeSettings(); - event->accept(); -} - -void MainWindow::createActions() -{ - m_newAction = new QAction(tr("&New"), this); - m_newAction->setIcon(QIcon(Constants::ICON_NEW)); - m_newAction->setShortcut(QKeySequence::New); - menuManager()->registerAction(m_newAction, Constants::NEW); - connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile())); - m_newAction->setEnabled(false); - - m_openAction = new QAction(tr("&Open..."), this); - m_openAction->setIcon(QIcon(Constants::ICON_OPEN)); - m_openAction->setShortcut(QKeySequence::Open); - m_openAction->setStatusTip(tr("Open an existing file")); - menuManager()->registerAction(m_openAction, Constants::OPEN); - connect(m_openAction, SIGNAL(triggered()), this, SLOT(open())); - - m_saveAction = new QAction(tr("&Save"), this); - m_saveAction->setIcon(QIcon(Constants::ICON_SAVE)); - m_saveAction->setShortcut(QKeySequence::Save); - menuManager()->registerAction(m_saveAction, Constants::SAVE); - connect(m_saveAction, SIGNAL(triggered()), this, SLOT(save())); - m_saveAction->setEnabled(false); - - m_saveAsAction = new QAction(tr("Save &As..."), this); - m_saveAsAction->setIcon(QIcon(Constants::ICON_SAVE_AS)); - m_saveAsAction->setShortcut(QKeySequence::SaveAs); - menuManager()->registerAction(m_saveAsAction, Constants::SAVE_AS); - connect(m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); - m_saveAsAction->setEnabled(false); - - m_saveAllAction = new QAction(tr("&Save A&ll"), this); - m_saveAllAction->setShortcut(QKeySequence::SelectAll); - menuManager()->registerAction(m_saveAllAction, Constants::SAVE_ALL); - connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll())); - m_saveAllAction->setEnabled(false); - - m_closeAction = new QAction(tr("Close"), this); - m_closeAction->setShortcut(QKeySequence::Close); - menuManager()->registerAction(m_closeAction, Constants::CLOSE); - connect(m_closeAction, SIGNAL(triggered()), this, SLOT(closeDocument())); - m_closeAction->setEnabled(false); - - m_exitAction = new QAction(tr("E&xit"), this); - m_exitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); - m_exitAction->setStatusTip(tr("Exit the application")); - menuManager()->registerAction(m_exitAction, Constants::EXIT); - connect(m_exitAction, SIGNAL(triggered()), this, SLOT(close())); - - m_cutAction = new QAction(tr("Cu&t"), this); - m_cutAction->setShortcut(QKeySequence::Cut); - menuManager()->registerAction(m_cutAction, Constants::CUT); - connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cut())); - m_cutAction->setEnabled(false); - - m_copyAction = new QAction(tr("&Copy"), this); - m_copyAction->setShortcut(QKeySequence::Copy); - menuManager()->registerAction(m_copyAction, Constants::COPY); - connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copy())); - m_copyAction->setEnabled(false); - - m_pasteAction = new QAction(tr("&Paste"), this); - m_pasteAction->setShortcut(QKeySequence::Paste); - menuManager()->registerAction(m_pasteAction, Constants::PASTE); - connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste())); - m_pasteAction->setEnabled(false); - - m_delAction = new QAction(tr("&Delete"), this); - m_delAction->setShortcut(QKeySequence::Delete); - menuManager()->registerAction(m_delAction, Constants::DEL); - connect(m_delAction, SIGNAL(triggered()), this, SLOT(del())); - m_delAction->setEnabled(false); - - m_selectAllAction = new QAction(tr("Select &All"), this); - m_selectAllAction->setShortcut(QKeySequence::SelectAll); - menuManager()->registerAction(m_selectAllAction, Constants::SELECT_ALL); - connect(m_selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll())); - m_selectAllAction->setEnabled(false); - - m_findAction = new QAction(tr("&Find"), this); - m_findAction->setShortcut(QKeySequence::Find); - menuManager()->registerAction(m_findAction, Constants::FIND); - connect(m_findAction, SIGNAL(triggered()), this, SLOT(find())); - m_findAction->setEnabled(false); - - m_gotoAction = new QAction(tr("&Go To.."), this); - m_gotoAction->setShortcut(QKeySequence(tr("Ctrl+G"))); - menuManager()->registerAction(m_gotoAction, Constants::GOTO_POS); - connect(m_gotoAction, SIGNAL(triggered()), this, SLOT(gotoPos())); - m_gotoAction->setEnabled(false); - - m_fullscreenAction = new QAction(tr("Fullscreen"), this); - m_fullscreenAction->setCheckable(true); - m_fullscreenAction->setShortcut(QKeySequence(tr("Ctrl+Shift+F11"))); - menuManager()->registerAction(m_fullscreenAction, Constants::TOGGLE_FULLSCREEN); - connect(m_fullscreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool))); - - m_settingsAction = new QAction(tr("&Settings"), this); - m_settingsAction->setIcon(QIcon(":/images/preferences.png")); - m_settingsAction->setShortcut(QKeySequence::Preferences); - m_settingsAction->setStatusTip(tr("Open the settings dialog")); - menuManager()->registerAction(m_settingsAction, Constants::SETTINGS); - connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog())); - - m_aboutAction = new QAction(tr("&About"), this); - m_aboutAction->setStatusTip(tr("Show the application's About box")); - menuManager()->registerAction(m_aboutAction, Constants::ABOUT); - connect(m_aboutAction, SIGNAL(triggered()), this, SLOT(about())); - - m_aboutQtAction = new QAction(tr("About &Qt"), this); - m_aboutQtAction->setStatusTip(tr("Show the Qt library's About box")); - menuManager()->registerAction(m_aboutQtAction, Constants::ABOUT_QT); - connect(m_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); - - m_pluginViewAction = new QAction(tr("About &Plugins"), this); - m_pluginViewAction->setStatusTip(tr("Show the plugin view dialog")); - menuManager()->registerAction(m_pluginViewAction, Constants::ABOUT_PLUGINS); - connect(m_pluginViewAction, SIGNAL(triggered()), m_pluginView, SLOT(show())); - -#ifdef Q_WS_MAC - m_exitAction->setMenuRole(QAction::QuitRole); - m_settingsAction->setMenuRole(QAction::PreferencesRole); - m_aboutAction->setMenuRole(QAction::AboutRole); - m_aboutQtAction->setMenuRole(QAction::AboutQtRole); - m_pluginViewAction->setMenuRole(QAction::ApplicationSpecificRole); -#endif -} - -void MainWindow::createMenus() -{ - m_fileMenu = m_menuBar->addMenu(tr("&File")); - menuManager()->registerMenu(m_fileMenu, Constants::M_FILE); - m_fileMenu->addAction(m_newAction); - m_fileMenu->addAction(m_openAction); - m_fileMenu->addSeparator(); - m_fileMenu->addAction(m_saveAction); - m_fileMenu->addAction(m_saveAsAction); - m_fileMenu->addAction(m_saveAllAction); - m_fileMenu->addAction(m_closeAction); - m_fileMenu->addSeparator(); - - m_recentFilesMenu = m_fileMenu->addMenu(tr("Recent &Files")); - m_recentFilesMenu->setEnabled(false); - menuManager()->registerMenu(m_recentFilesMenu, Constants::M_FILE_RECENTFILES); - - m_fileMenu->addSeparator(); - m_fileMenu->addAction(m_exitAction); - - m_editMenu = m_menuBar->addMenu(tr("&Edit")); - QAction *undoAction = m_undoGroup->createUndoAction(this); - menuManager()->registerAction(undoAction, Constants::UNDO); - undoAction->setIcon(QIcon(Constants::ICON_UNDO)); - undoAction->setShortcut(QKeySequence::Undo); - QAction *redoAction = m_undoGroup->createRedoAction(this); - menuManager()->registerAction(redoAction, Constants::REDO); - redoAction->setIcon(QIcon(Constants::ICON_REDO)); - redoAction->setShortcut(QKeySequence::Redo); - m_editMenu->addAction(undoAction); - m_editMenu->addAction(redoAction); - - m_editMenu->addSeparator(); - m_editMenu->addAction(m_cutAction); - m_editMenu->addAction(m_copyAction); - m_editMenu->addAction(m_pasteAction); - m_editMenu->addAction(m_delAction); - m_editMenu->addSeparator(); - m_editMenu->addAction(m_selectAllAction); - m_editMenu->addSeparator(); - m_editMenu->addAction(m_findAction); - m_editMenu->addAction(m_gotoAction); - menuManager()->registerMenu(m_editMenu, Constants::M_EDIT); - - m_viewMenu = m_menuBar->addMenu(tr("&View")); - m_viewMenu->addAction(m_fullscreenAction); - m_viewMenu->addAction(m_dockWidget->toggleViewAction()); - menuManager()->registerMenu(m_viewMenu, Constants::M_VIEW); - - m_toolsMenu = m_menuBar->addMenu(tr("&Tools")); - menuManager()->registerMenu(m_toolsMenu, Constants::M_TOOLS); - - m_sheetMenu = m_toolsMenu->addMenu(tr("&Sheet")); - menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); - -// m_toolsMenu->addSeparator(); - - m_toolsMenu->addAction(m_settingsAction); - - m_menuBar->addSeparator(); - - m_helpMenu = m_menuBar->addMenu(tr("&Help")); - menuManager()->registerMenu(m_helpMenu, Constants::M_HELP); - m_helpMenu->addAction(m_aboutAction); - m_helpMenu->addAction(m_aboutQtAction); - m_helpMenu->addAction(m_pluginViewAction); -} - -void MainWindow::createStatusBar() -{ - statusBar()->showMessage(tr("StatusReady")); -} - -void MainWindow::createDialogs() -{ - m_pluginView = new PluginView(m_pluginManager, this); - - // Create undo/redo command list - m_dockWidget = new QDockWidget("Command List", this); - m_dockWidget->setObjectName(QString::fromUtf8("UndoRedoCommandDockWidget")); - QUndoView *undoView = new QUndoView(m_undoGroup, m_dockWidget); - m_dockWidget->setWidget(undoView); - addDockWidget(Qt::RightDockWidgetArea, m_dockWidget); -} - -void MainWindow::readSettings() -{ - m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - restoreState(m_settings->value(Constants::MAIN_WINDOW_STATE).toByteArray()); - restoreGeometry(m_settings->value(Constants::MAIN_WINDOW_GEOMETRY).toByteArray()); - m_settings->endGroup(); -} - -void MainWindow::writeSettings() -{ - m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); - m_settings->setValue(Constants::MAIN_WINDOW_STATE, saveState()); - m_settings->setValue(Constants::MAIN_WINDOW_GEOMETRY, saveGeometry()); - m_settings->endGroup(); -} - -} /* namespace Core */ - -/* end of file */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h deleted file mode 100644 index d258a5eba..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/main_window.h +++ /dev/null @@ -1,147 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef MAIN_WINDOW_H -#define MAIN_WINDOW_H - -// Project includes -#include "../../extension_system/iplugin_manager.h" -#include "plugin_view_dialog.h" - -// STL includes - -// Qt includes -#include -#include -#include - -namespace Core -{ -class CSettingsDialog; -class CorePlugin; -class IContext; -class MenuManager; -class ContextManager; -class CoreImpl; - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); - ~MainWindow(); - - bool initialize(QString *errorString); - void extensionsInitialized(); - - MenuManager *menuManager() const; - ContextManager *contextManager() const; - QSettings *settings() const; - QUndoGroup *undoGroup() const; - - ExtensionSystem::IPluginManager *pluginManager() const; - - void addContextObject(IContext *context); - void removeContextObject(IContext *context); - -public Q_SLOTS: - bool showOptionsDialog(const QString &group = QString(), - const QString &page = QString(), - QWidget *parent = 0); - void updateContext(Core::IContext *context); - -private Q_SLOTS: - void open(); - void newFile(); - void save(); - void saveAs(); - void saveAll(); - void closeDocument(); - void cut(); - void copy(); - void paste(); - void del(); - void find(); - void gotoPos(); - void setFullScreen(bool enabled); - void about(); - -protected: - virtual void closeEvent(QCloseEvent *event); - -private: - void createActions(); - void createMenus(); - void createStatusBar(); - void createDialogs(); - - void readSettings(); - void writeSettings(); - - ExtensionSystem::IPluginManager *m_pluginManager; - PluginView *m_pluginView; - MenuManager *m_menuManager; - ContextManager *m_contextManager; - CoreImpl *m_coreImpl; - - QPalette m_originalPalette; - QString m_lastDir; - - QDockWidget *m_dockWidget; - QUndoGroup *m_undoGroup; - QSettings *m_settings; - - QTimer *m_mainTimer; - QTimer *m_statusBarTimer; - - QTabWidget *m_tabWidget; - - QMenu *m_fileMenu; - QMenu *m_recentFilesMenu; - QMenu *m_editMenu; - QMenu *m_viewMenu; - QMenu *m_toolsMenu; - QMenu *m_helpMenu; - QMenuBar *m_menuBar; - QMenu *m_sheetMenu; - - QAction *m_newAction; - QAction *m_openAction; - QAction *m_saveAction; - QAction *m_saveAsAction; - QAction *m_saveAllAction; - QAction *m_closeAction; - QAction *m_exitAction; - QAction *m_cutAction; - QAction *m_copyAction; - QAction *m_pasteAction; - QAction *m_delAction; - QAction *m_selectAllAction; - QAction *m_findAction; - QAction *m_gotoAction; - QAction *m_fullscreenAction; - QAction *m_settingsAction; - QAction *m_pluginViewAction; - QAction *m_aboutAction; - QAction *m_aboutQtAction; - -};/* class MainWindow */ - -} /* namespace Core */ - -#endif // MAIN_WINDOW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp deleted file mode 100644 index 3e6272f0a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "menu_manager.h" - -// NeL includes -#include - -namespace Core -{ -struct MenuManagerPrivate -{ - MenuManagerPrivate(): m_menuBar(0) {} - QMenuBar *m_menuBar; - typedef QHash IdMenuMap; - IdMenuMap m_menuMap; - typedef QHash IdActionMap; - IdActionMap m_actionMap; -}; - -MenuManager::MenuManager(QMenuBar *menuBar, QObject *parent) - : QObject(parent), - d(new MenuManagerPrivate()) -{ - d->m_menuBar = menuBar; -} - -MenuManager::~MenuManager() -{ - d->m_menuMap.clear(); - delete d; -} - -void MenuManager::registerMenu(QMenu *menu, const QString &id) -{ - menu->setObjectName(id); - d->m_menuMap.insert(id, menu); -} - -void MenuManager::registerAction(QAction *action, const QString &id) -{ - action->setObjectName(id); - d->m_actionMap.insert(id, action); -} - -QMenu *MenuManager::menu(const QString &id) const -{ - QMenu *result = 0; - if (!d->m_menuMap.contains(id)) - nlwarning("QMenu %s not found", id.toUtf8().constData()); - else - result = d->m_menuMap.value(id); - return result; -} - -QAction *MenuManager::action(const QString &id) const -{ - QAction *result = 0; - if (!d->m_actionMap.contains(id)) - nlwarning("QAction %s not found", id.toUtf8().constData()); - else - result = d->m_actionMap.value(id); - return result; -} - -void MenuManager::unregisterMenu(const QString &id) -{ - d->m_menuMap.remove(id); -} - -void MenuManager::unregisterAction(const QString &id) -{ - d->m_actionMap.remove(id); -} - -QMenuBar *MenuManager::menuBar() const -{ - return d->m_menuBar; -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h deleted file mode 100644 index fd6af8f3a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/menu_manager.h +++ /dev/null @@ -1,67 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef MENU_MANAGER_H -#define MENU_MANAGER_H - -// Project includes -#include "core_global.h" - -// Qt includes -#include -#include -#include -#include -#include -#include - -namespace Core -{ -struct MenuManagerPrivate; - -/* -@interface MenuManager -@brief The MenuManager provide the interface for registration of menus and menu item. -@details The MenuManager provides centralized access to menus and menu items. -All menus and menu items should be registered in the MenuManager. -*/ -class CORE_EXPORT MenuManager: public QObject -{ - Q_OBJECT - -public: - MenuManager(QMenuBar *menuBar, QObject *parent = 0); - virtual ~MenuManager(); - - void registerMenu(QMenu *menu, const QString &id); - void registerAction(QAction *action, const QString &id); - - QMenu *menu(const QString &id) const; - QAction *action(const QString &id) const; - - void unregisterMenu(const QString &id); - void unregisterAction(const QString &id); - - QMenuBar *menuBar() const; -private: - - MenuManagerPrivate *d; -}; - -} // namespace Core - -#endif // MENU_MANAGER_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml deleted file mode 100644 index 2f5d6e9a8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/ovqt_plugin_core.xml +++ /dev/null @@ -1,7 +0,0 @@ - - ovqt_plugin_core - Core - 0.8 - Ryzom Core - Core plugin. - \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp deleted file mode 100644 index 175902d39..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "plugin_view_dialog.h" -#include "core_constants.h" - -#include "nel/misc/debug.h" - -// Qt includes -#include -#include -#include -#include - -// Project includes -#include "../../extension_system/iplugin_spec.h" -#include "../../extension_system/iplugin_manager.h" - -namespace Core -{ - -PluginView::PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) - : QDialog(parent), - m_checkStateColumn(0) -{ - m_ui.setupUi(this); - m_pluginManager = pluginManager; - - connect(m_pluginManager, SIGNAL(pluginsChanged()), this, SLOT(updateList())); - connect(this, SIGNAL(accepted()), this, SLOT(updateSettings())); - - // WhiteList is list of plugins which can not disable. - m_whiteList << Constants::OVQT_CORE_PLUGIN; - updateList(); -} - -PluginView::~PluginView() -{ -} - -void PluginView::updateList() -{ - static QIcon okIcon = QApplication::style()->standardIcon(QStyle::SP_DialogApplyButton); - static QIcon errorIcon = QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton); - static QIcon notLoadedIcon = QApplication::style()->standardIcon(QStyle::SP_DialogResetButton); - - m_specToItem.clear(); - - QList items; - Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) - { - QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() - << spec->name() - << QString("%1").arg(spec->version()) - << spec->vendor() - << QDir::toNativeSeparators(spec->filePath())); - - bool ok = !spec->hasError(); - QIcon icon = ok ? okIcon : errorIcon; - if (ok && (spec->state() != ExtensionSystem::State::Running)) - icon = notLoadedIcon; - - item->setIcon(m_checkStateColumn, icon); - - if (!m_whiteList.contains(spec->name())) - item->setCheckState(m_checkStateColumn, spec->isEnabled() ? Qt::Checked : Qt::Unchecked); - - items.append(item); - m_specToItem.insert(spec, item); - } - - m_ui.pluginTreeWidget->clear(); - if (!items.isEmpty()) - m_ui.pluginTreeWidget->addTopLevelItems(items); - - m_ui.pluginTreeWidget->resizeColumnToContents(m_checkStateColumn); -} - -void PluginView::updateSettings() -{ - Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) - { - if (m_specToItem.contains(spec) && (!m_whiteList.contains(spec->name()))) - { - QTreeWidgetItem *item = m_specToItem.value(spec); - if (item->checkState(m_checkStateColumn) == Qt::Checked) - spec->setEnabled(true); - else - spec->setEnabled(false); - } - } -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h deleted file mode 100644 index aae16749d..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.h +++ /dev/null @@ -1,58 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PLUGIN_VIEW_H -#define PLUGIN_VIEW_H - -#include "ui_plugin_view_dialog.h" - -#include -#include - -namespace ExtensionSystem -{ -class IPluginManager; -class IPluginSpec; -} - -namespace Core -{ - -class PluginView: public QDialog -{ - Q_OBJECT - -public: - PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); - ~PluginView(); - -private Q_SLOTS: - void updateList(); - void updateSettings(); - -private: - - const int m_checkStateColumn; - QMap m_specToItem; - QStringList m_whiteList; - ExtensionSystem::IPluginManager *m_pluginManager; - Ui::PluginView m_ui; -}; /* class PluginView */ - -} /* namespace Core */ - -#endif // PLUGIN_VIEW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui deleted file mode 100644 index 9d7d395be..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/plugin_view_dialog.ui +++ /dev/null @@ -1,135 +0,0 @@ - - - PluginView - - - - 0 - 0 - 756 - 296 - - - - About plugins - - - true - - - - - - true - - - 0 - - - false - - - true - - - false - - - true - - - - Name - - - - - Version - - - - - Vendor - - - - - Location - - - - - - - - false - - - Details - - - - - - - false - - - Error details - - - - - - - Qt::Horizontal - - - - 427 - 20 - - - - - - - - Close - - - - - - - false - - - All objects list - - - - - - - - - - - closePushButton - clicked() - PluginView - accept() - - - 620 - 232 - - - 507 - 226 - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp deleted file mode 100644 index 115203ded..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#include "qtwin.h" -#include -#include -#include -#include -#include - -#ifdef Q_WS_WIN - -#include - -// Blur behind data structures -#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified -#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified -#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified -#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message - -typedef struct _DWM_BLURBEHIND -{ - DWORD dwFlags; - BOOL fEnable; - HRGN hRgnBlur; - BOOL fTransitionOnMaximized; -} DWM_BLURBEHIND, *PDWM_BLURBEHIND; - -typedef struct _MARGINS -{ - int cxLeftWidth; - int cxRightWidth; - int cyTopHeight; - int cyBottomHeight; -} MARGINS, *PMARGINS; - -typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL *pfEnabled); -typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset); -typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND *pBlurBehind); -typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); - -static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; -static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; -static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; -static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; - - -/* - * Internal helper class that notifies windows if the - * DWM compositing state changes and updates the widget - * flags correspondingly. - */ -class WindowNotifier : public QWidget -{ -public: - WindowNotifier() - { - winId(); - } - void addWidget(QWidget *widget) - { - widgets.append(widget); - } - void removeWidget(QWidget *widget) - { - widgets.removeAll(widget); - } - bool winEvent(MSG *message, long *result); - -private: - QWidgetList widgets; -}; - -static bool resolveLibs() -{ - if (!pDwmIsCompositionEnabled) - { - QLibrary dwmLib(QString::fromAscii("dwmapi")); - pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); - pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); - pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); - pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); - } - return pDwmIsCompositionEnabled != 0; -} - -#endif - -/*! - * Chekcs and returns true if Windows DWM composition - * is currently enabled on the system. - * - * To get live notification on the availability of - * this feature, you will currently have to - * reimplement winEvent() on your widget and listen - * for the WM_DWMCOMPOSITIONCHANGED event to occur. - * - */ -bool QtWin::isCompositionEnabled() -{ -#ifdef Q_WS_WIN - if (resolveLibs()) - { - HRESULT hr = S_OK; - BOOL isEnabled = false; - hr = pDwmIsCompositionEnabled(&isEnabled); - if (SUCCEEDED(hr)) - return isEnabled; - } -#endif - return false; -} - -/*! - * Enables Blur behind on a Widget. - * - * \a enable tells if the blur should be enabled or not - */ -bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable) -{ - Q_ASSERT(widget); - bool result = false; -#ifdef Q_WS_WIN - if (resolveLibs()) - { - DWM_BLURBEHIND bb = {0}; - HRESULT hr = S_OK; - bb.fEnable = enable; - bb.dwFlags = DWM_BB_ENABLE; - bb.hRgnBlur = NULL; - widget->setAttribute(Qt::WA_TranslucentBackground, enable); - widget->setAttribute(Qt::WA_NoSystemBackground, enable); - hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb); - if (SUCCEEDED(hr)) - { - result = true; - windowNotifier()->addWidget(widget); - } - } -#endif - return result; -} - -/*! - * ExtendFrameIntoClientArea. - * - * This controls the rendering of the frame inside the window. - * Note that passing margins of -1 (the default value) will completely - * remove the frame from the window. - * - * \note you should not call enableBlurBehindWindow before calling - * this functions - * - * \a enable tells if the blur should be enabled or not - */ -bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom) -{ - - Q_ASSERT(widget); - Q_UNUSED(left); - Q_UNUSED(top); - Q_UNUSED(right); - Q_UNUSED(bottom); - - bool result = false; -#ifdef Q_WS_WIN - if (resolveLibs()) - { - QLibrary dwmLib(QString::fromAscii("dwmapi")); - HRESULT hr = S_OK; - MARGINS m = {left, top, right, bottom}; - hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m); - if (SUCCEEDED(hr)) - { - result = true; - windowNotifier()->addWidget(widget); - } - widget->setAttribute(Qt::WA_TranslucentBackground, result); - } -#endif - return result; -} - -/*! - * Returns the current colorizationColor for the window. - * - * \a enable tells if the blur should be enabled or not - */ -QColor QtWin::colorizatinColor() -{ - QColor resultColor = QApplication::palette().window().color(); - -#ifdef Q_WS_WIN - if (resolveLibs()) - { - DWORD color = 0; - BOOL opaque = FALSE; - QLibrary dwmLib(QString::fromAscii("dwmapi")); - HRESULT hr = S_OK; - hr = pDwmGetColorizationColor(&color, &opaque); - if (SUCCEEDED(hr)) - resultColor = QColor(color); - } -#endif - return resultColor; -} - -#ifdef Q_WS_WIN -WindowNotifier *QtWin::windowNotifier() -{ - static WindowNotifier *windowNotifierInstance = 0; - if (!windowNotifierInstance) - windowNotifierInstance = new WindowNotifier; - return windowNotifierInstance; -} - - -/* Notify all enabled windows that the DWM state changed */ -bool WindowNotifier::winEvent(MSG *message, long *result) -{ - if (message && message->message == WM_DWMCOMPOSITIONCHANGED) - { - bool compositionEnabled = QtWin::isCompositionEnabled(); - Q_FOREACH(QWidget * widget, widgets) - { - if (widget) - { - widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); - } - widget->update(); - } - } - return QWidget::winEvent(message, result); -} -#endif diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h deleted file mode 100644 index 5692a34fb..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/qtwin.h +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#ifndef QTWIN_H -#define QTWIN_H - -#include -#include -/** - * This is a helper class for using the Desktop Window Manager - * functionality on Windows 7 and Windows Vista. On other platforms - * these functions will simply not do anything. - */ - -class WindowNotifier; - -class QtWin -{ -public: - static bool enableBlurBehindWindow(QWidget *widget, bool enable = true); - static bool extendFrameIntoClientArea(QWidget *widget, - int left = -1, int top = -1, - int right = -1, int bottom = -1); - static bool isCompositionEnabled(); - static QColor colorizatinColor(); - -private: - static WindowNotifier *windowNotifier(); -}; - -#endif // QTWIN_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp deleted file mode 100644 index e76d6c796..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "search_paths_settings_page.h" -#include "core_constants.h" -#include "icore.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include - -namespace Core -{ - -QString lastDir = "."; - -SearchPathsSettingsPage::SearchPathsSettingsPage(bool recurse, QObject *parent) - : IOptionsPage(parent), - m_recurse(recurse), - m_page(0) -{ -} - -SearchPathsSettingsPage::~SearchPathsSettingsPage() -{ -} - -QString SearchPathsSettingsPage::id() const -{ - if (m_recurse) - return QLatin1String("search_recurse_paths"); - else - return QLatin1String("search_paths"); -} - -QString SearchPathsSettingsPage::trName() const -{ - if (m_recurse) - return tr("Search Recurse Paths"); - else - return tr("Search Paths"); -} - -QString SearchPathsSettingsPage::category() const -{ - return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); -} - -QString SearchPathsSettingsPage::trCategory() const -{ - return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); -} - -QIcon SearchPathsSettingsPage::categoryIcon() const -{ - return QIcon(); -} - -QWidget *SearchPathsSettingsPage::createPage(QWidget *parent) -{ - m_page = new QWidget(parent); - m_ui.setupUi(m_page); - - readSettings(); - checkEnabledButton(); - connect(m_ui.addToolButton, SIGNAL(clicked()), this, SLOT(addPath())); - connect(m_ui.removeToolButton, SIGNAL(clicked()), this, SLOT(delPath())); - connect(m_ui.upToolButton, SIGNAL(clicked()), this, SLOT(upPath())); - connect(m_ui.downToolButton, SIGNAL(clicked()), this, SLOT(downPath())); - connect(m_ui.resetToolButton, SIGNAL(clicked()), m_ui.pathsListWidget, SLOT(clear())); - return m_page; -} - -void SearchPathsSettingsPage::apply() -{ - writeSettings(); - applySearchPaths(); -} - -void SearchPathsSettingsPage::finish() -{ - delete m_page; - m_page = 0; -} - -void SearchPathsSettingsPage::applySearchPaths() -{ - QStringList paths, remapExt; - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - if (m_recurse) - paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); - else - paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); - - remapExt = settings->value(Core::Constants::REMAP_EXTENSIONS).toStringList(); - settings->endGroup(); - - for (int i = 1; i < remapExt.size(); i += 2) - NLMISC::CPath::remapExtension(remapExt.at(i - 1).toUtf8().constData(), remapExt.at(i).toUtf8().constData(), true); - - Q_FOREACH(QString path, paths) - { - NLMISC::CPath::addSearchPath(path.toUtf8().constData(), m_recurse, false); - } -} - -void SearchPathsSettingsPage::addPath() -{ - QString newPath = QFileDialog::getExistingDirectory(m_page, "", lastDir); - if (!newPath.isEmpty()) - { - QListWidgetItem *newItem = new QListWidgetItem; - newItem->setText(newPath); - newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - m_ui.pathsListWidget->addItem(newItem); - lastDir = newPath; - } - - checkEnabledButton(); -} - -void SearchPathsSettingsPage::delPath() -{ - QListWidgetItem *removeItem = m_ui.pathsListWidget->takeItem(m_ui.pathsListWidget->currentRow()); - if (!removeItem) - delete removeItem; - - checkEnabledButton(); -} - -void SearchPathsSettingsPage::upPath() -{ - int currentRow = m_ui.pathsListWidget->currentRow(); - if (!(currentRow == 0)) - { - QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); - m_ui.pathsListWidget->insertItem(--currentRow, item); - m_ui.pathsListWidget->setCurrentRow(currentRow); - } -} - -void SearchPathsSettingsPage::downPath() -{ - int currentRow = m_ui.pathsListWidget->currentRow(); - if (!(currentRow == m_ui.pathsListWidget->count()-1)) - { - QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); - m_ui.pathsListWidget->insertItem(++currentRow, item); - m_ui.pathsListWidget->setCurrentRow(currentRow); - } -} - -void SearchPathsSettingsPage::readSettings() -{ - QStringList paths; - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - if (m_recurse) - paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); - else - paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); - settings->endGroup(); - Q_FOREACH(QString path, paths) - { - QListWidgetItem *newItem = new QListWidgetItem; - newItem->setText(path); - newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); - m_ui.pathsListWidget->addItem(newItem); - } -} - -void SearchPathsSettingsPage::writeSettings() -{ - QStringList paths; - for (int i = 0; i < m_ui.pathsListWidget->count(); ++i) - paths << m_ui.pathsListWidget->item(i)->text(); - - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Core::Constants::DATA_PATH_SECTION); - if (m_recurse) - settings->setValue(Core::Constants::RECURSIVE_SEARCH_PATHS, paths); - else - settings->setValue(Core::Constants::SEARCH_PATHS, paths); - settings->endGroup(); - settings->sync(); -} - -void SearchPathsSettingsPage::checkEnabledButton() -{ - bool bEnabled = true; - if (m_ui.pathsListWidget->count() == 0) - bEnabled = false; - - m_ui.removeToolButton->setEnabled(bEnabled); - m_ui.upToolButton->setEnabled(bEnabled); - m_ui.downToolButton->setEnabled(bEnabled); -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h deleted file mode 100644 index c45b29571..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.h +++ /dev/null @@ -1,74 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef SEARCH_PATHS_SETTINGS_PAGE_H -#define SEARCH_PATHS_SETTINGS_PAGE_H - -#include - -#include "ioptions_page.h" - -#include "ui_search_paths_settings_page.h" - -class QWidget; - -namespace Core -{ -/** -@class SearchPathsSettingsPage -*/ -class SearchPathsSettingsPage : public Core::IOptionsPage -{ - Q_OBJECT - -public: - explicit SearchPathsSettingsPage(bool recurse, QObject *parent = 0); - ~SearchPathsSettingsPage(); - - QString id() const; - QString trName() const; - QString category() const; - QString trCategory() const; - QIcon categoryIcon() const; - QWidget *createPage(QWidget *parent); - - void apply(); - void finish(); - - // Set of the search paths(not recursive) and the remap extensions (loading from settings file) - void applySearchPaths(); - -private Q_SLOTS: - void addPath(); - void delPath(); - void upPath(); - void downPath(); - -private: - void readSettings(); - void writeSettings(); - void checkEnabledButton(); - - bool m_recurse; - QWidget *m_page; - Ui::SearchPathsSettingsPage m_ui; -}; - -} // namespace Core - -#endif // SEARCH_PATHS_SETTINGS_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui deleted file mode 100644 index cf47314b8..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/search_paths_settings_page.ui +++ /dev/null @@ -1,198 +0,0 @@ - - - SearchPathsSettingsPage - - - - 0 - 0 - 431 - 285 - - - - Form - - - - 6 - - - 3 - - - - - Search paths - - - - - - - Qt::Horizontal - - - - 228 - 20 - - - - - - - - 3 - - - - - - 0 - 0 - - - - Add - - - - - - - :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png - - - - 20 - 20 - - - - true - - - - - - - - 0 - 0 - - - - Delete - - - - - - - :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png - - - - 20 - 20 - - - - true - - - - - - - - 0 - 0 - - - - Up - - - - - - - :/core/icons/ic_nel_up_item.png:/core/icons/ic_nel_up_item.png - - - - 20 - 20 - - - - true - - - - - - - - 0 - 0 - - - - Down - - - - - - - :/core/icons/ic_nel_down_item.png:/core/icons/ic_nel_down_item.png - - - - 20 - 20 - - - - true - - - - - - - Reset - - - - - - - :/core/icons/ic_nel_reset_all.png:/core/icons/ic_nel_reset_all.png - - - - 20 - 20 - - - - true - - - - - - - - - - - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp deleted file mode 100644 index 4b7bbac3a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.cpp +++ /dev/null @@ -1,182 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "settings_dialog.h" -#include "ioptions_page.h" - -// Qt includes -#include -#include - -struct PageData -{ - int index; - QString category; - QString id; -}; - -Q_DECLARE_METATYPE(PageData); - -namespace Core -{ -SettingsDialog::SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, - const QString &categoryId, - const QString &pageId, - QWidget *parent) - : QDialog(parent), - m_applied(false) -{ - m_ui.setupUi(this); - - m_plugMan = pluginManager; - - QString initialCategory = categoryId; - QString initialPage = pageId; - - m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - - connect(m_ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); - - m_ui.splitter->setCollapsible(1, false); - m_ui.pageTree->header()->setVisible(false); - - connect(m_ui.pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(pageSelected())); - - QMap categories; - - QList pages = m_plugMan->getObjects(); - - int index = 0; - Q_FOREACH(IOptionsPage *page, pages) - { - PageData pageData; - pageData.index = index; - pageData.category = page->category(); - pageData.id = page->id(); - - QTreeWidgetItem *item = new QTreeWidgetItem; - item->setText(0, page->trName()); - item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - - QStringList categoriesId = page->category().split(QLatin1Char('|')); - QStringList trCategories = page->trCategory().split(QLatin1Char('|')); - QString currentCategory = categoriesId.at(0); - - QTreeWidgetItem *treeitem; - if (!categories.contains(currentCategory)) - { - treeitem = new QTreeWidgetItem(m_ui.pageTree); - treeitem->setText(0, trCategories.at(0)); - treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - categories.insert(currentCategory, treeitem); - } - - int catCount = 1; - while (catCount < categoriesId.count()) - { - if (!categories.contains(currentCategory + QLatin1Char('|') + categoriesId.at(catCount))) - { - treeitem = new QTreeWidgetItem(categories.value(currentCategory)); - currentCategory += QLatin1Char('|') + categoriesId.at(catCount); - treeitem->setText(0, trCategories.at(catCount)); - treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - categories.insert(currentCategory, treeitem); - } - else - { - currentCategory += QLatin1Char('|') + categoriesId.at(catCount); - } - ++catCount; - } - - categories.value(currentCategory)->addChild(item); - - m_pages.append(page); - m_ui.stackedPages->addWidget(page->createPage(m_ui.stackedPages)); - - if (page->id() == initialPage && currentCategory == initialCategory) - { - m_ui.stackedPages->setCurrentIndex(m_ui.stackedPages->count()); - m_ui.pageTree->setCurrentItem(item); - } - - index++; - } - - QList sizes; - sizes << 150 << 300; - m_ui.splitter->setSizes(sizes); - - m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.pageTree), 0); - m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.layoutWidget), 1); -} - -SettingsDialog::~SettingsDialog() -{ -} - -void SettingsDialog::pageSelected() -{ - QTreeWidgetItem *item = m_ui.pageTree->currentItem(); - PageData data = item->data(0, Qt::UserRole).value(); - int index = data.index; - m_currentCategory = data.category; - m_currentPage = data.id; - m_ui.stackedPages->setCurrentIndex(index); -} - -void SettingsDialog::accept() -{ - m_applied = true; - Q_FOREACH(IOptionsPage *page, m_pages) - { - page->apply(); - page->finish(); - } - done(QDialog::Accepted); -} - -void SettingsDialog::reject() -{ - Q_FOREACH(IOptionsPage *page, m_pages) - page->finish(); - done(QDialog::Rejected); -} - -void SettingsDialog::apply() -{ - Q_FOREACH(IOptionsPage *page, m_pages) - page->apply(); - m_applied = true; -} - -bool SettingsDialog::execDialog() -{ - m_applied = false; - exec(); - return m_applied; -} - -void SettingsDialog::done(int val) -{ - QDialog::done(val); -} - -} /* namespace Core */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h deleted file mode 100644 index 9e1c86444..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.h +++ /dev/null @@ -1,75 +0,0 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SETTINGS_DIALOG_H -#define SETTINGS_DIALOG_H - -#include "ui_settings_dialog.h" - -// Qt includes -#include - -// Project includes -#include "../../extension_system/iplugin_manager.h" - -namespace Core -{ -class IOptionsPage; - -/** -@class CSettingsDialog -@brief Settings dialog -*/ -class SettingsDialog: public QDialog -{ - Q_OBJECT - -public: - SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, - const QString &initialCategory = QString(), - const QString &initialPage = QString(), - QWidget *parent = 0); - - ~SettingsDialog(); - - /// Run the dialog and return true if 'Ok' was choosen or 'Apply' was invoked at least once - bool execDialog(); - -public Q_SLOTS: - void done(int); - -private Q_SLOTS: - void pageSelected(); - void accept(); - void reject(); - void apply(); - -private: - QList m_pages; - bool m_applied; - QString m_currentCategory; - QString m_currentPage; - - ExtensionSystem::IPluginManager *m_plugMan; - - Ui::SettingsDialog m_ui; -}; /* class CSettingsDialog */ - -} /* namespace Core */ - -#endif // SETTINGS_DIALOG_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui deleted file mode 100644 index 8e9780c9a..000000000 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/settings_dialog.ui +++ /dev/null @@ -1,126 +0,0 @@ - - - SettingsDialog - - - - 0 - 0 - 697 - 476 - - - - Settings - - - - :/core/images/preferences.png:/core/images/preferences.png - - - - 6 - - - 9 - - - - - Qt::Horizontal - - - - - 0 - 0 - - - - 1 - - - - 0 - - - - - - - 6 - - - 0 - - - - - - 350 - 250 - - - - - - - - Qt::Horizontal - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - SettingsDialog - accept() - - - 297 - 361 - - - 297 - 193 - - - - - buttonBox - rejected() - SettingsDialog - reject() - - - 297 - 361 - - - 297 - 193 - - - - - diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_generic_settings.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_generic_settings.png deleted file mode 100644 index 799bacb284c7e3e1e41cbaeb538ffe32e21a4b3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5633 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 t_zc8nAU*@}8Hmq7dN2bPDNB8 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 UsoZjLV*mgE07*qoM6N<$g2^9G?f?J) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_up_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_up_item.png deleted file mode 100644 index ee471023e095a1ae11a0f614eb953b727b0b169d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3304 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 Eg5p97)c^nh diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_delete_item.png deleted file mode 100644 index a5a1787d593591f855be9a7eb8da271cc8d8f214..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1496 zcmaKs{XY{30LC|C-c2!W(h#B2QhA@kOt{brn;~tK$;-mn#DM?-zdb>=i zu*@RTd8@_pvUxpuxyoG1>Bsxw?uX}jKHujL_-0@|T~w8{l>h*Ms+%k3&``sHb<81=-~(e+|N^9C&_KHVw5X^3IM3J{S1(sAHJ}8!egC%W4+FY#L`JIX8~B! zIZ7C+< z6bcMhk7Jz$z zt<~^Npzeyeat^;b(tkMW#bRkwb5S`|-P(cZ{!1geIKC7Tzpi^Q9XhN7r*| zh)Tmw?h}4)r(e%EPx*~jbiDn>W9k_F^gyx#1J1b!&uZuD!J$Duh_I|$-B|3)pjcABT`DZr@@$gnJ?g*7niqC zPg~-q=_uM61|+bWZC}wlE4;C-L;LVrU6J(R@D0Z4=p`kt`4==LnW(d8wXiBZND)3NugXyk}j`B>QSp`rx>7I47#1U z_C?Zqn_!w_iq*Q=7#33$KOO+R;CW!bcdn#k;~tqqg>*o8s|#;{%M1@^2B=`1X*QOW z`~~EL<8YMd;Wk~hP%ln9+T{3weTCGPC>#3IdbbgtfSL(^;<-$(&+()%CWY(ZY}rUs zYZ^=Sws7E+dDpj6e_>>!qz;jFg;SMzWx6GvaM=_CJv#h+^qF(IggsR{8BYMQlBT|c zLR(J;=NJUkn>YRLcdDtY?zXt@zIEUuTe=1hEndEU6|7%)i#=`5cs5S}P9Mh=PcJfo z{ZbSwueq|yZyG~GMGk&1;XI&33fgfyu~6eIQgk!Fkv4<^W8F=|9U5oXINb+#fCen_ z{sB?u3Xfi@SxqMAC%ZI%1BJIf0uMiCx!yXz62rndMv z$=6toP8$LinV$s7C|ZjMS5+@W1rn4NxN=o7bmp|tGx-1vXy7V6(LK7Owl1b<1|o_O z>bY9rcsZ;+(mT(U8Vqy|@K*SC7Xeg!@WG?ntw{ZC`G3Vh1-90Bf1vJ=9f)jI$P4Q6YBQ@Z8;^^H#>9pe+1$q6DXU$-5VbBeJ(3kUiuh943T}3C$!G=4Zw&rX zIZx;etQ%$b10W;H`0fD|-g&n~Eq? zJZ zC}pc4u@0qD`7mQX=zMD+8o3Hi#&31p7{mxJ*6-KkigeYIgt}@Xn1a05YyE6U8VHU~ z8PL=CTn*0W$(#-|89Sz`9P!(hY?pOfm^ZQVXfjUeBhD+B#yUg0vkok?_%`$Xq0`=> g{}tB1bjDO$2a)_&SEAML{IoE@&Dj&vfF`E?18{b*hyVZp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png b/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_open.png deleted file mode 100644 index c4992affd19cf3a55bb8ec2f3121e5befa69a55c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4310 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 diff --git a/code/nel/tools/3d/object_viewer_qt/CMakeLists.txt b/code/studio/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/CMakeLists.txt rename to code/studio/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/data/andbasr.ttf b/code/studio/data/andbasr.ttf similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/data/andbasr.ttf rename to code/studio/data/andbasr.ttf diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cdirection_widget.png b/code/studio/doc/html/cdirection_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cdirection_widget.png rename to code/studio/doc/html/cdirection_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cedit_color_widget.png b/code/studio/doc/html/cedit_color_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cedit_color_widget.png rename to code/studio/doc/html/cedit_color_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_float_widget.png b/code/studio/doc/html/cedit_range_float_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_float_widget.png rename to code/studio/doc/html/cedit_range_float_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_int_widget.png b/code/studio/doc/html/cedit_range_int_widget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/cedit_range_int_widget.png rename to code/studio/doc/html/cedit_range_int_widget.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/gui_struct.png b/code/studio/doc/html/gui_struct.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/gui_struct.png rename to code/studio/doc/html/gui_struct.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/html/object_viewer_qt_window.png b/code/studio/doc/html/object_viewer_qt_window.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/html/object_viewer_qt_window.png rename to code/studio/doc/html/object_viewer_qt_window.png diff --git a/code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.bat b/code/studio/doc/make_ovqt_dox.bat similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.bat rename to code/studio/doc/make_ovqt_dox.bat diff --git a/code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.sh b/code/studio/doc/make_ovqt_dox.sh similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/make_ovqt_dox.sh rename to code/studio/doc/make_ovqt_dox.sh diff --git a/code/nel/tools/3d/object_viewer_qt/doc/ovqt.dox b/code/studio/doc/ovqt.dox similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/doc/ovqt.dox rename to code/studio/doc/ovqt.dox diff --git a/code/nel/tools/3d/object_viewer_qt/ovqt_config.h.cmake b/code/studio/ovqt_config.h.cmake similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/ovqt_config.h.cmake rename to code/studio/ovqt_config.h.cmake diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/CMakeLists.txt b/code/studio/src/3rdparty/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/CMakeLists.txt rename to code/studio/src/3rdparty/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/CMakeLists.txt b/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/CMakeLists.txt rename to code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt b/code/studio/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt rename to code/studio/src/3rdparty/qtpropertybrowser/LGPL_EXCEPTION.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 b/code/studio/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 rename to code/studio/src/3rdparty/qtpropertybrowser/LICENSE.GPL3 diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.LGPL b/code/studio/src/3rdparty/qtpropertybrowser/LICENSE.LGPL similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/LICENSE.LGPL rename to code/studio/src/3rdparty/qtpropertybrowser/LICENSE.LGPL diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase b/code/studio/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase rename to code/studio/src/3rdparty/qtpropertybrowser/QtAbstractEditorFactoryBase diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtAbstractPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtBoolPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBrowserItem b/code/studio/src/3rdparty/qtpropertybrowser/QtBrowserItem similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtBrowserItem rename to code/studio/src/3rdparty/qtpropertybrowser/QtBrowserItem diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtButtonPropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtCharEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtCharEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtCharPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCharPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtCharPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtCheckBoxFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtColorEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtColorEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtColorPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtColorPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtColorPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtCursorEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtCursorPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtDateEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtDateEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDatePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtDatePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDatePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtDatePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtDateTimeEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtDateTimePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtDoublePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtDoubleSpinBoxFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtEnumEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtEnumPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtFlagPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtFontEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtFontEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtFontPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtFontPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtFontPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtGroupBoxPropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtGroupPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtIntPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtIntPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtIntPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtIntPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtKeySequenceEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtKeySequencePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLineEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtLineEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLineEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtLineEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtLocalePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtPointFPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtPointPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtPointPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtPointPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtProperty b/code/studio/src/3rdparty/qtpropertybrowser/QtProperty similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtProperty rename to code/studio/src/3rdparty/qtpropertybrowser/QtProperty diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtRectFPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtRectPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtRectPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtRectPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtScrollBarFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtScrollBarFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtScrollBarFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtScrollBarFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtSizeFPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtSizePolicyPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtSizePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSizePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtSizePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSliderFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtSliderFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSliderFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtSliderFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtSpinBoxFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtStringPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtStringPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtStringPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtStringPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimeEditFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtTimeEditFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimeEditFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtTimeEditFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimePropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtTimePropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTimePropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtTimePropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser b/code/studio/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser rename to code/studio/src/3rdparty/qtpropertybrowser/QtTreePropertyBrowser diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory b/code/studio/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory rename to code/studio/src/3rdparty/qtpropertybrowser/QtVariantEditorFactory diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantProperty b/code/studio/src/3rdparty/qtpropertybrowser/QtVariantProperty similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantProperty rename to code/studio/src/3rdparty/qtpropertybrowser/QtVariantProperty diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager b/code/studio/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager rename to code/studio/src/3rdparty/qtpropertybrowser/QtVariantPropertyManager diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/README.TXT b/code/studio/src/3rdparty/qtpropertybrowser/README.TXT similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/README.TXT rename to code/studio/src/3rdparty/qtpropertybrowser/README.TXT diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-arrow.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-busy.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-busy.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-busy.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-busy.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-closedhand.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-cross.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-cross.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-cross.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-cross.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-forbidden.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hand.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hand.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hand.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hand.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-hsplit.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-ibeam.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-openhand.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeall.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeb.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizef.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizeh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-sizev.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-uparrow.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-vsplit.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-wait.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-wait.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-wait.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-wait.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png b/code/studio/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/cursor-whatsthis.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/resetproperty.png b/code/studio/src/3rdparty/qtpropertybrowser/images/resetproperty.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/images/resetproperty.png rename to code/studio/src/3rdparty/qtpropertybrowser/images/resetproperty.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtbuttonpropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.h b/code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qteditorfactory.h rename to code/studio/src/3rdparty/qtpropertybrowser/qteditorfactory.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtgroupboxpropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.pri diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowser.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertybrowserutils_p.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.h b/code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtpropertymanager.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtpropertymanager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h b/code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h rename to code/studio/src/3rdparty/qtpropertybrowser/qttreepropertybrowser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp b/code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp rename to code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.h b/code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/3rdparty/qtpropertybrowser/qtvariantproperty.h rename to code/studio/src/3rdparty/qtpropertybrowser/qtvariantproperty.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/CMakeLists.txt rename to code/studio/src/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/description.h b/code/studio/src/description.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/description.h rename to code/studio/src/description.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin.h b/code/studio/src/extension_system/iplugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin.h rename to code/studio/src/extension_system/iplugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_manager.h rename to code/studio/src/extension_system/iplugin_manager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_spec.h b/code/studio/src/extension_system/iplugin_spec.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/iplugin_spec.h rename to code/studio/src/extension_system/iplugin_spec.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.cpp rename to code/studio/src/extension_system/plugin_manager.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_manager.h rename to code/studio/src/extension_system/plugin_manager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.cpp b/code/studio/src/extension_system/plugin_spec.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.cpp rename to code/studio/src/extension_system/plugin_spec.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.h b/code/studio/src/extension_system/plugin_spec.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/extension_system/plugin_spec.h rename to code/studio/src/extension_system/plugin_spec.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/ic_nel_pill.ico b/code/studio/src/ic_nel_pill.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/ic_nel_pill.ico rename to code/studio/src/ic_nel_pill.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/images/nel_ide_load.png b/code/studio/src/images/nel_ide_load.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/images/nel_ide_load.png rename to code/studio/src/images/nel_ide_load.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/main.cpp b/code/studio/src/main.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/main.cpp rename to code/studio/src/main.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.qrc b/code/studio/src/object_viewer_qt.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.qrc rename to code/studio/src/object_viewer_qt.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.rc b/code/studio/src/object_viewer_qt.rc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/object_viewer_qt.rc rename to code/studio/src/object_viewer_qt.rc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt b/code/studio/src/plugins/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt rename to code/studio/src/plugins/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt b/code/studio/src/plugins/bnp_manager/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/CMakeLists.txt rename to code/studio/src/plugins/bnp_manager/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp b/code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp rename to code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h b/code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_dialog.h rename to code/studio/src/plugins/bnp_manager/bnp_dirtree_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui b/code/studio/src/plugins/bnp_manager/bnp_dirtree_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_dirtree_form.ui rename to code/studio/src/plugins/bnp_manager/bnp_dirtree_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp b/code/studio/src/plugins/bnp_manager/bnp_file.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.cpp rename to code/studio/src/plugins/bnp_manager/bnp_file.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h b/code/studio/src/plugins/bnp_manager/bnp_file.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_file.h rename to code/studio/src/plugins/bnp_manager/bnp_file.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp b/code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.cpp rename to code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h b/code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.h rename to code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui b/code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filelist_dialog.ui rename to code/studio/src/plugins/bnp_manager/bnp_filelist_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp b/code/studio/src/plugins/bnp_manager/bnp_filesystem_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.cpp rename to code/studio/src/plugins/bnp_manager/bnp_filesystem_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h b/code/studio/src/plugins/bnp_manager/bnp_filesystem_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_filesystem_model.h rename to code/studio/src/plugins/bnp_manager/bnp_filesystem_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc b/code/studio/src/plugins/bnp_manager/bnp_manager.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager.qrc rename to code/studio/src/plugins/bnp_manager/bnp_manager.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h b/code/studio/src/plugins/bnp_manager/bnp_manager_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_constants.h rename to code/studio/src/plugins/bnp_manager/bnp_manager_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.cpp rename to code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_plugin.h rename to code/studio/src/plugins/bnp_manager/bnp_manager_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp b/code/studio/src/plugins/bnp_manager/bnp_manager_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.cpp rename to code/studio/src/plugins/bnp_manager/bnp_manager_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h b/code/studio/src/plugins/bnp_manager/bnp_manager_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.h rename to code/studio/src/plugins/bnp_manager/bnp_manager_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui b/code/studio/src/plugins/bnp_manager/bnp_manager_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_manager_window.ui rename to code/studio/src/plugins/bnp_manager/bnp_manager_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp b/code/studio/src/plugins/bnp_manager/bnp_proxy_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.cpp rename to code/studio/src/plugins/bnp_manager/bnp_proxy_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h b/code/studio/src/plugins/bnp_manager/bnp_proxy_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/bnp_proxy_model.h rename to code/studio/src/plugins/bnp_manager/bnp_proxy_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_add_item.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_add_item.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_bnp_make.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_bnp_make.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_bnp_make.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_bnp_make.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_delete_item.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_delete_item.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_export.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_export.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_export.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_export.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_new.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_new.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_new.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_new.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_reset_all.png b/code/studio/src/plugins/bnp_manager/images/ic_nel_reset_all.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/images/ic_nel_reset_all.png rename to code/studio/src/plugins/bnp_manager/images/ic_nel_reset_all.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml b/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml rename to code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/CMakeLists.txt b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/CMakeLists.txt rename to code/studio/src/plugins/disp_sheet_id/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp rename to code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h rename to code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml b/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml rename to code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.cpp b/code/studio/src/plugins/disp_sheet_id/sheet_id_view.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.cpp rename to code/studio/src/plugins/disp_sheet_id/sheet_id_view.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.h b/code/studio/src/plugins/disp_sheet_id/sheet_id_view.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.h rename to code/studio/src/plugins/disp_sheet_id/sheet_id_view.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.ui b/code/studio/src/plugins/disp_sheet_id/sheet_id_view.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/disp_sheet_id/sheet_id_view.ui rename to code/studio/src/plugins/disp_sheet_id/sheet_id_view.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/CMakeLists.txt b/code/studio/src/plugins/example/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/CMakeLists.txt rename to code/studio/src/plugins/example/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.cpp b/code/studio/src/plugins/example/example_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.cpp rename to code/studio/src/plugins/example/example_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.h b/code/studio/src/plugins/example/example_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_plugin.h rename to code/studio/src/plugins/example/example_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.cpp b/code/studio/src/plugins/example/example_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.cpp rename to code/studio/src/plugins/example/example_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.h b/code/studio/src/plugins/example/example_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.h rename to code/studio/src/plugins/example/example_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.ui b/code/studio/src/plugins/example/example_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/example_settings_page.ui rename to code/studio/src/plugins/example/example_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/ovqt_plugin_example.xml b/code/studio/src/plugins/example/ovqt_plugin_example.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/ovqt_plugin_example.xml rename to code/studio/src/plugins/example/ovqt_plugin_example.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.cpp b/code/studio/src/plugins/example/qnel_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.cpp rename to code/studio/src/plugins/example/qnel_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.h b/code/studio/src/plugins/example/qnel_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/qnel_widget.h rename to code/studio/src/plugins/example/qnel_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.cpp b/code/studio/src/plugins/example/simple_viewer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.cpp rename to code/studio/src/plugins/example/simple_viewer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.h b/code/studio/src/plugins/example/simple_viewer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/example/simple_viewer.h rename to code/studio/src/plugins/example/simple_viewer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/CMakeLists.txt rename to code/studio/src/plugins/georges_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp b/code/studio/src/plugins/georges_editor/actions.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.cpp rename to code/studio/src/plugins/georges_editor/actions.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h b/code/studio/src/plugins/georges_editor/actions.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/actions.h rename to code/studio/src/plugins/georges_editor/actions.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.cpp b/code/studio/src/plugins/georges_editor/expandable_headerview.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.cpp rename to code/studio/src/plugins/georges_editor/expandable_headerview.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.h b/code/studio/src/plugins/georges_editor/expandable_headerview.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/expandable_headerview.h rename to code/studio/src/plugins/georges_editor/expandable_headerview.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp b/code/studio/src/plugins/georges_editor/formdelegate.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.cpp rename to code/studio/src/plugins/georges_editor/formdelegate.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h b/code/studio/src/plugins/georges_editor/formdelegate.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formdelegate.h rename to code/studio/src/plugins/georges_editor/formdelegate.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp b/code/studio/src/plugins/georges_editor/formitem.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.cpp rename to code/studio/src/plugins/georges_editor/formitem.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h b/code/studio/src/plugins/georges_editor/formitem.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/formitem.h rename to code/studio/src/plugins/georges_editor/formitem.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.cpp b/code/studio/src/plugins/georges_editor/georges.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.cpp rename to code/studio/src/plugins/georges_editor/georges.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.h b/code/studio/src/plugins/georges_editor/georges.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges.h rename to code/studio/src/plugins/georges_editor/georges.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_dirtree_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.cpp rename to code/studio/src/plugins/georges_editor/georges_dirtree_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.h b/code/studio/src/plugins/georges_editor/georges_dirtree_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_dialog.h rename to code/studio/src/plugins/georges_editor/georges_dirtree_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_form.ui b/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_dirtree_form.ui rename to code/studio/src/plugins/georges_editor/georges_dirtree_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc b/code/studio/src/plugins/georges_editor/georges_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor.qrc rename to code/studio/src/plugins/georges_editor/georges_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_constants.h b/code/studio/src/plugins/georges_editor/georges_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_constants.h rename to code/studio/src/plugins/georges_editor/georges_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp b/code/studio/src/plugins/georges_editor/georges_editor_form.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.cpp rename to code/studio/src/plugins/georges_editor/georges_editor_form.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h b/code/studio/src/plugins/georges_editor/georges_editor_form.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.h rename to code/studio/src/plugins/georges_editor/georges_editor_form.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.ui b/code/studio/src/plugins/georges_editor/georges_editor_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_form.ui rename to code/studio/src/plugins/georges_editor/georges_editor_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.cpp b/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.cpp rename to code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.h b/code/studio/src/plugins/georges_editor/georges_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_editor_plugin.h rename to code/studio/src/plugins/georges_editor/georges_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.cpp b/code/studio/src/plugins/georges_editor/georges_filesystem_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.cpp rename to code/studio/src/plugins/georges_editor/georges_filesystem_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.h b/code/studio/src/plugins/georges_editor/georges_filesystem_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_filesystem_model.h rename to code/studio/src/plugins/georges_editor/georges_filesystem_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.cpp rename to code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_dialog.h rename to code/studio/src/plugins/georges_editor/georges_treeview_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui b/code/studio/src/plugins/georges_editor/georges_treeview_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georges_treeview_form.ui rename to code/studio/src/plugins/georges_editor/georges_treeview_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.cpp rename to code/studio/src/plugins/georges_editor/georgesform_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h b/code/studio/src/plugins/georges_editor/georgesform_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_model.h rename to code/studio/src/plugins/georges_editor/georgesform_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_proxy_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.cpp rename to code/studio/src/plugins/georges_editor/georgesform_proxy_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h b/code/studio/src/plugins/georges_editor/georgesform_proxy_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/georgesform_proxy_model.h rename to code/studio/src/plugins/georges_editor/georgesform_proxy_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico b/code/studio/src/plugins/georges_editor/images/array.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/array.ico rename to code/studio/src/plugins/georges_editor/images/array.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico b/code/studio/src/plugins/georges_editor/images/header.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/header.ico rename to code/studio/src/plugins/georges_editor/images/header.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico b/code/studio/src/plugins/georges_editor/images/hold.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/hold.ico rename to code/studio/src/plugins/georges_editor/images/hold.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/ic_nel_georges_editor.png b/code/studio/src/plugins/georges_editor/images/ic_nel_georges_editor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/ic_nel_georges_editor.png rename to code/studio/src/plugins/georges_editor/images/ic_nel_georges_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico b/code/studio/src/plugins/georges_editor/images/root.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/root.ico rename to code/studio/src/plugins/georges_editor/images/root.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/struct.ico b/code/studio/src/plugins/georges_editor/images/struct.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/struct.ico rename to code/studio/src/plugins/georges_editor/images/struct.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico b/code/studio/src/plugins/georges_editor/images/vstruct.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/vstruct.ico rename to code/studio/src/plugins/georges_editor/images/vstruct.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico b/code/studio/src/plugins/georges_editor/images/zfee51.ico similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/images/zfee51.ico rename to code/studio/src/plugins/georges_editor/images/zfee51.ico diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml b/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml rename to code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.cpp b/code/studio/src/plugins/georges_editor/stdpch.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.cpp rename to code/studio/src/plugins/georges_editor/stdpch.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.h b/code/studio/src/plugins/georges_editor/stdpch.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/georges_editor/stdpch.h rename to code/studio/src/plugins/georges_editor/stdpch.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/CMakeLists.txt rename to code/studio/src/plugins/gui_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.cpp b/code/studio/src/plugins/gui_editor/action_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.cpp rename to code/studio/src/plugins/gui_editor/action_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.h b/code/studio/src/plugins/gui_editor/action_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.h rename to code/studio/src/plugins/gui_editor/action_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.ui b/code/studio/src/plugins/gui_editor/action_editor.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/action_editor.ui rename to code/studio/src/plugins/gui_editor/action_editor.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.cpp b/code/studio/src/plugins/gui_editor/add_widget_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.cpp rename to code/studio/src/plugins/gui_editor/add_widget_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.h b/code/studio/src/plugins/gui_editor/add_widget_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.h rename to code/studio/src/plugins/gui_editor/add_widget_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.ui b/code/studio/src/plugins/gui_editor/add_widget_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/add_widget_widget.ui rename to code/studio/src/plugins/gui_editor/add_widget_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.cpp b/code/studio/src/plugins/gui_editor/editor_message_processor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.cpp rename to code/studio/src/plugins/gui_editor/editor_message_processor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.h b/code/studio/src/plugins/gui_editor/editor_message_processor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_message_processor.h rename to code/studio/src/plugins/gui_editor/editor_message_processor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.cpp b/code/studio/src/plugins/gui_editor/editor_selection_watcher.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.cpp rename to code/studio/src/plugins/gui_editor/editor_selection_watcher.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.h b/code/studio/src/plugins/gui_editor/editor_selection_watcher.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/editor_selection_watcher.h rename to code/studio/src/plugins/gui_editor/editor_selection_watcher.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_constants.h b/code/studio/src/plugins/gui_editor/gui_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_constants.h rename to code/studio/src/plugins/gui_editor/gui_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.cpp b/code/studio/src/plugins/gui_editor/gui_editor_context.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_context.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.h b/code/studio/src/plugins/gui_editor/gui_editor_context.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_context.h rename to code/studio/src/plugins/gui_editor/gui_editor_context.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.cpp b/code/studio/src/plugins/gui_editor/gui_editor_core_listener.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_core_listener.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.h b/code/studio/src/plugins/gui_editor/gui_editor_core_listener.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_core_listener.h rename to code/studio/src/plugins/gui_editor/gui_editor_core_listener.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_global.h b/code/studio/src/plugins/gui_editor/gui_editor_global.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_global.h rename to code/studio/src/plugins/gui_editor/gui_editor_global.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.cpp b/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.h b/code/studio/src/plugins/gui_editor/gui_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_plugin.h rename to code/studio/src/plugins/gui_editor/gui_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.cpp rename to code/studio/src/plugins/gui_editor/gui_editor_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.h rename to code/studio/src/plugins/gui_editor/gui_editor_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.ui b/code/studio/src/plugins/gui_editor/gui_editor_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/gui_editor_window.ui rename to code/studio/src/plugins/gui_editor/gui_editor_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.cpp b/code/studio/src/plugins/gui_editor/link_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.cpp rename to code/studio/src/plugins/gui_editor/link_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.h b/code/studio/src/plugins/gui_editor/link_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.h rename to code/studio/src/plugins/gui_editor/link_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.ui b/code/studio/src/plugins/gui_editor/link_editor.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_editor.ui rename to code/studio/src/plugins/gui_editor/link_editor.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.cpp b/code/studio/src/plugins/gui_editor/link_list.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.cpp rename to code/studio/src/plugins/gui_editor/link_list.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.h b/code/studio/src/plugins/gui_editor/link_list.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.h rename to code/studio/src/plugins/gui_editor/link_list.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.ui b/code/studio/src/plugins/gui_editor/link_list.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/link_list.ui rename to code/studio/src/plugins/gui_editor/link_list.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.cpp rename to code/studio/src/plugins/gui_editor/nel3d_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nel3d_widget.h rename to code/studio/src/plugins/gui_editor/nel3d_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.cpp rename to code/studio/src/plugins/gui_editor/nelgui_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/nelgui_widget.h rename to code/studio/src/plugins/gui_editor/nelgui_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.cpp b/code/studio/src/plugins/gui_editor/new_property_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.cpp rename to code/studio/src/plugins/gui_editor/new_property_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.h b/code/studio/src/plugins/gui_editor/new_property_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.h rename to code/studio/src/plugins/gui_editor/new_property_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.ui b/code/studio/src/plugins/gui_editor/new_property_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_property_widget.ui rename to code/studio/src/plugins/gui_editor/new_property_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.cpp b/code/studio/src/plugins/gui_editor/new_widget_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.cpp rename to code/studio/src/plugins/gui_editor/new_widget_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.h b/code/studio/src/plugins/gui_editor/new_widget_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.h rename to code/studio/src/plugins/gui_editor/new_widget_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.ui b/code/studio/src/plugins/gui_editor/new_widget_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/new_widget_widget.ui rename to code/studio/src/plugins/gui_editor/new_widget_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml b/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml rename to code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.cpp b/code/studio/src/plugins/gui_editor/proc_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.cpp rename to code/studio/src/plugins/gui_editor/proc_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.h b/code/studio/src/plugins/gui_editor/proc_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.h rename to code/studio/src/plugins/gui_editor/proc_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.ui b/code/studio/src/plugins/gui_editor/proc_editor.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_editor.ui rename to code/studio/src/plugins/gui_editor/proc_editor.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.cpp b/code/studio/src/plugins/gui_editor/proc_list.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.cpp rename to code/studio/src/plugins/gui_editor/proc_list.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.h b/code/studio/src/plugins/gui_editor/proc_list.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.h rename to code/studio/src/plugins/gui_editor/proc_list.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.ui b/code/studio/src/plugins/gui_editor/proc_list.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/proc_list.ui rename to code/studio/src/plugins/gui_editor/proc_list.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.cpp b/code/studio/src/plugins/gui_editor/project_file_parser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.cpp rename to code/studio/src/plugins/gui_editor/project_file_parser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.h b/code/studio/src/plugins/gui_editor/project_file_parser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_parser.h rename to code/studio/src/plugins/gui_editor/project_file_parser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.cpp b/code/studio/src/plugins/gui_editor/project_file_serializer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.cpp rename to code/studio/src/plugins/gui_editor/project_file_serializer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.h b/code/studio/src/plugins/gui_editor/project_file_serializer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_file_serializer.h rename to code/studio/src/plugins/gui_editor/project_file_serializer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files.h b/code/studio/src/plugins/gui_editor/project_files.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files.h rename to code/studio/src/plugins/gui_editor/project_files.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files/login.xml b/code/studio/src/plugins/gui_editor/project_files/login.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_files/login.xml rename to code/studio/src/plugins/gui_editor/project_files/login.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.cpp b/code/studio/src/plugins/gui_editor/project_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.cpp rename to code/studio/src/plugins/gui_editor/project_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.h b/code/studio/src/plugins/gui_editor/project_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.h rename to code/studio/src/plugins/gui_editor/project_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.ui b/code/studio/src/plugins/gui_editor/project_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/project_window.ui rename to code/studio/src/plugins/gui_editor/project_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.cpp rename to code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/property_browser_ctrl.h rename to code/studio/src/plugins/gui_editor/property_browser_ctrl.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.cpp b/code/studio/src/plugins/gui_editor/widget_hierarchy.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.cpp rename to code/studio/src/plugins/gui_editor/widget_hierarchy.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.h b/code/studio/src/plugins/gui_editor/widget_hierarchy.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.h rename to code/studio/src/plugins/gui_editor/widget_hierarchy.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.ui b/code/studio/src/plugins/gui_editor/widget_hierarchy.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_hierarchy.ui rename to code/studio/src/plugins/gui_editor/widget_hierarchy.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info.h b/code/studio/src/plugins/gui_editor/widget_info.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info.h rename to code/studio/src/plugins/gui_editor/widget_info.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.cpp b/code/studio/src/plugins/gui_editor/widget_info_serializer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.cpp rename to code/studio/src/plugins/gui_editor/widget_info_serializer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.h b/code/studio/src/plugins/gui_editor/widget_info_serializer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_serializer.h rename to code/studio/src/plugins/gui_editor/widget_info_serializer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree.h b/code/studio/src/plugins/gui_editor/widget_info_tree.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree.h rename to code/studio/src/plugins/gui_editor/widget_info_tree.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_node.h b/code/studio/src/plugins/gui_editor/widget_info_tree_node.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_node.h rename to code/studio/src/plugins/gui_editor/widget_info_tree_node.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_visitor.h b/code/studio/src/plugins/gui_editor/widget_info_tree_visitor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_info_tree_visitor.h rename to code/studio/src/plugins/gui_editor/widget_info_tree_visitor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.cpp b/code/studio/src/plugins/gui_editor/widget_properties.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.cpp rename to code/studio/src/plugins/gui_editor/widget_properties.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.h b/code/studio/src/plugins/gui_editor/widget_properties.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.h rename to code/studio/src/plugins/gui_editor/widget_properties.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.ui b/code/studio/src/plugins/gui_editor/widget_properties.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties.ui rename to code/studio/src/plugins/gui_editor/widget_properties.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.cpp b/code/studio/src/plugins/gui_editor/widget_properties_parser.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.cpp rename to code/studio/src/plugins/gui_editor/widget_properties_parser.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.h b/code/studio/src/plugins/gui_editor/widget_properties_parser.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_properties_parser.h rename to code/studio/src/plugins/gui_editor/widget_properties_parser.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.cpp b/code/studio/src/plugins/gui_editor/widget_serializer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.cpp rename to code/studio/src/plugins/gui_editor/widget_serializer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.h b/code/studio/src/plugins/gui_editor/widget_serializer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widget_serializer.h rename to code/studio/src/plugins/gui_editor/widget_serializer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBase.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBase.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlBaseButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlColPick.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlColPick.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlScroll.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlScroll.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTabButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTabButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTabButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlTabButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/CtrlTextButton.xml rename to code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml rename to code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar3.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewBar3.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewDigit.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewDigit.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewNumber.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewQuantity.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/DBViewQuantity.xml rename to code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupCell.xml b/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupCell.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupCell.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupContainer.xml b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupContainer.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupEditBox.xml b/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupEditBox.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupFrame.xml b/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupFrame.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHTML.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHTML.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHeader.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupHeader.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupList.xml b/code/studio/src/plugins/gui_editor/widgets/GroupList.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupList.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupList.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupMenu.xml b/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupMenu.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupModal.xml b/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupModal.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupModal.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupParagraph.xml b/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupParagraph.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupScrollText.xml b/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupScrollText.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTab.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTab.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupTab.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTable.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTable.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupTable.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTree.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/GroupTree.xml rename to code/studio/src/plugins/gui_editor/widgets/GroupTree.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceElement.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceElement.xml rename to code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroup.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroup.xml rename to code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml rename to code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/RootGroup.xml b/code/studio/src/plugins/gui_editor/widgets/RootGroup.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/RootGroup.xml rename to code/studio/src/plugins/gui_editor/widgets/RootGroup.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmap.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewText.xml b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewText.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewText.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextFormated.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextID.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextID.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml rename to code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt b/code/studio/src/plugins/landscape_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt rename to code/studio/src/plugins/landscape_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp b/code/studio/src/plugins/landscape_editor/builder_zone.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp rename to code/studio/src/plugins/landscape_editor/builder_zone.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h b/code/studio/src/plugins/landscape_editor/builder_zone.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.h rename to code/studio/src/plugins/landscape_editor/builder_zone.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp b/code/studio/src/plugins/landscape_editor/builder_zone_base.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp rename to code/studio/src/plugins/landscape_editor/builder_zone_base.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.h b/code/studio/src/plugins/landscape_editor/builder_zone_base.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.h rename to code/studio/src/plugins/landscape_editor/builder_zone_base.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp b/code/studio/src/plugins/landscape_editor/builder_zone_region.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp rename to code/studio/src/plugins/landscape_editor/builder_zone_region.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h b/code/studio/src/plugins/landscape_editor/builder_zone_region.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h rename to code/studio/src/plugins/landscape_editor/builder_zone_region.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_grid.png b/code/studio/src/plugins/landscape_editor/icons/ic_grid.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_grid.png rename to code/studio/src/plugins/landscape_editor/icons/ic_grid.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_landscape_settings.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_transition_land.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_transition_land.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_transition_land.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_transition_land.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_world_editor.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_world_editor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_world_editor.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_world_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zone.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_zone.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zone.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_zone.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zonel.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_zonel.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zonel.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_zonel.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zones.png b/code/studio/src/plugins/landscape_editor/icons/ic_nel_zones.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_nel_zones.png rename to code/studio/src/plugins/landscape_editor/icons/ic_nel_zones.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_snapshot.png b/code/studio/src/plugins/landscape_editor/icons/ic_snapshot.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/icons/ic_snapshot.png rename to code/studio/src/plugins/landscape_editor/icons/ic_snapshot.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp b/code/studio/src/plugins/landscape_editor/landscape_actions.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp rename to code/studio/src/plugins/landscape_editor/landscape_actions.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h b/code/studio/src/plugins/landscape_editor/landscape_actions.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.h rename to code/studio/src/plugins/landscape_editor/landscape_actions.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor.qrc b/code/studio/src/plugins/landscape_editor/landscape_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor.qrc rename to code/studio/src/plugins/landscape_editor/landscape_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_constants.h b/code/studio/src/plugins/landscape_editor/landscape_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_constants.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_global.h b/code/studio/src/plugins/landscape_editor/landscape_editor_global.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_global.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_global.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp rename to code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.h b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp rename to code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h b/code/studio/src/plugins/landscape_editor/landscape_editor_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.h rename to code/studio/src/plugins/landscape_editor/landscape_editor_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.ui b/code/studio/src/plugins/landscape_editor/landscape_editor_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.ui rename to code/studio/src/plugins/landscape_editor/landscape_editor_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp b/code/studio/src/plugins/landscape_editor/landscape_scene.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp rename to code/studio/src/plugins/landscape_editor/landscape_scene.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h b/code/studio/src/plugins/landscape_editor/landscape_scene.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.h rename to code/studio/src/plugins/landscape_editor/landscape_scene.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp b/code/studio/src/plugins/landscape_editor/landscape_scene_base.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp rename to code/studio/src/plugins/landscape_editor/landscape_scene_base.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.h b/code/studio/src/plugins/landscape_editor/landscape_scene_base.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.h rename to code/studio/src/plugins/landscape_editor/landscape_scene_base.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp b/code/studio/src/plugins/landscape_editor/landscape_view.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp rename to code/studio/src/plugins/landscape_editor/landscape_view.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.h b/code/studio/src/plugins/landscape_editor/landscape_view.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.h rename to code/studio/src/plugins/landscape_editor/landscape_view.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp b/code/studio/src/plugins/landscape_editor/list_zones_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp rename to code/studio/src/plugins/landscape_editor/list_zones_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.h b/code/studio/src/plugins/landscape_editor/list_zones_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.h rename to code/studio/src/plugins/landscape_editor/list_zones_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp b/code/studio/src/plugins/landscape_editor/list_zones_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp rename to code/studio/src/plugins/landscape_editor/list_zones_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h b/code/studio/src/plugins/landscape_editor/list_zones_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.h rename to code/studio/src/plugins/landscape_editor/list_zones_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.ui b/code/studio/src/plugins/landscape_editor/list_zones_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.ui rename to code/studio/src/plugins/landscape_editor/list_zones_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml b/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml rename to code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp b/code/studio/src/plugins/landscape_editor/pixmap_database.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp rename to code/studio/src/plugins/landscape_editor/pixmap_database.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.h b/code/studio/src/plugins/landscape_editor/pixmap_database.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.h rename to code/studio/src/plugins/landscape_editor/pixmap_database.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp b/code/studio/src/plugins/landscape_editor/project_settings_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp rename to code/studio/src/plugins/landscape_editor/project_settings_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.h b/code/studio/src/plugins/landscape_editor/project_settings_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.h rename to code/studio/src/plugins/landscape_editor/project_settings_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.ui b/code/studio/src/plugins/landscape_editor/project_settings_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.ui rename to code/studio/src/plugins/landscape_editor/project_settings_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/shapshot_dialog.ui b/code/studio/src/plugins/landscape_editor/shapshot_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/shapshot_dialog.ui rename to code/studio/src/plugins/landscape_editor/shapshot_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp b/code/studio/src/plugins/landscape_editor/snapshot_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp rename to code/studio/src/plugins/landscape_editor/snapshot_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.h b/code/studio/src/plugins/landscape_editor/snapshot_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.h rename to code/studio/src/plugins/landscape_editor/snapshot_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp b/code/studio/src/plugins/landscape_editor/zone_region_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp rename to code/studio/src/plugins/landscape_editor/zone_region_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h b/code/studio/src/plugins/landscape_editor/zone_region_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.h rename to code/studio/src/plugins/landscape_editor/zone_region_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/CMakeLists.txt b/code/studio/src/plugins/log/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/CMakeLists.txt rename to code/studio/src/plugins/log/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_form.ui b/code/studio/src/plugins/log/log_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_form.ui rename to code/studio/src/plugins/log/log_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.cpp rename to code/studio/src/plugins/log/log_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.h b/code/studio/src/plugins/log/log_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_plugin.h rename to code/studio/src/plugins/log/log_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.cpp b/code/studio/src/plugins/log/log_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.cpp rename to code/studio/src/plugins/log/log_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.h b/code/studio/src/plugins/log/log_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.h rename to code/studio/src/plugins/log/log_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.ui b/code/studio/src/plugins/log/log_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/log_settings_page.ui rename to code/studio/src/plugins/log/log_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/ovqt_plugin_log.xml b/code/studio/src/plugins/log/ovqt_plugin_log.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/ovqt_plugin_log.xml rename to code/studio/src/plugins/log/ovqt_plugin_log.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.cpp b/code/studio/src/plugins/log/qt_displayer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.cpp rename to code/studio/src/plugins/log/qt_displayer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.h b/code/studio/src/plugins/log/qt_displayer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/log/qt_displayer.h rename to code/studio/src/plugins/log/qt_displayer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/CMakeLists.txt b/code/studio/src/plugins/mission_compiler/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/CMakeLists.txt rename to code/studio/src/plugins/mission_compiler/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-left-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-left-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-double-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-left-double-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-left-double-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-left-double-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-right-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-right-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-double-2.png b/code/studio/src/plugins/mission_compiler/images/arrow-right-double-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/arrow-right-double-2.png rename to code/studio/src/plugins/mission_compiler/images/arrow-right-double-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/document-export-4.png b/code/studio/src/plugins/mission_compiler/images/document-export-4.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/document-export-4.png rename to code/studio/src/plugins/mission_compiler/images/document-export-4.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_add_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_add_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_delete_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_delete_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_down_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_down_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_down_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_down_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_generic_settings.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_generic_settings.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_generic_settings.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_generic_settings.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_reset_all.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_reset_all.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_reset_all.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_reset_all.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_up_item.png b/code/studio/src/plugins/mission_compiler/images/ic_nel_up_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_up_item.png rename to code/studio/src/plugins/mission_compiler/images/ic_nel_up_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/news-subscribe-2.png b/code/studio/src/plugins/mission_compiler/images/news-subscribe-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/news-subscribe-2.png rename to code/studio/src/plugins/mission_compiler/images/news-subscribe-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/run-build-2.png b/code/studio/src/plugins/mission_compiler/images/run-build-2.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/run-build-2.png rename to code/studio/src/plugins/mission_compiler/images/run-build-2.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler.qrc b/code/studio/src/plugins/mission_compiler/mission_compiler.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler.qrc rename to code/studio/src/plugins/mission_compiler/mission_compiler.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.cpp rename to code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.h b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.ui b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_main_window.ui rename to code/studio/src/plugins/mission_compiler/mission_compiler_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.cpp rename to code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.h b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin_constants.h b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_plugin_constants.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_plugin_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.cpp rename to code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.h b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.h rename to code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.ui b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/mission_compiler_settings_page.ui rename to code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml b/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml rename to code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.cpp b/code/studio/src/plugins/mission_compiler/server_entry_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.cpp rename to code/studio/src/plugins/mission_compiler/server_entry_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.h b/code/studio/src/plugins/mission_compiler/server_entry_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.h rename to code/studio/src/plugins/mission_compiler/server_entry_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.ui b/code/studio/src/plugins/mission_compiler/server_entry_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/server_entry_dialog.ui rename to code/studio/src/plugins/mission_compiler/server_entry_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.cpp b/code/studio/src/plugins/mission_compiler/validation_file.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.cpp rename to code/studio/src/plugins/mission_compiler/validation_file.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.h b/code/studio/src/plugins/mission_compiler/validation_file.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/validation_file.h rename to code/studio/src/plugins/mission_compiler/validation_file.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/CMakeLists.txt b/code/studio/src/plugins/object_viewer/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/CMakeLists.txt rename to code/studio/src/plugins/object_viewer/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.cpp b/code/studio/src/plugins/object_viewer/graphics_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.cpp rename to code/studio/src/plugins/object_viewer/graphics_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.h b/code/studio/src/plugins/object_viewer/graphics_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.h rename to code/studio/src/plugins/object_viewer/graphics_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.ui b/code/studio/src/plugins/object_viewer/graphics_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_settings_page.ui rename to code/studio/src/plugins/object_viewer/graphics_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.cpp b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.cpp rename to code/studio/src/plugins/object_viewer/graphics_viewport.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.h b/code/studio/src/plugins/object_viewer/graphics_viewport.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/graphics_viewport.h rename to code/studio/src/plugins/object_viewer/graphics_viewport.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_add_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_add_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_anim.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_anim.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_anim.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_anim.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_animset.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_animset.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_animset.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_animset.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_append_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_append_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_append_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_append_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_bgcolor.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_bgcolor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_bgcolor.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_bgcolor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_3dedit.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_add.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_add.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_add.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_add.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_del.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_del.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_del.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_del.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_fps.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_camera_fps.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_camera_fps.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_camera_fps.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_daynight.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_daynight.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_daynight.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_daynight.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_delete_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_delete_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_down_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_down_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_down_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_down_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_framedelay.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_framedelay.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_framedelay.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_framedelay.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_insert_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_insert_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_insert_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_insert_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mixer.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_mixer.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mixer.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_mixer.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_mrm_mesh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_new.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_new.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_new.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_new.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_open.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_open.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_open.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_open.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_particle_system_close.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particles.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_particles.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_particles.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_particles.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_pill.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_pill.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/icons/ic_nel_pill.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_pill.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_reset_all.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_reset_all.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_reset_all.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_reset_all.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_reset_camera.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_reset_camera.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_reset_camera.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_reset_camera.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_save.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_save.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save_as.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_save_as.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_save_as.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_save_as.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_skelscale.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_skelscale.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_skelscale.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_skelscale.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_sound.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_sound.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_sound.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_sound.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_up_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_up_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/mission_compiler/images/ic_nel_up_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_up_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_veget.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_veget.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_veget.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_veget.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_vegetset.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_vegetset.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_vegetset.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_vegetset.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_water.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_water.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_water.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_water.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_wind.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_wind.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_wind.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_wind.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_workspace_item.png b/code/studio/src/plugins/object_viewer/icons/ic_nel_workspace_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_workspace_item.png rename to code/studio/src/plugins/object_viewer/icons/ic_nel_workspace_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_collision_zone_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_emitter_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_force_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_instance_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_light_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_located_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_particle_system_close_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_sound_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png b/code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png rename to code/studio/src/plugins/object_viewer/icons/particles_system_24/ic_nel_workspace_item_24.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/dqynight.png b/code/studio/src/plugins/object_viewer/images/dqynight.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/dqynight.png rename to code/studio/src/plugins/object_viewer/images/dqynight.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/ico_mrm_mesh.png b/code/studio/src/plugins/object_viewer/images/ico_mrm_mesh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/ico_mrm_mesh.png rename to code/studio/src/plugins/object_viewer/images/ico_mrm_mesh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/mixer.png b/code/studio/src/plugins/object_viewer/images/mixer.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/mixer.png rename to code/studio/src/plugins/object_viewer/images/mixer.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/nel.png b/code/studio/src/plugins/object_viewer/images/nel.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/core/images/nel.png rename to code/studio/src/plugins/object_viewer/images/nel.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pause.png b/code/studio/src/plugins/object_viewer/images/pause.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pause.png rename to code/studio/src/plugins/object_viewer/images/pause.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/play.png b/code/studio/src/plugins/object_viewer/images/play.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/play.png rename to code/studio/src/plugins/object_viewer/images/play.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/polymode.png b/code/studio/src/plugins/object_viewer/images/polymode.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/polymode.png rename to code/studio/src/plugins/object_viewer/images/polymode.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pqrticles.png b/code/studio/src/plugins/object_viewer/images/pqrticles.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/pqrticles.png rename to code/studio/src/plugins/object_viewer/images/pqrticles.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/refresh.png b/code/studio/src/plugins/object_viewer/images/refresh.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/refresh.png rename to code/studio/src/plugins/object_viewer/images/refresh.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmfill.png b/code/studio/src/plugins/object_viewer/images/rmfill.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmfill.png rename to code/studio/src/plugins/object_viewer/images/rmfill.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmline.png b/code/studio/src/plugins/object_viewer/images/rmline.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmline.png rename to code/studio/src/plugins/object_viewer/images/rmline.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmpoints.png b/code/studio/src/plugins/object_viewer/images/rmpoints.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/rmpoints.png rename to code/studio/src/plugins/object_viewer/images/rmpoints.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-backward.png b/code/studio/src/plugins/object_viewer/images/seek-backward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-backward.png rename to code/studio/src/plugins/object_viewer/images/seek-backward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-forward.png b/code/studio/src/plugins/object_viewer/images/seek-forward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/seek-forward.png rename to code/studio/src/plugins/object_viewer/images/seek-forward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-backward.png b/code/studio/src/plugins/object_viewer/images/skip-backward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-backward.png rename to code/studio/src/plugins/object_viewer/images/skip-backward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-forward.png b/code/studio/src/plugins/object_viewer/images/skip-forward.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/skip-forward.png rename to code/studio/src/plugins/object_viewer/images/skip-forward.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/sound.png b/code/studio/src/plugins/object_viewer/images/sound.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/sound.png rename to code/studio/src/plugins/object_viewer/images/sound.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/stop.png b/code/studio/src/plugins/object_viewer/images/stop.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/stop.png rename to code/studio/src/plugins/object_viewer/images/stop.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/water.png b/code/studio/src/plugins/object_viewer/images/water.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/water.png rename to code/studio/src/plugins/object_viewer/images/water.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/wind.png b/code/studio/src/plugins/object_viewer/images/wind.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/wind.png rename to code/studio/src/plugins/object_viewer/images/wind.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.cpp rename to code/studio/src/plugins/object_viewer/main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.h b/code/studio/src/plugins/object_viewer/main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/main_window.h rename to code/studio/src/plugins/object_viewer/main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.cpp b/code/studio/src/plugins/object_viewer/modules.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.cpp rename to code/studio/src/plugins/object_viewer/modules.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.h b/code/studio/src/plugins/object_viewer/modules.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/modules.h rename to code/studio/src/plugins/object_viewer/modules.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.cpp b/code/studio/src/plugins/object_viewer/object_viewer.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.cpp rename to code/studio/src/plugins/object_viewer/object_viewer.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.h b/code/studio/src/plugins/object_viewer/object_viewer.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.h rename to code/studio/src/plugins/object_viewer/object_viewer.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.qrc b/code/studio/src/plugins/object_viewer/object_viewer.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer.qrc rename to code/studio/src/plugins/object_viewer/object_viewer.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_constants.h b/code/studio/src/plugins/object_viewer/object_viewer_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_constants.h rename to code/studio/src/plugins/object_viewer/object_viewer_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.cpp b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.cpp rename to code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.h b/code/studio/src/plugins/object_viewer/object_viewer_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/object_viewer_plugin.h rename to code/studio/src/plugins/object_viewer/object_viewer_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml b/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml rename to code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_form.ui b/code/studio/src/plugins/object_viewer/particle_system/attrib_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/attrib_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/attrib_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/attrib_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.h b/code/studio/src/plugins/object_viewer/particle_system/attrib_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/attrib_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/attrib_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/auto_lod_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_form.ui b/code/studio/src/plugins/object_viewer/particle_system/auto_lod_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/auto_lod_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/auto_lod_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_form.ui b/code/studio/src/plugins/object_viewer/particle_system/basic_edit_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/basic_edit_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.h b/code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/basic_edit_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/basic_edit_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/bin_op_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/bin_op_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui b/code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h b/code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/constraint_mesh_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/curve_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/curve_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/curve_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/curve_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_form.ui b/code/studio/src/plugins/object_viewer/particle_system/curve_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/curve_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/curve_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_form.ui b/code/studio/src/plugins/object_viewer/particle_system/direction_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/direction_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/direction_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/direction_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.h b/code/studio/src/plugins/object_viewer/particle_system/direction_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/direction_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/direction_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.cpp b/code/studio/src/plugins/object_viewer/particle_system/dup_ps.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.cpp rename to code/studio/src/plugins/object_viewer/particle_system/dup_ps.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.h b/code/studio/src/plugins/object_viewer/particle_system/dup_ps.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/dup_ps.h rename to code/studio/src/plugins/object_viewer/particle_system/dup_ps.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_form.ui b/code/studio/src/plugins/object_viewer/particle_system/emitter_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/emitter_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/emitter_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/emitter_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.h b/code/studio/src/plugins/object_viewer/particle_system/emitter_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/emitter_page.h rename to code/studio/src/plugins/object_viewer/particle_system/emitter_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/follow_path_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/follow_path_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_form.ui b/code/studio/src/plugins/object_viewer/particle_system/located_bindable_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/located_bindable_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.h b/code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_bindable_page.h rename to code/studio/src/plugins/object_viewer/particle_system/located_bindable_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_form.ui b/code/studio/src/plugins/object_viewer/particle_system/located_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/located_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/located_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/located_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.h b/code/studio/src/plugins/object_viewer/particle_system/located_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/located_page.h rename to code/studio/src/plugins/object_viewer/particle_system/located_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_form.ui b/code/studio/src/plugins/object_viewer/particle_system/mesh_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/mesh_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/mesh_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/mesh_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.h b/code/studio/src/plugins/object_viewer/particle_system/mesh_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/mesh_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/mesh_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/morph_mesh_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_form.ui b/code/studio/src/plugins/object_viewer/particle_system/morph_mesh_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/morph_mesh_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/morph_mesh_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/multi_tex_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_form.ui b/code/studio/src/plugins/object_viewer/particle_system/multi_tex_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/multi_tex_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/multi_tex_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_control_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_control_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_control_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_control_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.h b/code/studio/src/plugins/object_viewer/particle_system/particle_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_editor.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_force_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_force_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_force_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_force_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_force_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_force_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_force_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_light_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_light_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_light_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_light_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_light_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_light_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_light_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_link_skeleton_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_node.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.h b/code/studio/src/plugins/object_viewer/particle_system/particle_node.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_node.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_node.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_property_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_property_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_sound_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_sound_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_sound_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_sound_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_system_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_system_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_system_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_system_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_system_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_system_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_system_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_anim_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.h b/code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_texture_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_texture_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.h b/code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_tree_model.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_tree_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_workspace_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_workspace_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_form.ui b/code/studio/src/plugins/object_viewer/particle_system/particle_zone_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/particle_zone_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.h b/code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/particle_zone_page.h rename to code/studio/src/plugins/object_viewer/particle_system/particle_zone_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp b/code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp rename to code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.h b/code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_initial_pos.h rename to code/studio/src/plugins/object_viewer/particle_system/ps_initial_pos.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_form.ui b/code/studio/src/plugins/object_viewer/particle_system/ps_mover_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/ps_mover_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.cpp b/code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.cpp rename to code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.h b/code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_mover_page.h rename to code/studio/src/plugins/object_viewer/particle_system/ps_mover_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_wrapper.h b/code/studio/src/plugins/object_viewer/particle_system/ps_wrapper.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/ps_wrapper.h rename to code/studio/src/plugins/object_viewer/particle_system/ps_wrapper.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/scheme_bank_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_form.ui b/code/studio/src/plugins/object_viewer/particle_system/scheme_bank_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_bank_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/scheme_bank_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.cpp b/code/studio/src/plugins/object_viewer/particle_system/scheme_manager.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.cpp rename to code/studio/src/plugins/object_viewer/particle_system/scheme_manager.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.h b/code/studio/src/plugins/object_viewer/particle_system/scheme_manager.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/scheme_manager.h rename to code/studio/src/plugins/object_viewer/particle_system/scheme_manager.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/spinner_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/spinner_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_form.ui b/code/studio/src/plugins/object_viewer/particle_system/tail_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/tail_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp b/code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp rename to code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.h b/code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/tail_particle_widget.h rename to code/studio/src/plugins/object_viewer/particle_system/tail_particle_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_blender_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/value_blender_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/value_from_emitter_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp b/code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp rename to code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.h b/code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_dialog.h rename to code/studio/src/plugins/object_viewer/particle_system/value_gradient_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_form.ui b/code/studio/src/plugins/object_viewer/particle_system/value_gradient_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/value_gradient_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/value_gradient_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/workspace_form.ui b/code/studio/src/plugins/object_viewer/particle_system/workspace_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/particle_system/workspace_form.ui rename to code/studio/src/plugins/object_viewer/particle_system/workspace_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/animation_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/animation_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.h b/code/studio/src/plugins/object_viewer/scene/animation_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_dialog.h rename to code/studio/src/plugins/object_viewer/scene/animation_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_form.ui b/code/studio/src/plugins/object_viewer/scene/animation_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_form.ui rename to code/studio/src/plugins/object_viewer/scene/animation_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/animation_set_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/animation_set_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.h b/code/studio/src/plugins/object_viewer/scene/animation_set_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_dialog.h rename to code/studio/src/plugins/object_viewer/scene/animation_set_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_form.ui b/code/studio/src/plugins/object_viewer/scene/animation_set_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/animation_set_form.ui rename to code/studio/src/plugins/object_viewer/scene/animation_set_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.cpp b/code/studio/src/plugins/object_viewer/scene/camera_control.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.cpp rename to code/studio/src/plugins/object_viewer/scene/camera_control.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.h b/code/studio/src/plugins/object_viewer/scene/camera_control.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/camera_control.h rename to code/studio/src/plugins/object_viewer/scene/camera_control.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/day_night_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/day_night_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.h b/code/studio/src/plugins/object_viewer/scene/day_night_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_dialog.h rename to code/studio/src/plugins/object_viewer/scene/day_night_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_form.ui b/code/studio/src/plugins/object_viewer/scene/day_night_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/day_night_form.ui rename to code/studio/src/plugins/object_viewer/scene/day_night_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.cpp b/code/studio/src/plugins/object_viewer/scene/entity.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.cpp rename to code/studio/src/plugins/object_viewer/scene/entity.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.h b/code/studio/src/plugins/object_viewer/scene/entity.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/entity.h rename to code/studio/src/plugins/object_viewer/scene/entity.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/global_wind_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/global_wind_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.h b/code/studio/src/plugins/object_viewer/scene/global_wind_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_dialog.h rename to code/studio/src/plugins/object_viewer/scene/global_wind_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_form.ui b/code/studio/src/plugins/object_viewer/scene/global_wind_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/global_wind_form.ui rename to code/studio/src/plugins/object_viewer/scene/global_wind_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.h b/code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_dialog.h rename to code/studio/src/plugins/object_viewer/scene/setup_fog_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_form.ui b/code/studio/src/plugins/object_viewer/scene/setup_fog_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/setup_fog_form.ui rename to code/studio/src/plugins/object_viewer/scene/setup_fog_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.h b/code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_dialog.h rename to code/studio/src/plugins/object_viewer/scene/skeleton_scale_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_form.ui b/code/studio/src/plugins/object_viewer/scene/skeleton_scale_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_scale_form.ui rename to code/studio/src/plugins/object_viewer/scene/skeleton_scale_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.cpp b/code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.cpp rename to code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.h b/code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/skeleton_tree_model.h rename to code/studio/src/plugins/object_viewer/scene/skeleton_tree_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_form.ui b/code/studio/src/plugins/object_viewer/scene/slot_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_form.ui rename to code/studio/src/plugins/object_viewer/scene/slot_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.h b/code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/slot_manager_dialog.h rename to code/studio/src/plugins/object_viewer/scene/slot_manager_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/sun_color_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/sun_color_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.h b/code/studio/src/plugins/object_viewer/scene/sun_color_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_dialog.h rename to code/studio/src/plugins/object_viewer/scene/sun_color_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_form.ui b/code/studio/src/plugins/object_viewer/scene/sun_color_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/sun_color_form.ui rename to code/studio/src/plugins/object_viewer/scene/sun_color_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.h b/code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_dialog.h rename to code/studio/src/plugins/object_viewer/scene/tune_mrm_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_form.ui b/code/studio/src/plugins/object_viewer/scene/tune_mrm_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_mrm_form.ui rename to code/studio/src/plugins/object_viewer/scene/tune_mrm_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.h b/code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_dialog.h rename to code/studio/src/plugins/object_viewer/scene/tune_timer_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_form.ui b/code/studio/src/plugins/object_viewer/scene/tune_timer_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/tune_timer_form.ui rename to code/studio/src/plugins/object_viewer/scene/tune_timer_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.cpp b/code/studio/src/plugins/object_viewer/scene/water_pool_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.cpp rename to code/studio/src/plugins/object_viewer/scene/water_pool_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.h b/code/studio/src/plugins/object_viewer/scene/water_pool_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_dialog.h rename to code/studio/src/plugins/object_viewer/scene/water_pool_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_form.ui b/code/studio/src/plugins/object_viewer/scene/water_pool_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/scene/water_pool_form.ui rename to code/studio/src/plugins/object_viewer/scene/water_pool_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.cpp b/code/studio/src/plugins/object_viewer/sound_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.cpp rename to code/studio/src/plugins/object_viewer/sound_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.h b/code/studio/src/plugins/object_viewer/sound_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.h rename to code/studio/src/plugins/object_viewer/sound_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.ui b/code/studio/src/plugins/object_viewer/sound_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_settings_page.ui rename to code/studio/src/plugins/object_viewer/sound_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.cpp b/code/studio/src/plugins/object_viewer/sound_system.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.cpp rename to code/studio/src/plugins/object_viewer/sound_system.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.h b/code/studio/src/plugins/object_viewer/sound_system.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/sound_system.h rename to code/studio/src/plugins/object_viewer/sound_system.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.cpp b/code/studio/src/plugins/object_viewer/stdpch.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.cpp rename to code/studio/src/plugins/object_viewer/stdpch.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.h b/code/studio/src/plugins/object_viewer/stdpch.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/stdpch.h rename to code/studio/src/plugins/object_viewer/stdpch.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_appearance_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_apperance_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_density_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_density_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_density_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_density_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_dialog_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_editor.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_landscape_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_node.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_node.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_node.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_node.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_node.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_noise_value_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_rotate_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui b/code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp b/code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.h b/code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable/vegetable_scale_page.h rename to code/studio/src/plugins/object_viewer/vegetable/vegetable_scale_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.cpp b/code/studio/src/plugins/object_viewer/vegetable_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.cpp rename to code/studio/src/plugins/object_viewer/vegetable_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.h b/code/studio/src/plugins/object_viewer/vegetable_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.h rename to code/studio/src/plugins/object_viewer/vegetable_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.ui b/code/studio/src/plugins/object_viewer/vegetable_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/vegetable_settings_page.ui rename to code/studio/src/plugins/object_viewer/vegetable_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_form.ui b/code/studio/src/plugins/object_viewer/widgets/color_edit_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_form.ui rename to code/studio/src/plugins/object_viewer/widgets/color_edit_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.cpp b/code/studio/src/plugins/object_viewer/widgets/color_edit_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.cpp rename to code/studio/src/plugins/object_viewer/widgets/color_edit_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.h b/code/studio/src/plugins/object_viewer/widgets/color_edit_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/color_edit_widget.h rename to code/studio/src/plugins/object_viewer/widgets/color_edit_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_float_form.ui b/code/studio/src/plugins/object_viewer/widgets/edit_range_float_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_float_form.ui rename to code/studio/src/plugins/object_viewer/widgets/edit_range_float_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_uint_form.ui b/code/studio/src/plugins/object_viewer/widgets/edit_range_uint_form.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_uint_form.ui rename to code/studio/src/plugins/object_viewer/widgets/edit_range_uint_form.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.cpp b/code/studio/src/plugins/object_viewer/widgets/edit_range_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.cpp rename to code/studio/src/plugins/object_viewer/widgets/edit_range_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.h b/code/studio/src/plugins/object_viewer/widgets/edit_range_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/edit_range_widget.h rename to code/studio/src/plugins/object_viewer/widgets/edit_range_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.cpp b/code/studio/src/plugins/object_viewer/widgets/hoverpoints.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.cpp rename to code/studio/src/plugins/object_viewer/widgets/hoverpoints.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.h b/code/studio/src/plugins/object_viewer/widgets/hoverpoints.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/widgets/hoverpoints.h rename to code/studio/src/plugins/object_viewer/widgets/hoverpoints.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/CMakeLists.txt b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/CMakeLists.txt rename to code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro rename to code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.pro diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilder.h b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilder.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilder.h rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilder.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderconfgdialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h b/code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h rename to code/studio/src/plugins/ovqt_sheet_builder/sheetbuilderdialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/CMakeLists.txt rename to code/studio/src/plugins/tile_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png b/code/studio/src/plugins/tile_editor/images/add_tile.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/add_tile.png rename to code/studio/src/plugins/tile_editor/images/add_tile.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_image.png b/code/studio/src/plugins/tile_editor/images/delete_image.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_image.png rename to code/studio/src/plugins/tile_editor/images/delete_image.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_tile.png b/code/studio/src/plugins/tile_editor/images/delete_tile.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/delete_tile.png rename to code/studio/src/plugins/tile_editor/images/delete_tile.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png b/code/studio/src/plugins/tile_editor/images/down.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/down.png rename to code/studio/src/plugins/tile_editor/images/down.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png b/code/studio/src/plugins/tile_editor/images/empty_image.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/empty_image.png rename to code/studio/src/plugins/tile_editor/images/empty_image.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_add_item.png b/code/studio/src/plugins/tile_editor/images/ic_nel_add_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_add_item.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_add_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_delete_item.png b/code/studio/src/plugins/tile_editor/images/ic_nel_delete_item.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_delete_item.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_delete_item.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png b/code/studio/src/plugins/tile_editor/images/ic_nel_new.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_new.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_new.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_open.png b/code/studio/src/plugins/tile_editor/images/ic_nel_open.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/icons/ic_nel_open.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_open.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save.png b/code/studio/src/plugins/tile_editor/images/ic_nel_save.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_save.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save_as.png b/code/studio/src/plugins/tile_editor/images/ic_nel_save_as.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/ic_nel_save_as.png rename to code/studio/src/plugins/tile_editor/images/ic_nel_save_as.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/left.png b/code/studio/src/plugins/tile_editor/images/left.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/left.png rename to code/studio/src/plugins/tile_editor/images/left.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/nel.png b/code/studio/src/plugins/tile_editor/images/nel.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/object_viewer/images/nel.png rename to code/studio/src/plugins/tile_editor/images/nel.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png b/code/studio/src/plugins/tile_editor/images/replace_image.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/replace_image.png rename to code/studio/src/plugins/tile_editor/images/replace_image.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png b/code/studio/src/plugins/tile_editor/images/reset.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/reset.png rename to code/studio/src/plugins/tile_editor/images/reset.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png b/code/studio/src/plugins/tile_editor/images/right.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/right.png rename to code/studio/src/plugins/tile_editor/images/right.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation0.png b/code/studio/src/plugins/tile_editor/images/rotation0.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation0.png rename to code/studio/src/plugins/tile_editor/images/rotation0.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png b/code/studio/src/plugins/tile_editor/images/rotation180.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation180.png rename to code/studio/src/plugins/tile_editor/images/rotation180.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation270.png b/code/studio/src/plugins/tile_editor/images/rotation270.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation270.png rename to code/studio/src/plugins/tile_editor/images/rotation270.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation90.png b/code/studio/src/plugins/tile_editor/images/rotation90.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/rotation90.png rename to code/studio/src/plugins/tile_editor/images/rotation90.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/up.png b/code/studio/src/plugins/tile_editor/images/up.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/images/up.png rename to code/studio/src/plugins/tile_editor/images/up.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml rename to code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc b/code/studio/src/plugins/tile_editor/tile_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor.qrc rename to code/studio/src/plugins/tile_editor/tile_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.cpp rename to code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.h rename to code/studio/src/plugins/tile_editor/tile_editor_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_main_window.ui rename to code/studio/src/plugins/tile_editor/tile_editor_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.cpp rename to code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_editor_plugin.h rename to code/studio/src/plugins/tile_editor/tile_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.cpp rename to code/studio/src/plugins/tile_editor/tile_item.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item.h rename to code/studio/src/plugins/tile_editor/tile_item.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp b/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.cpp rename to code/studio/src/plugins/tile_editor/tile_item_delegate.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h b/code/studio/src/plugins/tile_editor/tile_item_delegate.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_item_delegate.h rename to code/studio/src/plugins/tile_editor/tile_item_delegate.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.cpp rename to code/studio/src/plugins/tile_editor/tile_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/tile_editor/tile_model.h rename to code/studio/src/plugins/tile_editor/tile_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/CMakeLists.txt rename to code/studio/src/plugins/translation_manager/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/README b/code/studio/src/plugins/translation_manager/README similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/README rename to code/studio/src/plugins/translation_manager/README diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp b/code/studio/src/plugins/translation_manager/editor_phrase.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.cpp rename to code/studio/src/plugins/translation_manager/editor_phrase.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h b/code/studio/src/plugins/translation_manager/editor_phrase.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_phrase.h rename to code/studio/src/plugins/translation_manager/editor_phrase.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp b/code/studio/src/plugins/translation_manager/editor_worksheet.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.cpp rename to code/studio/src/plugins/translation_manager/editor_worksheet.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h b/code/studio/src/plugins/translation_manager/editor_worksheet.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/editor_worksheet.h rename to code/studio/src/plugins/translation_manager/editor_worksheet.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp b/code/studio/src/plugins/translation_manager/extract_bot_names.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.cpp rename to code/studio/src/plugins/translation_manager/extract_bot_names.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h b/code/studio/src/plugins/translation_manager/extract_bot_names.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_bot_names.h rename to code/studio/src/plugins/translation_manager/extract_bot_names.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp b/code/studio/src/plugins/translation_manager/extract_new_sheet_names.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.cpp rename to code/studio/src/plugins/translation_manager/extract_new_sheet_names.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h b/code/studio/src/plugins/translation_manager/extract_new_sheet_names.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/extract_new_sheet_names.h rename to code/studio/src/plugins/translation_manager/extract_new_sheet_names.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp b/code/studio/src/plugins/translation_manager/ftp_selection.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.cpp rename to code/studio/src/plugins/translation_manager/ftp_selection.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h b/code/studio/src/plugins/translation_manager/ftp_selection.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.h rename to code/studio/src/plugins/translation_manager/ftp_selection.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.qrc b/code/studio/src/plugins/translation_manager/ftp_selection.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.qrc rename to code/studio/src/plugins/translation_manager/ftp_selection.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.ui b/code/studio/src/plugins/translation_manager/ftp_selection.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ftp_selection.ui rename to code/studio/src/plugins/translation_manager/ftp_selection.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/cdtoparent.png b/code/studio/src/plugins/translation_manager/images/cdtoparent.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/cdtoparent.png rename to code/studio/src/plugins/translation_manager/images/cdtoparent.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/dir.png b/code/studio/src/plugins/translation_manager/images/dir.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/dir.png rename to code/studio/src/plugins/translation_manager/images/dir.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/file.png b/code/studio/src/plugins/translation_manager/images/file.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/images/file.png rename to code/studio/src/plugins/translation_manager/images/file.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml b/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml rename to code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp b/code/studio/src/plugins/translation_manager/source_selection.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.cpp rename to code/studio/src/plugins/translation_manager/source_selection.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h b/code/studio/src/plugins/translation_manager/source_selection.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.h rename to code/studio/src/plugins/translation_manager/source_selection.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.ui b/code/studio/src/plugins/translation_manager/source_selection.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/source_selection.ui rename to code/studio/src/plugins/translation_manager/source_selection.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h b/code/studio/src/plugins/translation_manager/translation_manager_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_constants.h rename to code/studio/src/plugins/translation_manager/translation_manager_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h b/code/studio/src/plugins/translation_manager/translation_manager_editor.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_editor.h rename to code/studio/src/plugins/translation_manager/translation_manager_editor.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.cpp rename to code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.h rename to code/studio/src/plugins/translation_manager/translation_manager_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.ui b/code/studio/src/plugins/translation_manager/translation_manager_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_main_window.ui rename to code/studio/src/plugins/translation_manager/translation_manager_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp b/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.cpp rename to code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h b/code/studio/src/plugins/translation_manager/translation_manager_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_plugin.h rename to code/studio/src/plugins/translation_manager/translation_manager_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp b/code/studio/src/plugins/translation_manager/translation_manager_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.cpp rename to code/studio/src/plugins/translation_manager/translation_manager_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h b/code/studio/src/plugins/translation_manager/translation_manager_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.h rename to code/studio/src/plugins/translation_manager/translation_manager_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui b/code/studio/src/plugins/translation_manager/translation_manager_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/translation_manager/translation_manager_settings_page.ui rename to code/studio/src/plugins/translation_manager/translation_manager_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt rename to code/studio/src/plugins/world_editor/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_move.png b/code/studio/src/plugins/world_editor/icons/ic_nel_move.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_move.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_move.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_rotate.png b/code/studio/src/plugins/world_editor/icons/ic_nel_rotate.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_rotate.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_rotate.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_scale.png b/code/studio/src/plugins/world_editor/icons/ic_nel_scale.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_scale.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_scale.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_select.png b/code/studio/src/plugins/world_editor/icons/ic_nel_select.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_select.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_select.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_turn.png b/code/studio/src/plugins/world_editor/icons/ic_nel_turn.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_turn.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_turn.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_world_editor.png b/code/studio/src/plugins/world_editor/icons/ic_nel_world_editor.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/icons/ic_nel_world_editor.png rename to code/studio/src/plugins/world_editor/icons/ic_nel_world_editor.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml b/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml rename to code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp b/code/studio/src/plugins/world_editor/primitive_item.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp rename to code/studio/src/plugins/world_editor/primitive_item.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h b/code/studio/src/plugins/world_editor/primitive_item.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h rename to code/studio/src/plugins/world_editor/primitive_item.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp b/code/studio/src/plugins/world_editor/primitives_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp rename to code/studio/src/plugins/world_editor/primitives_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h b/code/studio/src/plugins/world_editor/primitives_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h rename to code/studio/src/plugins/world_editor/primitives_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp b/code/studio/src/plugins/world_editor/primitives_view.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp rename to code/studio/src/plugins/world_editor/primitives_view.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h b/code/studio/src/plugins/world_editor/primitives_view.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h rename to code/studio/src/plugins/world_editor/primitives_view.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp b/code/studio/src/plugins/world_editor/project_settings_dialog.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp rename to code/studio/src/plugins/world_editor/project_settings_dialog.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.h b/code/studio/src/plugins/world_editor/project_settings_dialog.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.h rename to code/studio/src/plugins/world_editor/project_settings_dialog.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.ui b/code/studio/src/plugins/world_editor/project_settings_dialog.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.ui rename to code/studio/src/plugins/world_editor/project_settings_dialog.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.cpp rename to code/studio/src/plugins/world_editor/property_editor_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.h rename to code/studio/src/plugins/world_editor/property_editor_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.ui b/code/studio/src/plugins/world_editor/property_editor_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/property_editor_widget.ui rename to code/studio/src/plugins/world_editor/property_editor_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor.qrc b/code/studio/src/plugins/world_editor/world_editor.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor.qrc rename to code/studio/src/plugins/world_editor/world_editor.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp b/code/studio/src/plugins/world_editor/world_editor_actions.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp rename to code/studio/src/plugins/world_editor/world_editor_actions.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.h b/code/studio/src/plugins/world_editor/world_editor_actions.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.h rename to code/studio/src/plugins/world_editor/world_editor_actions.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_constants.h b/code/studio/src/plugins/world_editor/world_editor_constants.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_constants.h rename to code/studio/src/plugins/world_editor/world_editor_constants.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_global.h b/code/studio/src/plugins/world_editor/world_editor_global.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_global.h rename to code/studio/src/plugins/world_editor/world_editor_global.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp b/code/studio/src/plugins/world_editor/world_editor_misc.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp rename to code/studio/src/plugins/world_editor/world_editor_misc.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h b/code/studio/src/plugins/world_editor/world_editor_misc.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.h rename to code/studio/src/plugins/world_editor/world_editor_misc.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp b/code/studio/src/plugins/world_editor/world_editor_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp rename to code/studio/src/plugins/world_editor/world_editor_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.h b/code/studio/src/plugins/world_editor/world_editor_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.h rename to code/studio/src/plugins/world_editor/world_editor_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp b/code/studio/src/plugins/world_editor/world_editor_scene.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp rename to code/studio/src/plugins/world_editor/world_editor_scene.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.h b/code/studio/src/plugins/world_editor/world_editor_scene.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.h rename to code/studio/src/plugins/world_editor/world_editor_scene.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp b/code/studio/src/plugins/world_editor/world_editor_scene_item.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp rename to code/studio/src/plugins/world_editor/world_editor_scene_item.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.h b/code/studio/src/plugins/world_editor/world_editor_scene_item.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.h rename to code/studio/src/plugins/world_editor/world_editor_scene_item.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp b/code/studio/src/plugins/world_editor/world_editor_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp rename to code/studio/src/plugins/world_editor/world_editor_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.h b/code/studio/src/plugins/world_editor/world_editor_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.h rename to code/studio/src/plugins/world_editor/world_editor_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.ui b/code/studio/src/plugins/world_editor/world_editor_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.ui rename to code/studio/src/plugins/world_editor/world_editor_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp rename to code/studio/src/plugins/world_editor/world_editor_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h b/code/studio/src/plugins/world_editor/world_editor_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.h rename to code/studio/src/plugins/world_editor/world_editor_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui b/code/studio/src/plugins/world_editor/world_editor_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.ui rename to code/studio/src/plugins/world_editor/world_editor_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/CMakeLists.txt b/code/studio/src/plugins/zone_painter/CMakeLists.txt similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/CMakeLists.txt rename to code/studio/src/plugins/zone_painter/CMakeLists.txt diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-fill.png b/code/studio/src/plugins/zone_painter/images/color-fill.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-fill.png rename to code/studio/src/plugins/zone_painter/images/color-fill.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-picker-black.png b/code/studio/src/plugins/zone_painter/images/color-picker-black.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/color-picker-black.png rename to code/studio/src/plugins/zone_painter/images/color-picker-black.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/colorize.png b/code/studio/src/plugins/zone_painter/images/colorize.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/colorize.png rename to code/studio/src/plugins/zone_painter/images/colorize.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/draw-brush.png b/code/studio/src/plugins/zone_painter/images/draw-brush.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/draw-brush.png rename to code/studio/src/plugins/zone_painter/images/draw-brush.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-down-7.png b/code/studio/src/plugins/zone_painter/images/go-down-7.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-down-7.png rename to code/studio/src/plugins/zone_painter/images/go-down-7.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-jump-4.png b/code/studio/src/plugins/zone_painter/images/go-jump-4.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/go-jump-4.png rename to code/studio/src/plugins/zone_painter/images/go-jump-4.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-6.png b/code/studio/src/plugins/zone_painter/images/lock-6.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-6.png rename to code/studio/src/plugins/zone_painter/images/lock-6.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-silver.png b/code/studio/src/plugins/zone_painter/images/lock-silver.png similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/images/lock-silver.png rename to code/studio/src/plugins/zone_painter/images/lock-silver.png diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml b/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml rename to code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.cpp b/code/studio/src/plugins/zone_painter/painter_dock_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.cpp rename to code/studio/src/plugins/zone_painter/painter_dock_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.h b/code/studio/src/plugins/zone_painter/painter_dock_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.h rename to code/studio/src/plugins/zone_painter/painter_dock_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.ui b/code/studio/src/plugins/zone_painter/painter_dock_widget.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/painter_dock_widget.ui rename to code/studio/src/plugins/zone_painter/painter_dock_widget.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.cpp b/code/studio/src/plugins/zone_painter/qnel_widget.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.cpp rename to code/studio/src/plugins/zone_painter/qnel_widget.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.h b/code/studio/src/plugins/zone_painter/qnel_widget.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/qnel_widget.h rename to code/studio/src/plugins/zone_painter/qnel_widget.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter.qrc b/code/studio/src/plugins/zone_painter/zone_painter.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter.qrc rename to code/studio/src/plugins/zone_painter/zone_painter.qrc diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.cpp b/code/studio/src/plugins/zone_painter/zone_painter_main_window.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_main_window.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.h b/code/studio/src/plugins/zone_painter/zone_painter_main_window.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.h rename to code/studio/src/plugins/zone_painter/zone_painter_main_window.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.ui b/code/studio/src/plugins/zone_painter/zone_painter_main_window.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_main_window.ui rename to code/studio/src/plugins/zone_painter/zone_painter_main_window.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp b/code/studio/src/plugins/zone_painter/zone_painter_model.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_model.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h b/code/studio/src/plugins/zone_painter/zone_painter_model.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_model.h rename to code/studio/src/plugins/zone_painter/zone_painter_model.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp b/code/studio/src/plugins/zone_painter/zone_painter_plugin.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_plugin.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h b/code/studio/src/plugins/zone_painter/zone_painter_plugin.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_plugin.h rename to code/studio/src/plugins/zone_painter/zone_painter_plugin.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.cpp b/code/studio/src/plugins/zone_painter/zone_painter_settings_page.cpp similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.cpp rename to code/studio/src/plugins/zone_painter/zone_painter_settings_page.cpp diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.h b/code/studio/src/plugins/zone_painter/zone_painter_settings_page.h similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.h rename to code/studio/src/plugins/zone_painter/zone_painter_settings_page.h diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.ui b/code/studio/src/plugins/zone_painter/zone_painter_settings_page.ui similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/plugins/zone_painter/zone_painter_settings_page.ui rename to code/studio/src/plugins/zone_painter/zone_painter_settings_page.ui diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_de.ts b/code/studio/src/translations/object_viewer_qt_de.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_de.ts rename to code/studio/src/translations/object_viewer_qt_de.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_en.ts b/code/studio/src/translations/object_viewer_qt_en.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_en.ts rename to code/studio/src/translations/object_viewer_qt_en.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_fr.ts b/code/studio/src/translations/object_viewer_qt_fr.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_fr.ts rename to code/studio/src/translations/object_viewer_qt_fr.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_ru.ts b/code/studio/src/translations/object_viewer_qt_ru.ts similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/object_viewer_qt_ru.ts rename to code/studio/src/translations/object_viewer_qt_ru.ts diff --git a/code/nel/tools/3d/object_viewer_qt/src/translations/translations.qrc b/code/studio/src/translations/translations.qrc similarity index 100% rename from code/nel/tools/3d/object_viewer_qt/src/translations/translations.qrc rename to code/studio/src/translations/translations.qrc From 67ec1cf5be52326891af0dc0342d017c6ce11076 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 7 May 2014 00:50:57 +0200 Subject: [PATCH 021/220] Readding core plugin that was missing because of a hgignore entry. --- .hgignore | 2 +- code/studio/src/plugins/core/CMakeLists.txt | 73 +++ .../src/plugins/core/context_manager.cpp | 167 ++++++ .../studio/src/plugins/core/context_manager.h | 76 +++ code/studio/src/plugins/core/core_constants.h | 121 +++++ code/studio/src/plugins/core/core_global.h | 30 ++ code/studio/src/plugins/core/core_plugin.cpp | 104 ++++ code/studio/src/plugins/core/core_plugin.h | 74 +++ .../plugins/core/general_settings_page.cpp | 241 +++++++++ .../src/plugins/core/general_settings_page.h | 74 +++ .../src/plugins/core/general_settings_page.ui | 233 +++++++++ .../plugins/core/icons/ic_nel_add_item.png | Bin 0 -> 3270 bytes .../src/plugins/core/icons/ic_nel_crash.png | Bin 0 -> 6630 bytes .../plugins/core/icons/ic_nel_delete_item.png | Bin 0 -> 1496 bytes .../plugins/core/icons/ic_nel_down_item.png | Bin 0 -> 3812 bytes .../core/icons/ic_nel_generic_settings.png | Bin 0 -> 5633 bytes .../src/plugins/core/icons/ic_nel_new.png | Bin 0 -> 21396 bytes .../src/plugins/core/icons/ic_nel_open.png | Bin 0 -> 4310 bytes .../core/icons/ic_nel_path_settings.png | Bin 0 -> 4557 bytes .../src/plugins/core/icons/ic_nel_pill.png | Bin 0 -> 9291 bytes .../src/plugins/core/icons/ic_nel_redo.png | Bin 0 -> 4694 bytes .../plugins/core/icons/ic_nel_reset_all.png | Bin 0 -> 5938 bytes .../src/plugins/core/icons/ic_nel_save.png | Bin 0 -> 43738 bytes .../src/plugins/core/icons/ic_nel_save_as.png | Bin 0 -> 52871 bytes .../src/plugins/core/icons/ic_nel_undo.png | Bin 0 -> 4714 bytes .../src/plugins/core/icons/ic_nel_up_item.png | Bin 0 -> 3304 bytes code/studio/src/plugins/core/icontext.h | 76 +++ code/studio/src/plugins/core/icore.h | 70 +++ code/studio/src/plugins/core/icore_listener.h | 63 +++ code/studio/src/plugins/core/images/nel.png | Bin 0 -> 15587 bytes .../src/plugins/core/images/preferences.png | Bin 0 -> 10286 bytes code/studio/src/plugins/core/ioptions_page.h | 75 +++ code/studio/src/plugins/core/main_window.cpp | 492 ++++++++++++++++++ code/studio/src/plugins/core/main_window.h | 147 ++++++ code/studio/src/plugins/core/menu_manager.cpp | 96 ++++ code/studio/src/plugins/core/menu_manager.h | 67 +++ .../src/plugins/core/ovqt_plugin_core.xml | 7 + .../src/plugins/core/plugin_view_dialog.cpp | 108 ++++ .../src/plugins/core/plugin_view_dialog.h | 58 +++ .../src/plugins/core/plugin_view_dialog.ui | 135 +++++ code/studio/src/plugins/core/qtwin.cpp | 241 +++++++++ code/studio/src/plugins/core/qtwin.h | 37 ++ .../core/search_paths_settings_page.cpp | 219 ++++++++ .../plugins/core/search_paths_settings_page.h | 74 +++ .../core/search_paths_settings_page.ui | 198 +++++++ .../src/plugins/core/settings_dialog.cpp | 182 +++++++ .../studio/src/plugins/core/settings_dialog.h | 75 +++ .../src/plugins/core/settings_dialog.ui | 126 +++++ 48 files changed, 3740 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/core/CMakeLists.txt create mode 100644 code/studio/src/plugins/core/context_manager.cpp create mode 100644 code/studio/src/plugins/core/context_manager.h create mode 100644 code/studio/src/plugins/core/core_constants.h create mode 100644 code/studio/src/plugins/core/core_global.h create mode 100644 code/studio/src/plugins/core/core_plugin.cpp create mode 100644 code/studio/src/plugins/core/core_plugin.h create mode 100644 code/studio/src/plugins/core/general_settings_page.cpp create mode 100644 code/studio/src/plugins/core/general_settings_page.h create mode 100644 code/studio/src/plugins/core/general_settings_page.ui create mode 100644 code/studio/src/plugins/core/icons/ic_nel_add_item.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_crash.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_delete_item.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_down_item.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_generic_settings.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_new.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_open.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_path_settings.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_pill.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_redo.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_reset_all.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_save.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_save_as.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_undo.png create mode 100644 code/studio/src/plugins/core/icons/ic_nel_up_item.png create mode 100644 code/studio/src/plugins/core/icontext.h create mode 100644 code/studio/src/plugins/core/icore.h create mode 100644 code/studio/src/plugins/core/icore_listener.h create mode 100644 code/studio/src/plugins/core/images/nel.png create mode 100644 code/studio/src/plugins/core/images/preferences.png create mode 100644 code/studio/src/plugins/core/ioptions_page.h create mode 100644 code/studio/src/plugins/core/main_window.cpp create mode 100644 code/studio/src/plugins/core/main_window.h create mode 100644 code/studio/src/plugins/core/menu_manager.cpp create mode 100644 code/studio/src/plugins/core/menu_manager.h create mode 100644 code/studio/src/plugins/core/ovqt_plugin_core.xml create mode 100644 code/studio/src/plugins/core/plugin_view_dialog.cpp create mode 100644 code/studio/src/plugins/core/plugin_view_dialog.h create mode 100644 code/studio/src/plugins/core/plugin_view_dialog.ui create mode 100644 code/studio/src/plugins/core/qtwin.cpp create mode 100644 code/studio/src/plugins/core/qtwin.h create mode 100644 code/studio/src/plugins/core/search_paths_settings_page.cpp create mode 100644 code/studio/src/plugins/core/search_paths_settings_page.h create mode 100644 code/studio/src/plugins/core/search_paths_settings_page.ui create mode 100644 code/studio/src/plugins/core/settings_dialog.cpp create mode 100644 code/studio/src/plugins/core/settings_dialog.h create mode 100644 code/studio/src/plugins/core/settings_dialog.ui diff --git a/.hgignore b/.hgignore index 530c92512..5587652fd 100644 --- a/.hgignore +++ b/.hgignore @@ -43,7 +43,7 @@ default_c *.so *.so.* *_debug -core +core.* *.pc *.gch diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt new file mode 100644 index 000000000..5a20ba46c --- /dev/null +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -0,0 +1,73 @@ +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_CORE_PLUGIN_HDR + icore.h + icontext.h + icore_listener.h + ioptions_page.h + core_plugin.h + core.h + main_window.h + menu_manager.h + context_manager.h + settings_dialog.h + search_paths_settings_page.h + general_settings_page.h + plugin_view_dialog.h +) + +SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui + plugin_view_dialog.ui + general_settings_page.ui + search_paths_settings_page.ui +) + +SET(OVQT_CORE_PLUGIN_RCS core.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_ADD_RESOURCES(OVQT_CORE_PLUGIN_RC_SRCS ${OVQT_CORE_PLUGIN_RCS}) +QT4_WRAP_CPP(OVQT_CORE_PLUGIN_MOC_SRC ${OVQT_CORE_PLUGIN_HDR}) +QT4_WRAP_UI(OVQT_CORE_PLUGIN_UI_HDRS ${OVQT_CORE_PLUGIN_UIS}) + +SOURCE_GROUP(QtResources FILES ${OVQT_CORE_PLUGIN_UIS} ${OVQT_CORE_PLUGIN_RCS}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_CORE_PLUGIN_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) +SOURCE_GROUP("Core Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) + +TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) + +NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) +NL_ADD_LIB_SUFFIX(ovqt_plugin_core) + +ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +IF(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ELSE(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ENDIF(WIN32) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) + diff --git a/code/studio/src/plugins/core/context_manager.cpp b/code/studio/src/plugins/core/context_manager.cpp new file mode 100644 index 000000000..8355b5cb8 --- /dev/null +++ b/code/studio/src/plugins/core/context_manager.cpp @@ -0,0 +1,167 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "context_manager.h" +#include "icontext.h" +#include "main_window.h" + +// NeL includes +#include + +// Qt includes +#include +#include + +namespace Core +{ + +struct ContextManagerPrivate +{ + explicit ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget); + Core::MainWindow *m_mainWindow; + QTabWidget *m_tabWidget; + QVector m_contexts; + int m_oldCurrent; +}; + +ContextManagerPrivate::ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget) + : m_mainWindow(mainWindow), + m_tabWidget(tabWidget), + m_oldCurrent(-1) +{ +} + +ContextManager::ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget) + : d(new ContextManagerPrivate(mainWindow, tabWidget)) +{ + QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(objectAdded(QObject *)), + this, SLOT(objectAdded(QObject *))); + QObject::connect(d->m_mainWindow->pluginManager(), SIGNAL(aboutToRemoveObject(QObject *)), + this, SLOT(aboutToRemoveObject(QObject *))); + + QObject::connect(d->m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); +} + +ContextManager::~ContextManager() +{ + delete d; +} + +Core::IContext *ContextManager::currentContext() const +{ + int currentIndex = d->m_tabWidget->currentIndex(); + if (currentIndex < 0) + return 0; + return d->m_contexts.at(currentIndex); +} + +Core::IContext *ContextManager::context(const QString &id) const +{ + const int index = indexOf(id); + if (index >= 0) + return d->m_contexts.at(index); + return 0; +} + +void ContextManager::registerUndoStack(QUndoStack *stack) +{ + nlassert(stack); + d->m_mainWindow->undoGroup()->addStack(stack); +} + +void ContextManager::unregisterUndoStack(QUndoStack *stack) +{ + nlassert(stack); + d->m_mainWindow->undoGroup()->removeStack(stack); +} + +void ContextManager::activateContext(const QString &id) +{ + const int index = indexOf(id); + if (index >= 0) + d->m_tabWidget->setCurrentIndex(index); +} + +void ContextManager::updateCurrentContext() +{ + d->m_mainWindow->updateContext(currentContext()); +} + +void ContextManager::objectAdded(QObject *obj) +{ + IContext *context = qobject_cast(obj); + if (context) + addContextObject(context); +} + +void ContextManager::aboutToRemoveObject(QObject *obj) +{ + IContext *context = qobject_cast(obj); + if (context) + removeContextObject(context); +} + +void ContextManager::addContextObject(IContext *context) +{ + d->m_contexts.push_back(context); + d->m_mainWindow->addContextObject(context); + + QWidget *tabWidget = new QWidget(d->m_tabWidget); + d->m_tabWidget->addTab(tabWidget, context->icon(), context->trName()); + QGridLayout *gridLayout = new QGridLayout(tabWidget); + gridLayout->setObjectName(QString::fromUtf8("gridLayout_") + context->id()); + gridLayout->setContentsMargins(0, 0, 0, 0); + gridLayout->addWidget(context->widget(), 0, 0, 1, 1); +} + +void ContextManager::removeContextObject(IContext *context) +{ + d->m_mainWindow->removeContextObject(context); + + const int index = indexOf(context->id()); + QWidget *widget = d->m_tabWidget->widget(index); + d->m_tabWidget->removeTab(index); + d->m_contexts.remove(index); + delete widget; +} + +void ContextManager::currentTabChanged(int index) +{ + if (index >= 0) + { + IContext *context = d->m_contexts.at(index); + IContext *oldContext = 0; + if (d->m_oldCurrent >= 0) + oldContext = d->m_contexts.at(d->m_oldCurrent); + d->m_oldCurrent = index; + Q_EMIT currentContextChanged(context, oldContext); + } +} + +int ContextManager::indexOf(const QString &id) const +{ + for (int i = 0; i < d->m_contexts.count(); ++i) + { + if (d->m_contexts.at(i)->id() == id) + return i; + } + nlwarning(QString("Warning, no such context: %1").arg(id).toUtf8().constData()); + return -1; +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/context_manager.h b/code/studio/src/plugins/core/context_manager.h new file mode 100644 index 000000000..8151648e7 --- /dev/null +++ b/code/studio/src/plugins/core/context_manager.h @@ -0,0 +1,76 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CONTEXT_MANAGER_H +#define CONTEXT_MANAGER_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include + +QT_BEGIN_NAMESPACE +class QTabWidget; +class QUndoStack; +QT_END_NAMESPACE + +namespace Core +{ +class IContext; +class MainWindow; +struct ContextManagerPrivate; + +class CORE_EXPORT ContextManager : public QObject +{ + Q_OBJECT + +public: + explicit ContextManager(Core::MainWindow *mainWindow, QTabWidget *tabWidget); + virtual ~ContextManager(); + + Core::IContext *currentContext() const; + Core::IContext *context(const QString &id) const; + + // temporary solution for multiple undo stacks per context + void registerUndoStack(QUndoStack *stack); + void unregisterUndoStack(QUndoStack *stack); + +Q_SIGNALS: + // the default argument '=0' is important for connects without the oldContext argument. + void currentContextChanged(Core::IContext *context, Core::IContext *oldContext = 0); + +public Q_SLOTS: + void activateContext(const QString &id); + void updateCurrentContext(); + +private Q_SLOTS: + void objectAdded(QObject *obj); + void aboutToRemoveObject(QObject *obj); + void addContextObject(IContext *context); + void removeContextObject(IContext *context); + void currentTabChanged(int index); + +private: + int indexOf(const QString &id) const; + + ContextManagerPrivate *d; +}; + +} // namespace Core + +#endif // CONTEXT_MANAGER_H diff --git a/code/studio/src/plugins/core/core_constants.h b/code/studio/src/plugins/core/core_constants.h new file mode 100644 index 000000000..8bf6d5fcd --- /dev/null +++ b/code/studio/src/plugins/core/core_constants.h @@ -0,0 +1,121 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2010 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_CONSTANTS_H +#define CORE_CONSTANTS_H + +namespace Core +{ +namespace Constants +{ + +const char *const OVQT_VERSION_LONG = "0.8"; +const char *const OVQT_VENDOR = "Ryzom Core"; +const char *const OVQT_YEAR = "2010, 2011"; +const char *const OVQT_CORE_PLUGIN = "Core"; + +//mainwindow +const char *const MAIN_WINDOW = "ObjectViewerQt.MainWindow"; + +//menubar +const char *const MENU_BAR = "ObjectViewerQt.MenuBar"; + +//menus +const char *const M_FILE = "ObjectViewerQt.Menu.File"; +const char *const M_EDIT = "ObjectViewerQt.Menu.Edit"; +const char *const M_VIEW = "ObjectViewerQt.Menu.View"; +const char *const M_SCENE = "ObjectViewerQt.Menu.Scene"; +const char *const M_TOOLS = "ObjectViewerQt.Menu.Tools"; +const char *const M_WINDOW = "ObjectViewerQt.Menu.Window"; +const char *const M_HELP = "ObjectViewerQt.Menu.Help"; + +const char *const M_FILE_RECENTFILES = "ObjectViewerQt.Menu.File.RecentFiles"; +const char *const M_SHEET = "ObjectViewerQt.Menu.Sheet"; + +//actions +const char *const NEW = "ObjectViewerQt.New"; +const char *const OPEN = "ObjectViewerQt.Open"; +const char *const SAVE = "ObjectViewerQt.Save"; +const char *const SAVE_AS = "ObjectViewerQt.SaveAs"; +const char *const SAVE_ALL = "ObjectViewerQt.SaveAll"; +const char *const EXIT = "ObjectViewerQt.Exit"; + +const char *const UNDO = "ObjectViewerQt.Undo"; +const char *const REDO = "ObjectViewerQt.Redo"; +const char *const CUT = "ObjectViewerQt.Cut"; +const char *const COPY = "ObjectViewerQt.Copy"; +const char *const PASTE = "ObjectViewerQt.Paste"; +const char *const DEL = "ObjectViewerQt.Del"; +const char *const FIND = "ObjectViewerQt.Find"; +const char *const SELECT_ALL = "ObjectViewerQt.SelectAll"; +const char *const GOTO_POS = "ObjectViewerQt.Goto"; + +const char *const SETTINGS = "ObjectViewerQt.Settings"; +const char *const TOGGLE_FULLSCREEN = "ObjectViewerQt.ToggleFullScreen"; + +const char *const CLOSE = "ObjectViewerQt.Close"; +const char *const CLOSEALL = "ObjectViewerQt.CloseAll"; +const char *const CLOSEOTHERS = "ObjectViewerQt.CloseOthers"; +const char *const ABOUT = "ObjectViewerQt.About"; +const char *const ABOUT_PLUGINS = "ObjectViewerQt.AboutPlugins"; +const char *const ABOUT_QT = "ObjectViewerQt.AboutQt"; + +//settings +const char *const SETTINGS_CATEGORY_GENERAL = "general"; +const char *const SETTINGS_CATEGORY_GENERAL_ICON = ":/icons/ic_nel_generic_settings.png"; +const char *const SETTINGS_TR_CATEGORY_GENERAL = QT_TR_NOOP("General"); + +const char *const MAIN_WINDOW_SECTION = "MainWindow"; +const char *const MAIN_WINDOW_STATE = "WindowState"; +const char *const MAIN_WINDOW_GEOMETRY = "WindowGeometry"; +const char *const QT_STYLE = "QtStyle"; +const char *const QT_PALETTE = "QtPalette"; + +const char *const LANGUAGE = "Language"; +const char *const PLUGINS_PATH = "PluginPath"; +const char *const DATA_PATH_SECTION = "DataPath"; +const char *const SEARCH_PATHS = "SearchPaths"; +const char *const RECURSIVE_SEARCH_PATHS = "RecursiveSearchPathes"; +const char *const LEVELDESIGN_PATH = "LevelDesignPath"; +const char *const PRIMITIVES_PATH = "PrimitivesPath"; +const char *const ASSETS_PATH = "AssetsPath"; +const char *const LIGOCONFIG_FILE = "LigoConfigFile"; +const char *const REMAP_EXTENSIONS = "RemapExtensions"; + +const char *const LOG_SECTION = "LogSettings"; +const char *const LOG_ERROR = "LogError"; +const char *const LOG_WARNING = "LogWarning"; +const char *const LOG_DEBUG = "LogDebug"; +const char *const LOG_ASSERT = "LogAssert"; +const char *const LOG_INFO = "LogInfo"; + +//resources +const char *const ICON_NEL = ":/core/images/nel.png"; +const char *const ICON_SETTINGS = ":/core/images/preferences.png"; +const char *const ICON_PILL = ":/core/icons/ic_nel_pill.png"; +const char *const ICON_OPEN = ":/core/icons/ic_nel_open.png"; +const char *const ICON_NEW = ":/core/icons/ic_nel_new.png"; +const char *const ICON_SAVE = ":/core/icons/ic_nel_save.png"; +const char *const ICON_SAVE_AS = ":/core/icons/ic_nel_save_as.png"; +const char *const ICON_CRASH = ":/core/icons/ic_nel_crash.png"; +const char *const ICON_UNDO = ":/core/icons/ic_nel_undo.png"; +const char *const ICON_REDO = ":/core/icons/ic_nel_redo.png"; + +} // namespace Constants +} // namespace Core + +#endif // CORE_CONSTANTS_H diff --git a/code/studio/src/plugins/core/core_global.h b/code/studio/src/plugins/core/core_global.h new file mode 100644 index 000000000..48fe0ece9 --- /dev/null +++ b/code/studio/src/plugins/core/core_global.h @@ -0,0 +1,30 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_GLOBAL_H +#define CORE_GLOBAL_H + +#include + +#if defined(CORE_LIBRARY) +# define CORE_EXPORT Q_DECL_EXPORT +#else +# define CORE_EXPORT Q_DECL_IMPORT +#endif + +#endif // CORE_GLOBAL_H diff --git a/code/studio/src/plugins/core/core_plugin.cpp b/code/studio/src/plugins/core/core_plugin.cpp new file mode 100644 index 000000000..a72a68ccc --- /dev/null +++ b/code/studio/src/plugins/core/core_plugin.cpp @@ -0,0 +1,104 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2010 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "core_plugin.h" +#include "settings_dialog.h" +#include "core_constants.h" +#include "search_paths_settings_page.h" +#include "general_settings_page.h" +#include "../../extension_system/iplugin_spec.h" + +// NeL includes +#include "nel/misc/debug.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +using namespace Core; + +CorePlugin::CorePlugin() + : m_plugMan(0), + m_mainWindow(0) +{ +} + +CorePlugin::~CorePlugin() +{ + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); + + if (m_mainWindow) + delete m_mainWindow; +} + +bool CorePlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + Q_UNUSED(errorString); + m_plugMan = pluginManager; + + m_mainWindow = new MainWindow(pluginManager); + bool success = m_mainWindow->initialize(errorString); + + GeneralSettingsPage *generalSettings = new GeneralSettingsPage(this); + SearchPathsSettingsPage *searchPathPage = new SearchPathsSettingsPage(false, this); + SearchPathsSettingsPage *recureseSearchPathPage = new SearchPathsSettingsPage(true, this); + + generalSettings->applyGeneralSettings(); + searchPathPage->applySearchPaths(); + recureseSearchPathPage->applySearchPaths(); + addAutoReleasedObject(generalSettings); + addAutoReleasedObject(searchPathPage); + addAutoReleasedObject(recureseSearchPathPage); + return success; +} + +void CorePlugin::extensionsInitialized() +{ + m_mainWindow->extensionsInitialized(); +} + +void CorePlugin::shutdown() +{ +} + +void CorePlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_libContext = new NLMISC::CLibraryContext(*nelContext); +} + +void CorePlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +Q_EXPORT_PLUGIN(CorePlugin) diff --git a/code/studio/src/plugins/core/core_plugin.h b/code/studio/src/plugins/core/core_plugin.h new file mode 100644 index 000000000..5062227e3 --- /dev/null +++ b/code/studio/src/plugins/core/core_plugin.h @@ -0,0 +1,74 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2010 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_PLUGIN_H +#define CORE_PLUGIN_H + +#include "../../extension_system/iplugin.h" +#include "main_window.h" + +#include "nel/misc/app_context.h" + +#include + +namespace NLMISC +{ +class CLibraryContext; +} + +namespace ExtensionSystem +{ +class IPluginSpec; +} + +namespace Core +{ + +class CorePlugin : public QObject, public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_INTERFACES(ExtensionSystem::IPlugin) +public: + + CorePlugin(); + virtual ~CorePlugin(); + + bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); + void extensionsInitialized(); + void shutdown(); + + void setNelContext(NLMISC::INelContext *nelContext); + + void addAutoReleasedObject(QObject *obj); + + ExtensionSystem::IPluginManager *pluginManager() const + { + return m_plugMan; + } + +protected: + NLMISC::CLibraryContext *m_libContext; + +private: + ExtensionSystem::IPluginManager *m_plugMan; + MainWindow *m_mainWindow; + QList m_autoReleaseObjects; +}; + +} // namespace Core + +#endif // CORE_PLUGIN_H diff --git a/code/studio/src/plugins/core/general_settings_page.cpp b/code/studio/src/plugins/core/general_settings_page.cpp new file mode 100644 index 000000000..bfbb06d66 --- /dev/null +++ b/code/studio/src/plugins/core/general_settings_page.cpp @@ -0,0 +1,241 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "general_settings_page.h" +#include "core_constants.h" +#include "icore.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +namespace Core +{ + +GeneralSettingsPage::GeneralSettingsPage(QObject *parent) + : IOptionsPage(parent), + m_page(0) +{ + m_originalPalette = QApplication::palette(); +} + +GeneralSettingsPage::~GeneralSettingsPage() +{ +} + +QString GeneralSettingsPage::id() const +{ + return QLatin1String("general_settings"); +} + +QString GeneralSettingsPage::trName() const +{ + return tr("General"); +} + +QString GeneralSettingsPage::category() const +{ + return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); +} + +QString GeneralSettingsPage::trCategory() const +{ + return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); +} + +QIcon GeneralSettingsPage::categoryIcon() const +{ + return QIcon(); +} + +void GeneralSettingsPage::applyGeneralSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + + settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + QApplication::setStyle(QStyleFactory::create(settings->value(Constants::QT_STYLE, "").toString())); + + if (settings->value(Constants::QT_PALETTE, true).toBool()) + QApplication::setPalette(QApplication::style()->standardPalette()); + else + QApplication::setPalette(m_originalPalette); + settings->endGroup(); + + QString levelDesignPrefix; +#if defined(_DEBUG) && defined(NL_OS_WINDOWS) + levelDesignPrefix = "l:"; +#else + levelDesignPrefix = QString("%1/data_leveldesign").arg(RYZOM_SHARE_PREFIX); +#endif + + // Add primitives path and ligo config file to CPath + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + QString primitivePath = settings->value(Core::Constants::PRIMITIVES_PATH, QString("%1/primitives").arg(levelDesignPrefix)).toString(); + QString ligoConfigFile = settings->value(Core::Constants::LIGOCONFIG_FILE, QString("%1/leveldesign/world_editor_files/world_editor_classes.xml").arg(levelDesignPrefix)).toString(); + QString leveldesignPath = settings->value(Core::Constants::LEVELDESIGN_PATH, QString("%1/leveldesign").arg(levelDesignPrefix)).toString(); + NLMISC::CPath::addSearchPath(primitivePath.toUtf8().constData(), true, false); + NLMISC::CPath::display(); + NLMISC::CPath::addSearchFile(ligoConfigFile.toUtf8().constData()); + NLMISC::CPath::addSearchPath(leveldesignPath.toUtf8().constData(), true, false); + settings->endGroup(); +} + +QWidget *GeneralSettingsPage::createPage(QWidget *parent) +{ + m_page = new QWidget(parent); + m_ui.setupUi(m_page); + + readSettings(); + connect(m_ui.languageComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(changeLanguage(QString))); + connect(m_ui.pluginsPathButton, SIGNAL(clicked()), this, SLOT(setPluginsPath())); + connect(m_ui.leveldesignPathButton, SIGNAL(clicked()), this, SLOT(setLevelDesignPath())); + connect(m_ui.assetsPathButton, SIGNAL(clicked()), this, SLOT(setAssetsPath())); + connect(m_ui.primitivesPathButton, SIGNAL(clicked()), this, SLOT(setPrimitivesPath())); + connect(m_ui.ligoConfigFileButton, SIGNAL(clicked()), this, SLOT(setLigoConfigFile())); + return m_page; +} + +void GeneralSettingsPage::apply() +{ + writeSettings(); + applyGeneralSettings(); +} + +void GeneralSettingsPage::finish() +{ + delete m_page; + m_page = 0; +} + +void GeneralSettingsPage::changeLanguage(const QString &lang) +{ + QMessageBox::information(0, tr("Restart required"), + tr("The language change will take effect after a restart of Object Viewer Qt.")); +} + +void GeneralSettingsPage::setPluginsPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the plugins path"), + m_ui.pluginsPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.pluginsPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::setLevelDesignPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the level design path"), + m_ui.leveldesignPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.leveldesignPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::setPrimitivesPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the primitives path"), + m_ui.primitivesPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.primitivesPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::setLigoConfigFile() +{ + QString newFile = QFileDialog::getOpenFileName(0, tr("Set the ligo config file"), + m_ui.ligoConfigFileLineEdit->text()); + if (!newFile.isEmpty()) + { + m_ui.ligoConfigFileLineEdit->setText(newFile); + } +} + + +void GeneralSettingsPage::setAssetsPath() +{ + QString newPath = QFileDialog::getExistingDirectory(0, tr("Set the assets path"), + m_ui.assetsPathLineEdit->text()); + if (!newPath.isEmpty()) + { + m_ui.assetsPathLineEdit->setText(newPath); + } +} + +void GeneralSettingsPage::readSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + + m_ui.pluginsPathLineEdit->setText(settings->value(Core::Constants::PLUGINS_PATH, "./plugins").toString()); + + settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + m_ui.styleComboBox->addItems(QStyleFactory::keys()); + QString style = settings->value(Constants::QT_STYLE, "").toString(); + if (style == "") + m_ui.styleComboBox->setCurrentIndex(0); + else + m_ui.styleComboBox->setCurrentIndex(m_ui.styleComboBox->findText(style)); + m_ui.paletteCheckBox->setChecked(settings->value(Constants::QT_PALETTE, true).toBool()); + settings->endGroup(); + + QStringList paths; + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + m_ui.leveldesignPathLineEdit->setText(settings->value(Core::Constants::LEVELDESIGN_PATH, "l:/leveldesign").toString()); + m_ui.assetsPathLineEdit->setText(settings->value(Core::Constants::ASSETS_PATH, "w:/database").toString()); + m_ui.primitivesPathLineEdit->setText(settings->value(Core::Constants::PRIMITIVES_PATH, "l:/primitives").toString()); + m_ui.ligoConfigFileLineEdit->setText(settings->value(Core::Constants::LIGOCONFIG_FILE, "l:/leveldesign/world_editor_files/world_editor_classes.xml").toString()); + settings->endGroup(); +} + +void GeneralSettingsPage::writeSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + + settings->setValue(Core::Constants::PLUGINS_PATH, m_ui.pluginsPathLineEdit->text()); + + settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + if (m_ui.styleComboBox->currentIndex() == 0) + settings->setValue(Constants::QT_STYLE, ""); + else + settings->setValue(Constants::QT_STYLE, m_ui.styleComboBox->currentText()); + settings->setValue(Constants::QT_PALETTE, m_ui.paletteCheckBox->isChecked()); + settings->endGroup(); + + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + settings->setValue(Core::Constants::LEVELDESIGN_PATH, m_ui.leveldesignPathLineEdit->text()); + settings->setValue(Core::Constants::ASSETS_PATH, m_ui.assetsPathLineEdit->text()); + settings->setValue(Core::Constants::PRIMITIVES_PATH, m_ui.primitivesPathLineEdit->text()); + settings->setValue(Core::Constants::LIGOCONFIG_FILE, m_ui.ligoConfigFileLineEdit->text()); + settings->endGroup(); + settings->sync(); +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/general_settings_page.h b/code/studio/src/plugins/core/general_settings_page.h new file mode 100644 index 000000000..66eacd189 --- /dev/null +++ b/code/studio/src/plugins/core/general_settings_page.h @@ -0,0 +1,74 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef GENERAL_SETTINGS_PAGE_H +#define GENERAL_SETTINGS_PAGE_H + +#include + +#include "ioptions_page.h" + +#include "ui_general_settings_page.h" + +class QWidget; + +namespace Core +{ +/** +@class GeneralSettingsPage +*/ +class GeneralSettingsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + explicit GeneralSettingsPage(QObject *parent = 0); + ~GeneralSettingsPage(); + + QString id() const; + QString trName() const; + QString category() const; + QString trCategory() const; + QIcon categoryIcon() const; + QWidget *createPage(QWidget *parent); + + void apply(); + void finish(); + + void applyGeneralSettings(); + +private Q_SLOTS: + void changeLanguage(const QString &lang); + void setPluginsPath(); + void setLevelDesignPath(); + void setAssetsPath(); + void setPrimitivesPath(); + void setLigoConfigFile(); + +private: + void readSettings(); + void writeSettings(); + + QPalette m_originalPalette; + QWidget *m_page; + Ui::GeneralSettingsPage m_ui; +}; + +} // namespace Core + +#endif // GENERAL_SETTINGS_H diff --git a/code/studio/src/plugins/core/general_settings_page.ui b/code/studio/src/plugins/core/general_settings_page.ui new file mode 100644 index 000000000..7d40b65df --- /dev/null +++ b/code/studio/src/plugins/core/general_settings_page.ui @@ -0,0 +1,233 @@ + + + GeneralSettingsPage + + + + 0 + 0 + 267 + 282 + + + + Form + + + + 6 + + + 3 + + + + + Qt Style + + + + 6 + + + 6 + + + + + + default + + + + + + + + Use style's standard palette + + + + + + + + + + Language + + + + 6 + + + + + false + + + + English + + + + + German + + + + + French + + + + + Russian + + + + + + + + + + + Paths + + + + 6 + + + 6 + + + + + Plugins + + + + + + + + 0 + 0 + + + + + + + + ... + + + + + + + Sheets + + + + + + + + 0 + 0 + + + + + + + + ... + + + + + + + Assets Database: + + + + + + + + 0 + 0 + + + + + + + + ... + + + + + + + Primitives + + + + + + + + + + ... + + + + + + + + + + Ligo Config File + + + + + + + ... + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + diff --git a/code/studio/src/plugins/core/icons/ic_nel_add_item.png b/code/studio/src/plugins/core/icons/ic_nel_add_item.png new file mode 100644 index 0000000000000000000000000000000000000000..bde338f7851d2675b29272c7dcf9471196a8f6cc GIT binary patch literal 3270 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 Eg5p97)c^nh literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_crash.png b/code/studio/src/plugins/core/icons/ic_nel_crash.png new file mode 100644 index 0000000000000000000000000000000000000000..5e1f6380bad86acca278838ce7a1c6499eb2660f GIT binary patch literal 6630 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 literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_down_item.png b/code/studio/src/plugins/core/icons/ic_nel_down_item.png new file mode 100644 index 0000000000000000000000000000000000000000..fc86c4f6db072ec99ee76b81b8ea21d607226dd7 GIT binary patch literal 3812 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 literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_open.png b/code/studio/src/plugins/core/icons/ic_nel_open.png new file mode 100644 index 0000000000000000000000000000000000000000..c4992affd19cf3a55bb8ec2f3121e5befa69a55c GIT binary patch literal 4310 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 rVX-&N2bPDNB8 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 UsoZjLV*mgE07*qoM6N<$g2^9G?f?J) literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_save.png b/code/studio/src/plugins/core/icons/ic_nel_save.png new file mode 100644 index 0000000000000000000000000000000000000000..5aeb3bbe94a27c3528cecf0f2e849fb82a85b4b3 GIT binary patch literal 43738 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 %I{nv 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 literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/icons/ic_nel_save_as.png b/code/studio/src/plugins/core/icons/ic_nel_save_as.png new file mode 100644 index 0000000000000000000000000000000000000000..6cb71a33436e58801b73476821800b1b95a1018e GIT binary patch literal 52871 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 mw#_~9)Gt2qq5{#N!2bXMO`x+Fh$+(m0000 +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ICONTEXT_H +#define ICONTEXT_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QWidget; +class QUndoStack; +QT_END_NAMESPACE + +namespace Core +{ +/** +@interface IContext +@brief The IContext is an interface for providing tab pages in main window. +@details You need to subclass this interface and put an instance of your subclass + into the plugin manager object pool. +*/ +class CORE_EXPORT IContext: public QObject +{ + Q_OBJECT +public: + IContext(QObject *parent = 0): QObject(parent) {} + virtual ~IContext() {} + + /// id() is a unique identifier for referencing this page + virtual QString id() const = 0; + + /// trName() is the (translated) name for display. + virtual QString trName() const = 0; + + /// icon() is the icon for display + virtual QIcon icon() const = 0; + + /// The widget will be destroyed by the widget hierarchy when the main window closes + virtual QWidget *widget() = 0; + + virtual QUndoStack *undoStack() = 0; + + virtual void open() = 0; + + virtual void save(){} + + virtual void saveAs(){} + + virtual void newDocument(){} + + virtual void close(){} +}; + +} // namespace Core + +#endif // ICONTEXT_H diff --git a/code/studio/src/plugins/core/icore.h b/code/studio/src/plugins/core/icore.h new file mode 100644 index 000000000..4f1ee474f --- /dev/null +++ b/code/studio/src/plugins/core/icore.h @@ -0,0 +1,70 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ICORE_H +#define ICORE_H + +#include "core_global.h" + +#include + +QT_BEGIN_NAMESPACE +class QMainWindow; +class QSettings; +QT_END_NAMESPACE + +namespace ExtensionSystem +{ +class IPluginManager; +} + +namespace Core +{ +class MenuManager; +class ContextManager; + +class CORE_EXPORT ICore : public QObject +{ + Q_OBJECT + +public: + ICore() {} + virtual ~ICore() {} + + static ICore *instance(); + + virtual bool showOptionsDialog(const QString &group = QString(), + const QString &page = QString(), + QWidget *parent = 0) = 0; + + virtual MenuManager *menuManager() const = 0; + virtual ContextManager *contextManager() const = 0; + + virtual QSettings *settings() const = 0; + virtual QMainWindow *mainWindow() const = 0; + + virtual ExtensionSystem::IPluginManager *pluginManager() const = 0; + +Q_SIGNALS: + void changeSettings(); + void closeMainWindow(); +}; + +} // namespace Core + +#endif // ICORE_H diff --git a/code/studio/src/plugins/core/icore_listener.h b/code/studio/src/plugins/core/icore_listener.h new file mode 100644 index 000000000..c27e40242 --- /dev/null +++ b/code/studio/src/plugins/core/icore_listener.h @@ -0,0 +1,63 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ICORE_LISTENER_H +#define ICORE_LISTENER_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include + +QT_BEGIN_NAMESPACE +class QWidget; +QT_END_NAMESPACE + +namespace Core +{ +/** +@interface ICoreListener +@brief The ICoreListener is an interface for providing a hook for plugins to veto on close event emitted from +the core plugin. +@details You implement this interface if you want to prevent the closing of the whole application. +If the application window requests a close, then first ICoreListener::closeMainWindow() is called +(in arbitrary order) on all registered objects implementing this interface. +If one if these calls returns false, the process is aborted and the event is ignored. If all calls return +true, the corresponding signal is emitted and the event is accepted/performed. + +You need to add your implementing object to the plugin managers objects: +PluginManager->addObject(yourImplementingObject); +Don't forget to remove the object again at deconstruction (e.g. in the destructor of +your plugin) +*/ +class CORE_EXPORT ICoreListener: public QObject +{ + Q_OBJECT +public: + ICoreListener(QObject *parent = 0): QObject(parent) {} + virtual ~ICoreListener() {} + + /// Return false from the implemented method if you want to prevent the event. + virtual bool closeMainWindow() const = 0; +}; + +} // namespace Core + + +#endif // ICORE_LISTENER_H diff --git a/code/studio/src/plugins/core/images/nel.png b/code/studio/src/plugins/core/images/nel.png new file mode 100644 index 0000000000000000000000000000000000000000..d2139bb2557984f999a563059ea00f7e76436293 GIT binary patch literal 15587 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 literal 0 HcmV?d00001 diff --git a/code/studio/src/plugins/core/images/preferences.png b/code/studio/src/plugins/core/images/preferences.png new file mode 100644 index 0000000000000000000000000000000000000000..729bc039355928ae3b0c39969f6dbfea6154a125 GIT binary patch literal 10286 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 +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef IOPTIONS_PAGE_H +#define IOPTIONS_PAGE_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include + +QT_BEGIN_NAMESPACE +class QWidget; +class QIcon; +QT_END_NAMESPACE + +namespace Core +{ +/** +@interface IOptionsPage +@brief The IOptionsPage is an interface for providing options pages. +@details You need to subclass this interface and put an instance of your subclass + into the plugin manager object pool. +*/ +class CORE_EXPORT IOptionsPage: public QObject +{ + Q_OBJECT +public: + IOptionsPage(QObject *parent = 0): QObject(parent) {} + virtual ~IOptionsPage() {} + + /// id() is a unique identifier for referencing this page + virtual QString id() const = 0; + + /// trName() is the (translated) name for display. + virtual QString trName() const = 0; + + /// category() is the unique id for the category that the page should be displayed in + virtual QString category() const = 0; + + /// trCategory() is the translated category + virtual QString trCategory() const = 0; + + virtual QIcon categoryIcon() const = 0; + + /// createPage() is called to retrieve the widget to show in the preferences dialog + /// The widget will be destroyed by the widget hierarchy when the dialog closes + virtual QWidget *createPage(QWidget *parent) = 0; + + /// apply() is called to store the settings. It should detect if any changes have been made and store those. + virtual void apply() = 0; + + /// finish() is called directly before the preferences dialog closes + virtual void finish() = 0; +}; + +} // namespace Core + +#endif // IOPTIONS_PAGE_H diff --git a/code/studio/src/plugins/core/main_window.cpp b/code/studio/src/plugins/core/main_window.cpp new file mode 100644 index 000000000..a90e67bc0 --- /dev/null +++ b/code/studio/src/plugins/core/main_window.cpp @@ -0,0 +1,492 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "main_window.h" +#include "icontext.h" +#include "icore_listener.h" +#include "menu_manager.h" +#include "context_manager.h" +#include "core.h" +#include "core_constants.h" +#include "settings_dialog.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include + +namespace Core +{ + +MainWindow::MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) + : QMainWindow(parent), + m_pluginManager(0), + m_menuManager(0), + m_contextManager(0), + m_coreImpl(0), + m_lastDir("."), + m_undoGroup(0), + m_settings(0) +{ + QCoreApplication::setApplicationName(QLatin1String("ObjectViewerQt")); + QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::OVQT_VERSION_LONG)); + QCoreApplication::setOrganizationName(QLatin1String("RyzomCore")); + + setObjectName(Constants::MAIN_WINDOW); + setWindowIcon(QIcon(Constants::ICON_PILL)); + setWindowTitle(tr("Object Viewer Qt")); + + m_pluginManager = pluginManager; + m_settings = m_pluginManager->settings(); + m_coreImpl = new CoreImpl(this); + +#ifdef Q_WS_MAC + m_menuBar = new QMenuBar(0); +#else + m_menuBar = new QMenuBar(this); + setMenuBar(m_menuBar); +#endif + + m_menuManager = new MenuManager(m_menuBar, this); + + m_tabWidget = new QTabWidget(this); + m_tabWidget->setTabPosition(QTabWidget::South); + m_tabWidget->setMovable(false); + m_tabWidget->setDocumentMode(true); + setCentralWidget(m_tabWidget); + + m_contextManager = new ContextManager(this, m_tabWidget); + + setDockNestingEnabled(true); + m_originalPalette = QApplication::palette(); + m_undoGroup = new QUndoGroup(this); + + createDialogs(); + createActions(); + createMenus(); + createStatusBar(); + resize(1024, 768); +} + +MainWindow::~MainWindow() +{ + m_pluginManager->removeObject(m_coreImpl); + m_pluginManager->removeObject(m_menuManager); + + delete m_coreImpl; + m_coreImpl = 0; +} + +bool MainWindow::initialize(QString *errorString) +{ + Q_UNUSED(errorString); + m_pluginManager->addObject(m_coreImpl); + m_pluginManager->addObject(m_menuManager); + return true; +} + +void MainWindow::extensionsInitialized() +{ + readSettings(); + connect(m_contextManager, SIGNAL(currentContextChanged(Core::IContext *)), + this, SLOT(updateContext(Core::IContext *))); + if (m_contextManager->currentContext() != NULL) + updateContext(m_contextManager->currentContext()); + show(); +} + +MenuManager *MainWindow::menuManager() const +{ + return m_menuManager; +} + +ContextManager *MainWindow::contextManager() const +{ + return m_contextManager; +} + +QSettings *MainWindow::settings() const +{ + return m_settings; +} + +QUndoGroup *MainWindow::undoGroup() const +{ + return m_undoGroup; +} + +ExtensionSystem::IPluginManager *MainWindow::pluginManager() const +{ + return m_pluginManager; +} + +void MainWindow::addContextObject(IContext *context) +{ + QUndoStack *stack = context->undoStack(); + if (stack) + m_undoGroup->addStack(stack); +} + +void MainWindow::removeContextObject(IContext *context) +{ + QUndoStack *stack = context->undoStack(); + if (stack) + m_undoGroup->removeStack(stack); +} + +void MainWindow::open() +{ + m_contextManager->currentContext()->open(); +} + +void MainWindow::newFile() +{ + m_contextManager->currentContext()->newDocument(); +} + +void MainWindow::save() +{ + m_contextManager->currentContext()->save(); +} + +void MainWindow::saveAs() +{ + m_contextManager->currentContext()->saveAs(); +} + +void MainWindow::saveAll() +{ +} + +void MainWindow::closeDocument() +{ + m_contextManager->currentContext()->close(); +} + + +void MainWindow::cut() +{ +} + +void MainWindow::copy() +{ +} + +void MainWindow::paste() +{ +} + +void MainWindow::del() +{ +} + +void MainWindow::find() +{ +} + +void MainWindow::gotoPos() +{ +} + +void MainWindow::setFullScreen(bool enabled) +{ + if (bool(windowState() & Qt::WindowFullScreen) == enabled) + return; + if (enabled) + setWindowState(windowState() | Qt::WindowFullScreen); + else + setWindowState(windowState() & ~Qt::WindowFullScreen); +} + +bool MainWindow::showOptionsDialog(const QString &group, + const QString &page, + QWidget *parent) +{ + if (!parent) + parent = this; + SettingsDialog settingsDialog(m_pluginManager, group, page, parent); + settingsDialog.show(); + bool ok = settingsDialog.execDialog(); + if (ok) + Q_EMIT m_coreImpl->changeSettings(); + return ok; +} + +void MainWindow::about() +{ + QMessageBox::about(this, tr("About Object Viewer Qt"), + tr("

Object Viewer Qt

" + "

Ryzom Core team

Compiled on %1 %2").arg(__DATE__).arg(__TIME__)); +} + +void MainWindow::updateContext(Core::IContext *context) +{ + m_undoGroup->setActiveStack(context->undoStack()); +} + +void MainWindow::closeEvent(QCloseEvent *event) +{ + QList listeners = m_pluginManager->getObjects(); + Q_FOREACH(ICoreListener *listener, listeners) + { + if (!listener->closeMainWindow()) + { + event->ignore(); + return; + } + } + Q_EMIT m_coreImpl->closeMainWindow(); + + writeSettings(); + event->accept(); +} + +void MainWindow::createActions() +{ + m_newAction = new QAction(tr("&New"), this); + m_newAction->setIcon(QIcon(Constants::ICON_NEW)); + m_newAction->setShortcut(QKeySequence::New); + menuManager()->registerAction(m_newAction, Constants::NEW); + connect(m_newAction, SIGNAL(triggered()), this, SLOT(newFile())); + m_newAction->setEnabled(false); + + m_openAction = new QAction(tr("&Open..."), this); + m_openAction->setIcon(QIcon(Constants::ICON_OPEN)); + m_openAction->setShortcut(QKeySequence::Open); + m_openAction->setStatusTip(tr("Open an existing file")); + menuManager()->registerAction(m_openAction, Constants::OPEN); + connect(m_openAction, SIGNAL(triggered()), this, SLOT(open())); + + m_saveAction = new QAction(tr("&Save"), this); + m_saveAction->setIcon(QIcon(Constants::ICON_SAVE)); + m_saveAction->setShortcut(QKeySequence::Save); + menuManager()->registerAction(m_saveAction, Constants::SAVE); + connect(m_saveAction, SIGNAL(triggered()), this, SLOT(save())); + m_saveAction->setEnabled(false); + + m_saveAsAction = new QAction(tr("Save &As..."), this); + m_saveAsAction->setIcon(QIcon(Constants::ICON_SAVE_AS)); + m_saveAsAction->setShortcut(QKeySequence::SaveAs); + menuManager()->registerAction(m_saveAsAction, Constants::SAVE_AS); + connect(m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); + m_saveAsAction->setEnabled(false); + + m_saveAllAction = new QAction(tr("&Save A&ll"), this); + m_saveAllAction->setShortcut(QKeySequence::SelectAll); + menuManager()->registerAction(m_saveAllAction, Constants::SAVE_ALL); + connect(m_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll())); + m_saveAllAction->setEnabled(false); + + m_closeAction = new QAction(tr("Close"), this); + m_closeAction->setShortcut(QKeySequence::Close); + menuManager()->registerAction(m_closeAction, Constants::CLOSE); + connect(m_closeAction, SIGNAL(triggered()), this, SLOT(closeDocument())); + m_closeAction->setEnabled(false); + + m_exitAction = new QAction(tr("E&xit"), this); + m_exitAction->setShortcut(QKeySequence(tr("Ctrl+Q"))); + m_exitAction->setStatusTip(tr("Exit the application")); + menuManager()->registerAction(m_exitAction, Constants::EXIT); + connect(m_exitAction, SIGNAL(triggered()), this, SLOT(close())); + + m_cutAction = new QAction(tr("Cu&t"), this); + m_cutAction->setShortcut(QKeySequence::Cut); + menuManager()->registerAction(m_cutAction, Constants::CUT); + connect(m_cutAction, SIGNAL(triggered()), this, SLOT(cut())); + m_cutAction->setEnabled(false); + + m_copyAction = new QAction(tr("&Copy"), this); + m_copyAction->setShortcut(QKeySequence::Copy); + menuManager()->registerAction(m_copyAction, Constants::COPY); + connect(m_copyAction, SIGNAL(triggered()), this, SLOT(copy())); + m_copyAction->setEnabled(false); + + m_pasteAction = new QAction(tr("&Paste"), this); + m_pasteAction->setShortcut(QKeySequence::Paste); + menuManager()->registerAction(m_pasteAction, Constants::PASTE); + connect(m_pasteAction, SIGNAL(triggered()), this, SLOT(paste())); + m_pasteAction->setEnabled(false); + + m_delAction = new QAction(tr("&Delete"), this); + m_delAction->setShortcut(QKeySequence::Delete); + menuManager()->registerAction(m_delAction, Constants::DEL); + connect(m_delAction, SIGNAL(triggered()), this, SLOT(del())); + m_delAction->setEnabled(false); + + m_selectAllAction = new QAction(tr("Select &All"), this); + m_selectAllAction->setShortcut(QKeySequence::SelectAll); + menuManager()->registerAction(m_selectAllAction, Constants::SELECT_ALL); + connect(m_selectAllAction, SIGNAL(triggered()), this, SLOT(selectAll())); + m_selectAllAction->setEnabled(false); + + m_findAction = new QAction(tr("&Find"), this); + m_findAction->setShortcut(QKeySequence::Find); + menuManager()->registerAction(m_findAction, Constants::FIND); + connect(m_findAction, SIGNAL(triggered()), this, SLOT(find())); + m_findAction->setEnabled(false); + + m_gotoAction = new QAction(tr("&Go To.."), this); + m_gotoAction->setShortcut(QKeySequence(tr("Ctrl+G"))); + menuManager()->registerAction(m_gotoAction, Constants::GOTO_POS); + connect(m_gotoAction, SIGNAL(triggered()), this, SLOT(gotoPos())); + m_gotoAction->setEnabled(false); + + m_fullscreenAction = new QAction(tr("Fullscreen"), this); + m_fullscreenAction->setCheckable(true); + m_fullscreenAction->setShortcut(QKeySequence(tr("Ctrl+Shift+F11"))); + menuManager()->registerAction(m_fullscreenAction, Constants::TOGGLE_FULLSCREEN); + connect(m_fullscreenAction, SIGNAL(triggered(bool)), this, SLOT(setFullScreen(bool))); + + m_settingsAction = new QAction(tr("&Settings"), this); + m_settingsAction->setIcon(QIcon(":/images/preferences.png")); + m_settingsAction->setShortcut(QKeySequence::Preferences); + m_settingsAction->setStatusTip(tr("Open the settings dialog")); + menuManager()->registerAction(m_settingsAction, Constants::SETTINGS); + connect(m_settingsAction, SIGNAL(triggered()), this, SLOT(showOptionsDialog())); + + m_aboutAction = new QAction(tr("&About"), this); + m_aboutAction->setStatusTip(tr("Show the application's About box")); + menuManager()->registerAction(m_aboutAction, Constants::ABOUT); + connect(m_aboutAction, SIGNAL(triggered()), this, SLOT(about())); + + m_aboutQtAction = new QAction(tr("About &Qt"), this); + m_aboutQtAction->setStatusTip(tr("Show the Qt library's About box")); + menuManager()->registerAction(m_aboutQtAction, Constants::ABOUT_QT); + connect(m_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); + + m_pluginViewAction = new QAction(tr("About &Plugins"), this); + m_pluginViewAction->setStatusTip(tr("Show the plugin view dialog")); + menuManager()->registerAction(m_pluginViewAction, Constants::ABOUT_PLUGINS); + connect(m_pluginViewAction, SIGNAL(triggered()), m_pluginView, SLOT(show())); + +#ifdef Q_WS_MAC + m_exitAction->setMenuRole(QAction::QuitRole); + m_settingsAction->setMenuRole(QAction::PreferencesRole); + m_aboutAction->setMenuRole(QAction::AboutRole); + m_aboutQtAction->setMenuRole(QAction::AboutQtRole); + m_pluginViewAction->setMenuRole(QAction::ApplicationSpecificRole); +#endif +} + +void MainWindow::createMenus() +{ + m_fileMenu = m_menuBar->addMenu(tr("&File")); + menuManager()->registerMenu(m_fileMenu, Constants::M_FILE); + m_fileMenu->addAction(m_newAction); + m_fileMenu->addAction(m_openAction); + m_fileMenu->addSeparator(); + m_fileMenu->addAction(m_saveAction); + m_fileMenu->addAction(m_saveAsAction); + m_fileMenu->addAction(m_saveAllAction); + m_fileMenu->addAction(m_closeAction); + m_fileMenu->addSeparator(); + + m_recentFilesMenu = m_fileMenu->addMenu(tr("Recent &Files")); + m_recentFilesMenu->setEnabled(false); + menuManager()->registerMenu(m_recentFilesMenu, Constants::M_FILE_RECENTFILES); + + m_fileMenu->addSeparator(); + m_fileMenu->addAction(m_exitAction); + + m_editMenu = m_menuBar->addMenu(tr("&Edit")); + QAction *undoAction = m_undoGroup->createUndoAction(this); + menuManager()->registerAction(undoAction, Constants::UNDO); + undoAction->setIcon(QIcon(Constants::ICON_UNDO)); + undoAction->setShortcut(QKeySequence::Undo); + QAction *redoAction = m_undoGroup->createRedoAction(this); + menuManager()->registerAction(redoAction, Constants::REDO); + redoAction->setIcon(QIcon(Constants::ICON_REDO)); + redoAction->setShortcut(QKeySequence::Redo); + m_editMenu->addAction(undoAction); + m_editMenu->addAction(redoAction); + + m_editMenu->addSeparator(); + m_editMenu->addAction(m_cutAction); + m_editMenu->addAction(m_copyAction); + m_editMenu->addAction(m_pasteAction); + m_editMenu->addAction(m_delAction); + m_editMenu->addSeparator(); + m_editMenu->addAction(m_selectAllAction); + m_editMenu->addSeparator(); + m_editMenu->addAction(m_findAction); + m_editMenu->addAction(m_gotoAction); + menuManager()->registerMenu(m_editMenu, Constants::M_EDIT); + + m_viewMenu = m_menuBar->addMenu(tr("&View")); + m_viewMenu->addAction(m_fullscreenAction); + m_viewMenu->addAction(m_dockWidget->toggleViewAction()); + menuManager()->registerMenu(m_viewMenu, Constants::M_VIEW); + + m_toolsMenu = m_menuBar->addMenu(tr("&Tools")); + menuManager()->registerMenu(m_toolsMenu, Constants::M_TOOLS); + + m_sheetMenu = m_toolsMenu->addMenu(tr("&Sheet")); + menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); + +// m_toolsMenu->addSeparator(); + + m_toolsMenu->addAction(m_settingsAction); + + m_menuBar->addSeparator(); + + m_helpMenu = m_menuBar->addMenu(tr("&Help")); + menuManager()->registerMenu(m_helpMenu, Constants::M_HELP); + m_helpMenu->addAction(m_aboutAction); + m_helpMenu->addAction(m_aboutQtAction); + m_helpMenu->addAction(m_pluginViewAction); +} + +void MainWindow::createStatusBar() +{ + statusBar()->showMessage(tr("StatusReady")); +} + +void MainWindow::createDialogs() +{ + m_pluginView = new PluginView(m_pluginManager, this); + + // Create undo/redo command list + m_dockWidget = new QDockWidget("Command List", this); + m_dockWidget->setObjectName(QString::fromUtf8("UndoRedoCommandDockWidget")); + QUndoView *undoView = new QUndoView(m_undoGroup, m_dockWidget); + m_dockWidget->setWidget(undoView); + addDockWidget(Qt::RightDockWidgetArea, m_dockWidget); +} + +void MainWindow::readSettings() +{ + m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + restoreState(m_settings->value(Constants::MAIN_WINDOW_STATE).toByteArray()); + restoreGeometry(m_settings->value(Constants::MAIN_WINDOW_GEOMETRY).toByteArray()); + m_settings->endGroup(); +} + +void MainWindow::writeSettings() +{ + m_settings->beginGroup(Constants::MAIN_WINDOW_SECTION); + m_settings->setValue(Constants::MAIN_WINDOW_STATE, saveState()); + m_settings->setValue(Constants::MAIN_WINDOW_GEOMETRY, saveGeometry()); + m_settings->endGroup(); +} + +} /* namespace Core */ + +/* end of file */ diff --git a/code/studio/src/plugins/core/main_window.h b/code/studio/src/plugins/core/main_window.h new file mode 100644 index 000000000..d258a5eba --- /dev/null +++ b/code/studio/src/plugins/core/main_window.h @@ -0,0 +1,147 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef MAIN_WINDOW_H +#define MAIN_WINDOW_H + +// Project includes +#include "../../extension_system/iplugin_manager.h" +#include "plugin_view_dialog.h" + +// STL includes + +// Qt includes +#include +#include +#include + +namespace Core +{ +class CSettingsDialog; +class CorePlugin; +class IContext; +class MenuManager; +class ContextManager; +class CoreImpl; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); + ~MainWindow(); + + bool initialize(QString *errorString); + void extensionsInitialized(); + + MenuManager *menuManager() const; + ContextManager *contextManager() const; + QSettings *settings() const; + QUndoGroup *undoGroup() const; + + ExtensionSystem::IPluginManager *pluginManager() const; + + void addContextObject(IContext *context); + void removeContextObject(IContext *context); + +public Q_SLOTS: + bool showOptionsDialog(const QString &group = QString(), + const QString &page = QString(), + QWidget *parent = 0); + void updateContext(Core::IContext *context); + +private Q_SLOTS: + void open(); + void newFile(); + void save(); + void saveAs(); + void saveAll(); + void closeDocument(); + void cut(); + void copy(); + void paste(); + void del(); + void find(); + void gotoPos(); + void setFullScreen(bool enabled); + void about(); + +protected: + virtual void closeEvent(QCloseEvent *event); + +private: + void createActions(); + void createMenus(); + void createStatusBar(); + void createDialogs(); + + void readSettings(); + void writeSettings(); + + ExtensionSystem::IPluginManager *m_pluginManager; + PluginView *m_pluginView; + MenuManager *m_menuManager; + ContextManager *m_contextManager; + CoreImpl *m_coreImpl; + + QPalette m_originalPalette; + QString m_lastDir; + + QDockWidget *m_dockWidget; + QUndoGroup *m_undoGroup; + QSettings *m_settings; + + QTimer *m_mainTimer; + QTimer *m_statusBarTimer; + + QTabWidget *m_tabWidget; + + QMenu *m_fileMenu; + QMenu *m_recentFilesMenu; + QMenu *m_editMenu; + QMenu *m_viewMenu; + QMenu *m_toolsMenu; + QMenu *m_helpMenu; + QMenuBar *m_menuBar; + QMenu *m_sheetMenu; + + QAction *m_newAction; + QAction *m_openAction; + QAction *m_saveAction; + QAction *m_saveAsAction; + QAction *m_saveAllAction; + QAction *m_closeAction; + QAction *m_exitAction; + QAction *m_cutAction; + QAction *m_copyAction; + QAction *m_pasteAction; + QAction *m_delAction; + QAction *m_selectAllAction; + QAction *m_findAction; + QAction *m_gotoAction; + QAction *m_fullscreenAction; + QAction *m_settingsAction; + QAction *m_pluginViewAction; + QAction *m_aboutAction; + QAction *m_aboutQtAction; + +};/* class MainWindow */ + +} /* namespace Core */ + +#endif // MAIN_WINDOW_H diff --git a/code/studio/src/plugins/core/menu_manager.cpp b/code/studio/src/plugins/core/menu_manager.cpp new file mode 100644 index 000000000..3e6272f0a --- /dev/null +++ b/code/studio/src/plugins/core/menu_manager.cpp @@ -0,0 +1,96 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "menu_manager.h" + +// NeL includes +#include + +namespace Core +{ +struct MenuManagerPrivate +{ + MenuManagerPrivate(): m_menuBar(0) {} + QMenuBar *m_menuBar; + typedef QHash IdMenuMap; + IdMenuMap m_menuMap; + typedef QHash IdActionMap; + IdActionMap m_actionMap; +}; + +MenuManager::MenuManager(QMenuBar *menuBar, QObject *parent) + : QObject(parent), + d(new MenuManagerPrivate()) +{ + d->m_menuBar = menuBar; +} + +MenuManager::~MenuManager() +{ + d->m_menuMap.clear(); + delete d; +} + +void MenuManager::registerMenu(QMenu *menu, const QString &id) +{ + menu->setObjectName(id); + d->m_menuMap.insert(id, menu); +} + +void MenuManager::registerAction(QAction *action, const QString &id) +{ + action->setObjectName(id); + d->m_actionMap.insert(id, action); +} + +QMenu *MenuManager::menu(const QString &id) const +{ + QMenu *result = 0; + if (!d->m_menuMap.contains(id)) + nlwarning("QMenu %s not found", id.toUtf8().constData()); + else + result = d->m_menuMap.value(id); + return result; +} + +QAction *MenuManager::action(const QString &id) const +{ + QAction *result = 0; + if (!d->m_actionMap.contains(id)) + nlwarning("QAction %s not found", id.toUtf8().constData()); + else + result = d->m_actionMap.value(id); + return result; +} + +void MenuManager::unregisterMenu(const QString &id) +{ + d->m_menuMap.remove(id); +} + +void MenuManager::unregisterAction(const QString &id) +{ + d->m_actionMap.remove(id); +} + +QMenuBar *MenuManager::menuBar() const +{ + return d->m_menuBar; +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/menu_manager.h b/code/studio/src/plugins/core/menu_manager.h new file mode 100644 index 000000000..fd6af8f3a --- /dev/null +++ b/code/studio/src/plugins/core/menu_manager.h @@ -0,0 +1,67 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef MENU_MANAGER_H +#define MENU_MANAGER_H + +// Project includes +#include "core_global.h" + +// Qt includes +#include +#include +#include +#include +#include +#include + +namespace Core +{ +struct MenuManagerPrivate; + +/* +@interface MenuManager +@brief The MenuManager provide the interface for registration of menus and menu item. +@details The MenuManager provides centralized access to menus and menu items. +All menus and menu items should be registered in the MenuManager. +*/ +class CORE_EXPORT MenuManager: public QObject +{ + Q_OBJECT + +public: + MenuManager(QMenuBar *menuBar, QObject *parent = 0); + virtual ~MenuManager(); + + void registerMenu(QMenu *menu, const QString &id); + void registerAction(QAction *action, const QString &id); + + QMenu *menu(const QString &id) const; + QAction *action(const QString &id) const; + + void unregisterMenu(const QString &id); + void unregisterAction(const QString &id); + + QMenuBar *menuBar() const; +private: + + MenuManagerPrivate *d; +}; + +} // namespace Core + +#endif // MENU_MANAGER_H diff --git a/code/studio/src/plugins/core/ovqt_plugin_core.xml b/code/studio/src/plugins/core/ovqt_plugin_core.xml new file mode 100644 index 000000000..2f5d6e9a8 --- /dev/null +++ b/code/studio/src/plugins/core/ovqt_plugin_core.xml @@ -0,0 +1,7 @@ + + ovqt_plugin_core + Core + 0.8 + Ryzom Core + Core plugin. + \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp new file mode 100644 index 000000000..175902d39 --- /dev/null +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -0,0 +1,108 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "plugin_view_dialog.h" +#include "core_constants.h" + +#include "nel/misc/debug.h" + +// Qt includes +#include +#include +#include +#include + +// Project includes +#include "../../extension_system/iplugin_spec.h" +#include "../../extension_system/iplugin_manager.h" + +namespace Core +{ + +PluginView::PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent) + : QDialog(parent), + m_checkStateColumn(0) +{ + m_ui.setupUi(this); + m_pluginManager = pluginManager; + + connect(m_pluginManager, SIGNAL(pluginsChanged()), this, SLOT(updateList())); + connect(this, SIGNAL(accepted()), this, SLOT(updateSettings())); + + // WhiteList is list of plugins which can not disable. + m_whiteList << Constants::OVQT_CORE_PLUGIN; + updateList(); +} + +PluginView::~PluginView() +{ +} + +void PluginView::updateList() +{ + static QIcon okIcon = QApplication::style()->standardIcon(QStyle::SP_DialogApplyButton); + static QIcon errorIcon = QApplication::style()->standardIcon(QStyle::SP_DialogCancelButton); + static QIcon notLoadedIcon = QApplication::style()->standardIcon(QStyle::SP_DialogResetButton); + + m_specToItem.clear(); + + QList items; + Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) + { + QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() + << spec->name() + << QString("%1").arg(spec->version()) + << spec->vendor() + << QDir::toNativeSeparators(spec->filePath())); + + bool ok = !spec->hasError(); + QIcon icon = ok ? okIcon : errorIcon; + if (ok && (spec->state() != ExtensionSystem::State::Running)) + icon = notLoadedIcon; + + item->setIcon(m_checkStateColumn, icon); + + if (!m_whiteList.contains(spec->name())) + item->setCheckState(m_checkStateColumn, spec->isEnabled() ? Qt::Checked : Qt::Unchecked); + + items.append(item); + m_specToItem.insert(spec, item); + } + + m_ui.pluginTreeWidget->clear(); + if (!items.isEmpty()) + m_ui.pluginTreeWidget->addTopLevelItems(items); + + m_ui.pluginTreeWidget->resizeColumnToContents(m_checkStateColumn); +} + +void PluginView::updateSettings() +{ + Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) + { + if (m_specToItem.contains(spec) && (!m_whiteList.contains(spec->name()))) + { + QTreeWidgetItem *item = m_specToItem.value(spec); + if (item->checkState(m_checkStateColumn) == Qt::Checked) + spec->setEnabled(true); + else + spec->setEnabled(false); + } + } +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.h b/code/studio/src/plugins/core/plugin_view_dialog.h new file mode 100644 index 000000000..aae16749d --- /dev/null +++ b/code/studio/src/plugins/core/plugin_view_dialog.h @@ -0,0 +1,58 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PLUGIN_VIEW_H +#define PLUGIN_VIEW_H + +#include "ui_plugin_view_dialog.h" + +#include +#include + +namespace ExtensionSystem +{ +class IPluginManager; +class IPluginSpec; +} + +namespace Core +{ + +class PluginView: public QDialog +{ + Q_OBJECT + +public: + PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget *parent = 0); + ~PluginView(); + +private Q_SLOTS: + void updateList(); + void updateSettings(); + +private: + + const int m_checkStateColumn; + QMap m_specToItem; + QStringList m_whiteList; + ExtensionSystem::IPluginManager *m_pluginManager; + Ui::PluginView m_ui; +}; /* class PluginView */ + +} /* namespace Core */ + +#endif // PLUGIN_VIEW_H diff --git a/code/studio/src/plugins/core/plugin_view_dialog.ui b/code/studio/src/plugins/core/plugin_view_dialog.ui new file mode 100644 index 000000000..9d7d395be --- /dev/null +++ b/code/studio/src/plugins/core/plugin_view_dialog.ui @@ -0,0 +1,135 @@ + + + PluginView + + + + 0 + 0 + 756 + 296 + + + + About plugins + + + true + + + + + + true + + + 0 + + + false + + + true + + + false + + + true + + + + Name + + + + + Version + + + + + Vendor + + + + + Location + + + + + + + + false + + + Details + + + + + + + false + + + Error details + + + + + + + Qt::Horizontal + + + + 427 + 20 + + + + + + + + Close + + + + + + + false + + + All objects list + + + + + + + + + + + closePushButton + clicked() + PluginView + accept() + + + 620 + 232 + + + 507 + 226 + + + + + diff --git a/code/studio/src/plugins/core/qtwin.cpp b/code/studio/src/plugins/core/qtwin.cpp new file mode 100644 index 000000000..115203ded --- /dev/null +++ b/code/studio/src/plugins/core/qtwin.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#include "qtwin.h" +#include +#include +#include +#include +#include + +#ifdef Q_WS_WIN + +#include + +// Blur behind data structures +#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified +#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified +#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified +#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message + +typedef struct _DWM_BLURBEHIND +{ + DWORD dwFlags; + BOOL fEnable; + HRGN hRgnBlur; + BOOL fTransitionOnMaximized; +} DWM_BLURBEHIND, *PDWM_BLURBEHIND; + +typedef struct _MARGINS +{ + int cxLeftWidth; + int cxRightWidth; + int cyTopHeight; + int cyBottomHeight; +} MARGINS, *PMARGINS; + +typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL *pfEnabled); +typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS *pMarInset); +typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND *pBlurBehind); +typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); + +static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; +static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; +static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; +static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; + + +/* + * Internal helper class that notifies windows if the + * DWM compositing state changes and updates the widget + * flags correspondingly. + */ +class WindowNotifier : public QWidget +{ +public: + WindowNotifier() + { + winId(); + } + void addWidget(QWidget *widget) + { + widgets.append(widget); + } + void removeWidget(QWidget *widget) + { + widgets.removeAll(widget); + } + bool winEvent(MSG *message, long *result); + +private: + QWidgetList widgets; +}; + +static bool resolveLibs() +{ + if (!pDwmIsCompositionEnabled) + { + QLibrary dwmLib(QString::fromAscii("dwmapi")); + pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); + pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); + pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); + pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); + } + return pDwmIsCompositionEnabled != 0; +} + +#endif + +/*! + * Chekcs and returns true if Windows DWM composition + * is currently enabled on the system. + * + * To get live notification on the availability of + * this feature, you will currently have to + * reimplement winEvent() on your widget and listen + * for the WM_DWMCOMPOSITIONCHANGED event to occur. + * + */ +bool QtWin::isCompositionEnabled() +{ +#ifdef Q_WS_WIN + if (resolveLibs()) + { + HRESULT hr = S_OK; + BOOL isEnabled = false; + hr = pDwmIsCompositionEnabled(&isEnabled); + if (SUCCEEDED(hr)) + return isEnabled; + } +#endif + return false; +} + +/*! + * Enables Blur behind on a Widget. + * + * \a enable tells if the blur should be enabled or not + */ +bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable) +{ + Q_ASSERT(widget); + bool result = false; +#ifdef Q_WS_WIN + if (resolveLibs()) + { + DWM_BLURBEHIND bb = {0}; + HRESULT hr = S_OK; + bb.fEnable = enable; + bb.dwFlags = DWM_BB_ENABLE; + bb.hRgnBlur = NULL; + widget->setAttribute(Qt::WA_TranslucentBackground, enable); + widget->setAttribute(Qt::WA_NoSystemBackground, enable); + hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb); + if (SUCCEEDED(hr)) + { + result = true; + windowNotifier()->addWidget(widget); + } + } +#endif + return result; +} + +/*! + * ExtendFrameIntoClientArea. + * + * This controls the rendering of the frame inside the window. + * Note that passing margins of -1 (the default value) will completely + * remove the frame from the window. + * + * \note you should not call enableBlurBehindWindow before calling + * this functions + * + * \a enable tells if the blur should be enabled or not + */ +bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom) +{ + + Q_ASSERT(widget); + Q_UNUSED(left); + Q_UNUSED(top); + Q_UNUSED(right); + Q_UNUSED(bottom); + + bool result = false; +#ifdef Q_WS_WIN + if (resolveLibs()) + { + QLibrary dwmLib(QString::fromAscii("dwmapi")); + HRESULT hr = S_OK; + MARGINS m = {left, top, right, bottom}; + hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m); + if (SUCCEEDED(hr)) + { + result = true; + windowNotifier()->addWidget(widget); + } + widget->setAttribute(Qt::WA_TranslucentBackground, result); + } +#endif + return result; +} + +/*! + * Returns the current colorizationColor for the window. + * + * \a enable tells if the blur should be enabled or not + */ +QColor QtWin::colorizatinColor() +{ + QColor resultColor = QApplication::palette().window().color(); + +#ifdef Q_WS_WIN + if (resolveLibs()) + { + DWORD color = 0; + BOOL opaque = FALSE; + QLibrary dwmLib(QString::fromAscii("dwmapi")); + HRESULT hr = S_OK; + hr = pDwmGetColorizationColor(&color, &opaque); + if (SUCCEEDED(hr)) + resultColor = QColor(color); + } +#endif + return resultColor; +} + +#ifdef Q_WS_WIN +WindowNotifier *QtWin::windowNotifier() +{ + static WindowNotifier *windowNotifierInstance = 0; + if (!windowNotifierInstance) + windowNotifierInstance = new WindowNotifier; + return windowNotifierInstance; +} + + +/* Notify all enabled windows that the DWM state changed */ +bool WindowNotifier::winEvent(MSG *message, long *result) +{ + if (message && message->message == WM_DWMCOMPOSITIONCHANGED) + { + bool compositionEnabled = QtWin::isCompositionEnabled(); + Q_FOREACH(QWidget * widget, widgets) + { + if (widget) + { + widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); + } + widget->update(); + } + } + return QWidget::winEvent(message, result); +} +#endif diff --git a/code/studio/src/plugins/core/qtwin.h b/code/studio/src/plugins/core/qtwin.h new file mode 100644 index 000000000..5692a34fb --- /dev/null +++ b/code/studio/src/plugins/core/qtwin.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Use, modification and distribution is allowed without limitation, +** warranty, liability or support of any kind. +** +****************************************************************************/ + +#ifndef QTWIN_H +#define QTWIN_H + +#include +#include +/** + * This is a helper class for using the Desktop Window Manager + * functionality on Windows 7 and Windows Vista. On other platforms + * these functions will simply not do anything. + */ + +class WindowNotifier; + +class QtWin +{ +public: + static bool enableBlurBehindWindow(QWidget *widget, bool enable = true); + static bool extendFrameIntoClientArea(QWidget *widget, + int left = -1, int top = -1, + int right = -1, int bottom = -1); + static bool isCompositionEnabled(); + static QColor colorizatinColor(); + +private: + static WindowNotifier *windowNotifier(); +}; + +#endif // QTWIN_H diff --git a/code/studio/src/plugins/core/search_paths_settings_page.cpp b/code/studio/src/plugins/core/search_paths_settings_page.cpp new file mode 100644 index 000000000..e76d6c796 --- /dev/null +++ b/code/studio/src/plugins/core/search_paths_settings_page.cpp @@ -0,0 +1,219 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "search_paths_settings_page.h" +#include "core_constants.h" +#include "icore.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include + +namespace Core +{ + +QString lastDir = "."; + +SearchPathsSettingsPage::SearchPathsSettingsPage(bool recurse, QObject *parent) + : IOptionsPage(parent), + m_recurse(recurse), + m_page(0) +{ +} + +SearchPathsSettingsPage::~SearchPathsSettingsPage() +{ +} + +QString SearchPathsSettingsPage::id() const +{ + if (m_recurse) + return QLatin1String("search_recurse_paths"); + else + return QLatin1String("search_paths"); +} + +QString SearchPathsSettingsPage::trName() const +{ + if (m_recurse) + return tr("Search Recurse Paths"); + else + return tr("Search Paths"); +} + +QString SearchPathsSettingsPage::category() const +{ + return QLatin1String(Constants::SETTINGS_CATEGORY_GENERAL); +} + +QString SearchPathsSettingsPage::trCategory() const +{ + return tr(Constants::SETTINGS_TR_CATEGORY_GENERAL); +} + +QIcon SearchPathsSettingsPage::categoryIcon() const +{ + return QIcon(); +} + +QWidget *SearchPathsSettingsPage::createPage(QWidget *parent) +{ + m_page = new QWidget(parent); + m_ui.setupUi(m_page); + + readSettings(); + checkEnabledButton(); + connect(m_ui.addToolButton, SIGNAL(clicked()), this, SLOT(addPath())); + connect(m_ui.removeToolButton, SIGNAL(clicked()), this, SLOT(delPath())); + connect(m_ui.upToolButton, SIGNAL(clicked()), this, SLOT(upPath())); + connect(m_ui.downToolButton, SIGNAL(clicked()), this, SLOT(downPath())); + connect(m_ui.resetToolButton, SIGNAL(clicked()), m_ui.pathsListWidget, SLOT(clear())); + return m_page; +} + +void SearchPathsSettingsPage::apply() +{ + writeSettings(); + applySearchPaths(); +} + +void SearchPathsSettingsPage::finish() +{ + delete m_page; + m_page = 0; +} + +void SearchPathsSettingsPage::applySearchPaths() +{ + QStringList paths, remapExt; + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + if (m_recurse) + paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); + else + paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); + + remapExt = settings->value(Core::Constants::REMAP_EXTENSIONS).toStringList(); + settings->endGroup(); + + for (int i = 1; i < remapExt.size(); i += 2) + NLMISC::CPath::remapExtension(remapExt.at(i - 1).toUtf8().constData(), remapExt.at(i).toUtf8().constData(), true); + + Q_FOREACH(QString path, paths) + { + NLMISC::CPath::addSearchPath(path.toUtf8().constData(), m_recurse, false); + } +} + +void SearchPathsSettingsPage::addPath() +{ + QString newPath = QFileDialog::getExistingDirectory(m_page, "", lastDir); + if (!newPath.isEmpty()) + { + QListWidgetItem *newItem = new QListWidgetItem; + newItem->setText(newPath); + newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + m_ui.pathsListWidget->addItem(newItem); + lastDir = newPath; + } + + checkEnabledButton(); +} + +void SearchPathsSettingsPage::delPath() +{ + QListWidgetItem *removeItem = m_ui.pathsListWidget->takeItem(m_ui.pathsListWidget->currentRow()); + if (!removeItem) + delete removeItem; + + checkEnabledButton(); +} + +void SearchPathsSettingsPage::upPath() +{ + int currentRow = m_ui.pathsListWidget->currentRow(); + if (!(currentRow == 0)) + { + QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); + m_ui.pathsListWidget->insertItem(--currentRow, item); + m_ui.pathsListWidget->setCurrentRow(currentRow); + } +} + +void SearchPathsSettingsPage::downPath() +{ + int currentRow = m_ui.pathsListWidget->currentRow(); + if (!(currentRow == m_ui.pathsListWidget->count()-1)) + { + QListWidgetItem *item = m_ui.pathsListWidget->takeItem(currentRow); + m_ui.pathsListWidget->insertItem(++currentRow, item); + m_ui.pathsListWidget->setCurrentRow(currentRow); + } +} + +void SearchPathsSettingsPage::readSettings() +{ + QStringList paths; + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + if (m_recurse) + paths = settings->value(Core::Constants::RECURSIVE_SEARCH_PATHS).toStringList(); + else + paths = settings->value(Core::Constants::SEARCH_PATHS).toStringList(); + settings->endGroup(); + Q_FOREACH(QString path, paths) + { + QListWidgetItem *newItem = new QListWidgetItem; + newItem->setText(path); + newItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + m_ui.pathsListWidget->addItem(newItem); + } +} + +void SearchPathsSettingsPage::writeSettings() +{ + QStringList paths; + for (int i = 0; i < m_ui.pathsListWidget->count(); ++i) + paths << m_ui.pathsListWidget->item(i)->text(); + + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Core::Constants::DATA_PATH_SECTION); + if (m_recurse) + settings->setValue(Core::Constants::RECURSIVE_SEARCH_PATHS, paths); + else + settings->setValue(Core::Constants::SEARCH_PATHS, paths); + settings->endGroup(); + settings->sync(); +} + +void SearchPathsSettingsPage::checkEnabledButton() +{ + bool bEnabled = true; + if (m_ui.pathsListWidget->count() == 0) + bEnabled = false; + + m_ui.removeToolButton->setEnabled(bEnabled); + m_ui.upToolButton->setEnabled(bEnabled); + m_ui.downToolButton->setEnabled(bEnabled); +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/search_paths_settings_page.h b/code/studio/src/plugins/core/search_paths_settings_page.h new file mode 100644 index 000000000..c45b29571 --- /dev/null +++ b/code/studio/src/plugins/core/search_paths_settings_page.h @@ -0,0 +1,74 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef SEARCH_PATHS_SETTINGS_PAGE_H +#define SEARCH_PATHS_SETTINGS_PAGE_H + +#include + +#include "ioptions_page.h" + +#include "ui_search_paths_settings_page.h" + +class QWidget; + +namespace Core +{ +/** +@class SearchPathsSettingsPage +*/ +class SearchPathsSettingsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + explicit SearchPathsSettingsPage(bool recurse, QObject *parent = 0); + ~SearchPathsSettingsPage(); + + QString id() const; + QString trName() const; + QString category() const; + QString trCategory() const; + QIcon categoryIcon() const; + QWidget *createPage(QWidget *parent); + + void apply(); + void finish(); + + // Set of the search paths(not recursive) and the remap extensions (loading from settings file) + void applySearchPaths(); + +private Q_SLOTS: + void addPath(); + void delPath(); + void upPath(); + void downPath(); + +private: + void readSettings(); + void writeSettings(); + void checkEnabledButton(); + + bool m_recurse; + QWidget *m_page; + Ui::SearchPathsSettingsPage m_ui; +}; + +} // namespace Core + +#endif // SEARCH_PATHS_SETTINGS_H diff --git a/code/studio/src/plugins/core/search_paths_settings_page.ui b/code/studio/src/plugins/core/search_paths_settings_page.ui new file mode 100644 index 000000000..cf47314b8 --- /dev/null +++ b/code/studio/src/plugins/core/search_paths_settings_page.ui @@ -0,0 +1,198 @@ + + + SearchPathsSettingsPage + + + + 0 + 0 + 431 + 285 + + + + Form + + + + 6 + + + 3 + + + + + Search paths + + + + + + + Qt::Horizontal + + + + 228 + 20 + + + + + + + + 3 + + + + + + 0 + 0 + + + + Add + + + + + + + :/core/icons/ic_nel_add_item.png:/core/icons/ic_nel_add_item.png + + + + 20 + 20 + + + + true + + + + + + + + 0 + 0 + + + + Delete + + + + + + + :/core/icons/ic_nel_delete_item.png:/core/icons/ic_nel_delete_item.png + + + + 20 + 20 + + + + true + + + + + + + + 0 + 0 + + + + Up + + + + + + + :/core/icons/ic_nel_up_item.png:/core/icons/ic_nel_up_item.png + + + + 20 + 20 + + + + true + + + + + + + + 0 + 0 + + + + Down + + + + + + + :/core/icons/ic_nel_down_item.png:/core/icons/ic_nel_down_item.png + + + + 20 + 20 + + + + true + + + + + + + Reset + + + + + + + :/core/icons/ic_nel_reset_all.png:/core/icons/ic_nel_reset_all.png + + + + 20 + 20 + + + + true + + + + + + + + + + + + + + + diff --git a/code/studio/src/plugins/core/settings_dialog.cpp b/code/studio/src/plugins/core/settings_dialog.cpp new file mode 100644 index 000000000..4b7bbac3a --- /dev/null +++ b/code/studio/src/plugins/core/settings_dialog.cpp @@ -0,0 +1,182 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "settings_dialog.h" +#include "ioptions_page.h" + +// Qt includes +#include +#include + +struct PageData +{ + int index; + QString category; + QString id; +}; + +Q_DECLARE_METATYPE(PageData); + +namespace Core +{ +SettingsDialog::SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, + const QString &categoryId, + const QString &pageId, + QWidget *parent) + : QDialog(parent), + m_applied(false) +{ + m_ui.setupUi(this); + + m_plugMan = pluginManager; + + QString initialCategory = categoryId; + QString initialPage = pageId; + + m_ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + + connect(m_ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); + + m_ui.splitter->setCollapsible(1, false); + m_ui.pageTree->header()->setVisible(false); + + connect(m_ui.pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + this, SLOT(pageSelected())); + + QMap categories; + + QList pages = m_plugMan->getObjects(); + + int index = 0; + Q_FOREACH(IOptionsPage *page, pages) + { + PageData pageData; + pageData.index = index; + pageData.category = page->category(); + pageData.id = page->id(); + + QTreeWidgetItem *item = new QTreeWidgetItem; + item->setText(0, page->trName()); + item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + + QStringList categoriesId = page->category().split(QLatin1Char('|')); + QStringList trCategories = page->trCategory().split(QLatin1Char('|')); + QString currentCategory = categoriesId.at(0); + + QTreeWidgetItem *treeitem; + if (!categories.contains(currentCategory)) + { + treeitem = new QTreeWidgetItem(m_ui.pageTree); + treeitem->setText(0, trCategories.at(0)); + treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + categories.insert(currentCategory, treeitem); + } + + int catCount = 1; + while (catCount < categoriesId.count()) + { + if (!categories.contains(currentCategory + QLatin1Char('|') + categoriesId.at(catCount))) + { + treeitem = new QTreeWidgetItem(categories.value(currentCategory)); + currentCategory += QLatin1Char('|') + categoriesId.at(catCount); + treeitem->setText(0, trCategories.at(catCount)); + treeitem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + categories.insert(currentCategory, treeitem); + } + else + { + currentCategory += QLatin1Char('|') + categoriesId.at(catCount); + } + ++catCount; + } + + categories.value(currentCategory)->addChild(item); + + m_pages.append(page); + m_ui.stackedPages->addWidget(page->createPage(m_ui.stackedPages)); + + if (page->id() == initialPage && currentCategory == initialCategory) + { + m_ui.stackedPages->setCurrentIndex(m_ui.stackedPages->count()); + m_ui.pageTree->setCurrentItem(item); + } + + index++; + } + + QList sizes; + sizes << 150 << 300; + m_ui.splitter->setSizes(sizes); + + m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.pageTree), 0); + m_ui.splitter->setStretchFactor(m_ui.splitter->indexOf(m_ui.layoutWidget), 1); +} + +SettingsDialog::~SettingsDialog() +{ +} + +void SettingsDialog::pageSelected() +{ + QTreeWidgetItem *item = m_ui.pageTree->currentItem(); + PageData data = item->data(0, Qt::UserRole).value(); + int index = data.index; + m_currentCategory = data.category; + m_currentPage = data.id; + m_ui.stackedPages->setCurrentIndex(index); +} + +void SettingsDialog::accept() +{ + m_applied = true; + Q_FOREACH(IOptionsPage *page, m_pages) + { + page->apply(); + page->finish(); + } + done(QDialog::Accepted); +} + +void SettingsDialog::reject() +{ + Q_FOREACH(IOptionsPage *page, m_pages) + page->finish(); + done(QDialog::Rejected); +} + +void SettingsDialog::apply() +{ + Q_FOREACH(IOptionsPage *page, m_pages) + page->apply(); + m_applied = true; +} + +bool SettingsDialog::execDialog() +{ + m_applied = false; + exec(); + return m_applied; +} + +void SettingsDialog::done(int val) +{ + QDialog::done(val); +} + +} /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/settings_dialog.h b/code/studio/src/plugins/core/settings_dialog.h new file mode 100644 index 000000000..9e1c86444 --- /dev/null +++ b/code/studio/src/plugins/core/settings_dialog.h @@ -0,0 +1,75 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SETTINGS_DIALOG_H +#define SETTINGS_DIALOG_H + +#include "ui_settings_dialog.h" + +// Qt includes +#include + +// Project includes +#include "../../extension_system/iplugin_manager.h" + +namespace Core +{ +class IOptionsPage; + +/** +@class CSettingsDialog +@brief Settings dialog +*/ +class SettingsDialog: public QDialog +{ + Q_OBJECT + +public: + SettingsDialog(ExtensionSystem::IPluginManager *pluginManager, + const QString &initialCategory = QString(), + const QString &initialPage = QString(), + QWidget *parent = 0); + + ~SettingsDialog(); + + /// Run the dialog and return true if 'Ok' was choosen or 'Apply' was invoked at least once + bool execDialog(); + +public Q_SLOTS: + void done(int); + +private Q_SLOTS: + void pageSelected(); + void accept(); + void reject(); + void apply(); + +private: + QList m_pages; + bool m_applied; + QString m_currentCategory; + QString m_currentPage; + + ExtensionSystem::IPluginManager *m_plugMan; + + Ui::SettingsDialog m_ui; +}; /* class CSettingsDialog */ + +} /* namespace Core */ + +#endif // SETTINGS_DIALOG_H diff --git a/code/studio/src/plugins/core/settings_dialog.ui b/code/studio/src/plugins/core/settings_dialog.ui new file mode 100644 index 000000000..8e9780c9a --- /dev/null +++ b/code/studio/src/plugins/core/settings_dialog.ui @@ -0,0 +1,126 @@ + + + SettingsDialog + + + + 0 + 0 + 697 + 476 + + + + Settings + + + + :/core/images/preferences.png:/core/images/preferences.png + + + + 6 + + + 9 + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + 1 + + + + 0 + + + + + + + 6 + + + 0 + + + + + + 350 + 250 + + + + + + + + Qt::Horizontal + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + SettingsDialog + accept() + + + 297 + 361 + + + 297 + 193 + + + + + buttonBox + rejected() + SettingsDialog + reject() + + + 297 + 361 + + + 297 + 193 + + + + + From 33e55d85eb51837356786615db44491edb5487f1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 7 May 2014 00:53:07 +0200 Subject: [PATCH 022/220] Same as before... --- .hgignore | 1 - code/studio/src/plugins/core/core.cpp | 77 +++++++++++++++++++++++++++ code/studio/src/plugins/core/core.h | 54 +++++++++++++++++++ code/studio/src/plugins/core/core.qrc | 21 ++++++++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/core/core.cpp create mode 100644 code/studio/src/plugins/core/core.h create mode 100644 code/studio/src/plugins/core/core.qrc diff --git a/.hgignore b/.hgignore index 5587652fd..6b7285bac 100644 --- a/.hgignore +++ b/.hgignore @@ -43,7 +43,6 @@ default_c *.so *.so.* *_debug -core.* *.pc *.gch diff --git a/code/studio/src/plugins/core/core.cpp b/code/studio/src/plugins/core/core.cpp new file mode 100644 index 000000000..b21d934c8 --- /dev/null +++ b/code/studio/src/plugins/core/core.cpp @@ -0,0 +1,77 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "core.h" +#include "context_manager.h" +#include "main_window.h" +#include "../../extension_system/iplugin_manager.h" + +static Core::CoreImpl *m_coreInstance = 0; + +namespace Core +{ + +ICore *ICore::instance() +{ + return m_coreInstance; +} + +CoreImpl::CoreImpl(MainWindow *mainWindow) +{ + m_mainWindow = mainWindow; + m_coreInstance = this; +} + +CoreImpl::~CoreImpl() +{ + m_coreInstance = 0; +} + +bool CoreImpl::showOptionsDialog(const QString &group, + const QString &page, + QWidget *parent) +{ + return m_mainWindow->showOptionsDialog(group, page, parent); +} + +MenuManager *CoreImpl::menuManager() const +{ + return m_mainWindow->menuManager(); +} + +ContextManager *CoreImpl::contextManager() const +{ + return m_mainWindow->contextManager(); +} + +QSettings *CoreImpl::settings() const +{ + return m_mainWindow->settings(); +} + +QMainWindow *CoreImpl::mainWindow() const +{ + return m_mainWindow; +} + +ExtensionSystem::IPluginManager *CoreImpl::pluginManager() const +{ + return m_mainWindow->pluginManager(); +} + +} // namespace Core diff --git a/code/studio/src/plugins/core/core.h b/code/studio/src/plugins/core/core.h new file mode 100644 index 000000000..f34dd6ae6 --- /dev/null +++ b/code/studio/src/plugins/core/core.h @@ -0,0 +1,54 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CORE_H +#define CORE_H + +#include "icore.h" + +namespace Core +{ +class MainWindow; + +class CoreImpl : public ICore +{ + Q_OBJECT + +public: + explicit CoreImpl(MainWindow *mainWindow); + virtual ~CoreImpl(); + + virtual bool showOptionsDialog(const QString &group = QString(), + const QString &page = QString(), + QWidget *parent = 0); + + virtual MenuManager *menuManager() const; + virtual ContextManager *contextManager() const; + + virtual QSettings *settings() const; + virtual QMainWindow *mainWindow() const; + + virtual ExtensionSystem::IPluginManager *pluginManager() const; +private: + MainWindow *m_mainWindow; + friend class MainWindow; +}; + +} // namespace Core + +#endif // CORE_H diff --git a/code/studio/src/plugins/core/core.qrc b/code/studio/src/plugins/core/core.qrc new file mode 100644 index 000000000..68b6ad141 --- /dev/null +++ b/code/studio/src/plugins/core/core.qrc @@ -0,0 +1,21 @@ + + + icons/ic_nel_add_item.png + icons/ic_nel_redo.png + icons/ic_nel_undo.png + icons/ic_nel_crash.png + icons/ic_nel_delete_item.png + icons/ic_nel_down_item.png + icons/ic_nel_generic_settings.png + icons/ic_nel_open.png + icons/ic_nel_new.png + icons/ic_nel_save.png + icons/ic_nel_save_as.png + icons/ic_nel_path_settings.png + icons/ic_nel_pill.png + icons/ic_nel_reset_all.png + icons/ic_nel_up_item.png + images/nel.png + images/preferences.png + + From 133280f7c6629f81f49488c4d4e311d118fb8ff2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 18 May 2014 21:47:31 +0200 Subject: [PATCH 023/220] Renamed ovqt and ovqt plugin binaries. --- code/studio/CMakeLists.txt | 6 +-- code/studio/src/CMakeLists.txt | 38 +++++++++---------- .../src/plugins/bnp_manager/CMakeLists.txt | 12 +++--- .../bnp_manager/ovqt_plugin_bnp_manager.xml | 2 +- code/studio/src/plugins/core/CMakeLists.txt | 18 ++++----- .../src/plugins/core/ovqt_plugin_core.xml | 2 +- .../src/plugins/disp_sheet_id/CMakeLists.txt | 20 +++++----- .../ovqt_plugin_disp_sheet_id.xml | 2 +- .../studio/src/plugins/example/CMakeLists.txt | 18 ++++----- .../plugins/example/ovqt_plugin_example.xml | 2 +- .../src/plugins/georges_editor/CMakeLists.txt | 20 +++++----- .../ovqt_plugin_georges_editor.xml | 2 +- .../src/plugins/gui_editor/CMakeLists.txt | 20 +++++----- .../gui_editor/ovqt_plugin_gui_editor.xml | 2 +- .../plugins/landscape_editor/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_landscape_editor.xml | 2 +- code/studio/src/plugins/log/CMakeLists.txt | 18 ++++----- .../src/plugins/log/ovqt_plugin_log.xml | 2 +- .../plugins/mission_compiler/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_mission_compiler.xml | 2 +- .../src/plugins/object_viewer/CMakeLists.txt | 22 +++++------ .../ovqt_plugin_object_viewer.xml | 2 +- .../plugins/ovqt_sheet_builder/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_sheet_builder.xml | 2 +- .../src/plugins/tile_editor/CMakeLists.txt | 14 +++---- .../tile_editor/ovqt_plugin_tile_editor.xml | 2 +- .../translation_manager/CMakeLists.txt | 18 ++++----- .../ovqt_plugin_translation_manager.xml | 2 +- .../src/plugins/world_editor/CMakeLists.txt | 22 +++++------ .../world_editor/ovqt_plugin_world_editor.xml | 2 +- .../src/plugins/zone_painter/CMakeLists.txt | 18 ++++----- .../zone_painter/ovqt_plugin_zone_painter.xml | 2 +- 32 files changed, 174 insertions(+), 174 deletions(-) diff --git a/code/studio/CMakeLists.txt b/code/studio/CMakeLists.txt index ff1128b9f..b301430cf 100644 --- a/code/studio/CMakeLists.txt +++ b/code/studio/CMakeLists.txt @@ -16,9 +16,9 @@ ELSEIF(APPLE) SET(OVQT_PLUGIN_DIR "plugins") SET(OVQT_DATA_DIR ".") ELSE(WIN32) - SET(OVQT_PLUGIN_SPECS_DIR ${NL_SHARE_PREFIX}/object_viewer_qt/plugins) - SET(OVQT_PLUGIN_DIR ${NL_LIB_PREFIX}/object_viewer_qt) - SET(OVQT_DATA_DIR ${NL_SHARE_PREFIX}/object_viewer_qt/data) + SET(OVQT_PLUGIN_SPECS_DIR ${NL_SHARE_PREFIX}/studio/plugins) + SET(OVQT_PLUGIN_DIR ${NL_LIB_PREFIX}/studio) + SET(OVQT_DATA_DIR ${NL_SHARE_PREFIX}/studio/data) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ovqt_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/ovqt_config.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index d77b0e6a1..cc0c5d452 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -5,16 +5,16 @@ INCLUDE( ${QT_USE_FILE} ) CONFIGURE_FILE(translations/translations.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc COPYONLY) -FILE(GLOB OBJECT_VIEWER_SRC extension_system/*.h +FILE(GLOB STUDIO_SRC extension_system/*.h extension_system/*.cpp *.h *.cpp) -SET(OBJECT_VIEWER_HDR extension_system/iplugin_manager.h +SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h) -SET(OBJECT_VIEWER_RCS object_viewer_qt.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) +SET(STUDIO_RCS object_viewer_qt.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) -SET(OBJECT_VIEWER_TS translations/object_viewer_qt_en.ts +SET(STUDIO_TS translations/object_viewer_qt_en.ts translations/object_viewer_qt_fr.ts translations/object_viewer_qt_de.ts translations/object_viewer_qt_ru.ts) @@ -23,31 +23,31 @@ SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) IF(WIN32) - SET(OBJECT_VIEWER_RC object_viewer_qt.rc) + SET(STUDIO object_viewer_qt.rc) ENDIF(WIN32) -QT4_ADD_TRANSLATION(OBJECT_VIEWER_QM ${OBJECT_VIEWER_TS}) -QT4_ADD_RESOURCES( OBJECT_VIEWER_RC_SRCS ${OBJECT_VIEWER_RCS}) -QT4_WRAP_CPP( OBJECT_VIEWER_MOC_SRCS ${OBJECT_VIEWER_HDR} ) +QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) +QT4_ADD_RESOURCES( STUDIO_RC_SRCS ${STUDIO_RCS}) +QT4_WRAP_CPP( STUDIO_MOC_SRCS ${STUDIO_HDR} ) -SOURCE_GROUP(QtResources FILES ${OBJECT_VIEWER_RCS}) -SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OBJECT_VIEWER_MOC_SRCS} ${OBJECT_VIEWER_RC_SRCS}) +SOURCE_GROUP(QtResources FILES ${STUDIO_RCS}) +SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${STUDIO_MOC_SRCS} ${STUDIO_RC_SRCS}) -ADD_EXECUTABLE(object_viewer_qt WIN32 MACOSX_BUNDLE - ${OBJECT_VIEWER_SRC} - ${OBJECT_VIEWER_MOC_SRCS} - ${OBJECT_VIEWER_RC_SRCS} - ${OBJECT_VIEWER_RC}) +ADD_EXECUTABLE(studio WIN32 MACOSX_BUNDLE + ${STUDIO_SRC} + ${STUDIO_MOC_SRCS} + ${STUDIO_RC_SRCS} + ${STUDIO_RC}) -TARGET_LINK_LIBRARIES(object_viewer_qt +TARGET_LINK_LIBRARIES(studio nelmisc ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY}) ADD_DEFINITIONS(-DQT_NO_KEYWORDS ${LIBXML2_DEFINITIONS} ${QT_DEFINITIONS}) -NL_DEFAULT_PROPS(object_viewer_qt "NeL, Tools, 3D: Object Viewer Qt") -NL_ADD_RUNTIME_FLAGS(object_viewer_qt) +NL_DEFAULT_PROPS(studio "Tools: Studio") +NL_ADD_RUNTIME_FLAGS(studio) ADD_SUBDIRECTORY(plugins) -INSTALL(TARGETS object_viewer_qt RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT runtime BUNDLE DESTINATION /Applications) +INSTALL(TARGETS studio RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT runtime BUNDLE DESTINATION /Applications) diff --git a/code/studio/src/plugins/bnp_manager/CMakeLists.txt b/code/studio/src/plugins/bnp_manager/CMakeLists.txt index 2991da073..be56bc704 100644 --- a/code/studio/src/plugins/bnp_manager/CMakeLists.txt +++ b/code/studio/src/plugins/bnp_manager/CMakeLists.txt @@ -34,16 +34,16 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_BNP_MANAGER_MOC_SRC}) SOURCE_GROUP("BNP Manager Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_bnp_manager MODULE ${SRC} ${OVQT_PLUG_BNP_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_BNP_MANAGER_RC_SRCS} ${OVQT_PLUG_BNP_MANAGER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_bnp_manager MODULE ${SRC} ${OVQT_PLUG_BNP_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_BNP_MANAGER_RC_SRCS} ${OVQT_PLUG_BNP_MANAGER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_bnp_manager ovqt_plugin_core nelmisc nelgeorges ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_bnp_manager studio_plugin_core nelmisc nelgeorges ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_bnp_manager "NeL, Tools, 3D: Object Viewer Qt Plugin: BNP Manager") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_bnp_manager) -NL_ADD_LIB_SUFFIX(ovqt_plugin_bnp_manager) +NL_DEFAULT_PROPS(studio_plugin_bnp_manager "Tools: Studio Plugin: BNP Manager") +NL_ADD_RUNTIME_FLAGS(studio_plugin_bnp_manager) +NL_ADD_LIB_SUFFIX(studio_plugin_bnp_manager) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) -INSTALL(TARGETS ovqt_plugin_bnp_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) +INSTALL(TARGETS studio_plugin_bnp_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_bnp_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml b/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml index a368a123c..591611504 100644 --- a/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml +++ b/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml @@ -1,5 +1,5 @@ - ovqt_plugin_bnp_manager + studio_plugin_bnp_manager BNPManager 0.1 Krolock diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt index 5a20ba46c..add4665bc 100644 --- a/code/studio/src/plugins/core/CMakeLists.txt +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -45,27 +45,27 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) SOURCE_GROUP("Core Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) +ADD_LIBRARY(studio_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_core nelmisc ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) -NL_ADD_LIB_SUFFIX(ovqt_plugin_core) +NL_DEFAULT_PROPS(studio_plugin_core "Tools: Studio Plugin: Core") +NL_ADD_RUNTIME_FLAGS(studio_plugin_core) +NL_ADD_LIB_SUFFIX(studio_plugin_core) ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_core LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/core/ovqt_plugin_core.xml b/code/studio/src/plugins/core/ovqt_plugin_core.xml index 2f5d6e9a8..335ed8845 100644 --- a/code/studio/src/plugins/core/ovqt_plugin_core.xml +++ b/code/studio/src/plugins/core/ovqt_plugin_core.xml @@ -1,5 +1,5 @@ - ovqt_plugin_core + studio_plugin_core Core 0.8 Ryzom Core diff --git a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt index 7e5c0e409..65f880f07 100644 --- a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt +++ b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt @@ -26,32 +26,32 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_DISP_SHEET_ID_PLUGIN_MOC_SRC}) SOURCE_GROUP("Display sheet id Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_disp_sheet_id MODULE ${SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_UI_HDRS}) +ADD_LIBRARY(studio_plugin_disp_sheet_id MODULE ${SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_DISP_SHEET_ID_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_disp_sheet_id ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_disp_sheet_id studio_plugin_core nelmisc ${QT_LIBRARIES}) IF(WITH_STLPORT) - TARGET_LINK_LIBRARIES(ovqt_plugin_disp_sheet_id ${CMAKE_THREAD_LIBS_INIT}) + TARGET_LINK_LIBRARIES(studio_plugin_disp_sheet_id ${CMAKE_THREAD_LIBS_INIT}) ENDIF(WITH_STLPORT) -NL_DEFAULT_PROPS(ovqt_plugin_disp_sheet_id "NeL, Tools, 3D: Object Viewer Qt Plugin: Display sheet id") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_disp_sheet_id) -NL_ADD_LIB_SUFFIX(ovqt_plugin_disp_sheet_id) +NL_DEFAULT_PROPS(studio_plugin_disp_sheet_id "Tools: Studio Plugin: Display sheet id") +NL_ADD_RUNTIME_FLAGS(studio_plugin_disp_sheet_id) +NL_ADD_LIB_SUFFIX(studio_plugin_disp_sheet_id) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_disp_sheet_id LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml b/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml index 173ce4479..4ac055b1a 100644 --- a/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml +++ b/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml @@ -1,5 +1,5 @@ - ovqt_plugin_disp_sheet_id + studio_plugin_disp_sheet_id DisplaySheetId 1.0 pemeon diff --git a/code/studio/src/plugins/example/CMakeLists.txt b/code/studio/src/plugins/example/CMakeLists.txt index 27e8698df..9eda8916e 100644 --- a/code/studio/src/plugins/example/CMakeLists.txt +++ b/code/studio/src/plugins/example/CMakeLists.txt @@ -28,27 +28,27 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_EXAMPLE_MOC_SRC}) SOURCE_GROUP("Example Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_example MODULE ${SRC} ${OVQT_PLUG_EXAMPLE_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_EXAMPLE_UI_HDRS}) +ADD_LIBRARY(studio_plugin_example MODULE ${SRC} ${OVQT_PLUG_EXAMPLE_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_EXAMPLE_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_example ovqt_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_example studio_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_example "NeL, Tools, 3D: Object Viewer Qt Plugin: Example") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_example) -NL_ADD_LIB_SUFFIX(ovqt_plugin_example) +NL_DEFAULT_PROPS(studio_plugin_example "Tools: Studio Plugin: Example") +NL_ADD_RUNTIME_FLAGS(studio_plugin_example) +NL_ADD_LIB_SUFFIX(studio_plugin_example) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_example LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/example/ovqt_plugin_example.xml b/code/studio/src/plugins/example/ovqt_plugin_example.xml index ae6664d52..434e37907 100644 --- a/code/studio/src/plugins/example/ovqt_plugin_example.xml +++ b/code/studio/src/plugins/example/ovqt_plugin_example.xml @@ -1,5 +1,5 @@ - ovqt_plugin_example + studio_plugin_example ExamplePlugin 0.2 dnk-88 diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index af33f5311..044d1ed39 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -36,32 +36,32 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC}) SOURCE_GROUP("Georges Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_georges_editor MODULE ${SRC} ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_GEORGES_EDITOR_UI_HDRS} ${OVQT_PLUGIN_GEORGES_EDITOR_RC_SRCS}) +ADD_LIBRARY(studio_plugin_georges_editor MODULE ${SRC} ${OVQT_PLUG_GEORGES_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_GEORGES_EDITOR_UI_HDRS} ${OVQT_PLUGIN_GEORGES_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_georges_editor ovqt_plugin_core nelmisc nelgeorges qt_property_browser ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_georges_editor studio_plugin_core nelmisc nelgeorges qt_property_browser ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_georges_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Georges Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_georges_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_georges_editor) +NL_DEFAULT_PROPS(studio_plugin_georges_editor "Tools: Studio Plugin: Georges Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_georges_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_georges_editor) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WITH_PCH) - ADD_NATIVE_PRECOMPILED_HEADER(ovqt_plugin_georges_editor ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) + ADD_NATIVE_PRECOMPILED_HEADER(studio_plugin_georges_editor ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) ENDIF(WITH_PCH) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_georges_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml b/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml index a1972dded..700373bf3 100644 --- a/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml +++ b/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_georges_editor + studio_plugin_georges_editor GeorgesEditor 0.4 aquiles diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index fd1283db8..909d2e993 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -61,7 +61,7 @@ SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_GUI_EDITOR_MOC_SRC} OVQT_P SOURCE_GROUP("GUI Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_gui_editor MODULE ${SRC} +ADD_LIBRARY(studio_plugin_gui_editor MODULE ${SRC} ${OVQT_PLUGIN_GUI_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_GUI_EDITOR_UI_HDRS} @@ -69,8 +69,8 @@ ADD_LIBRARY(ovqt_plugin_gui_editor MODULE ${SRC} ) TARGET_LINK_LIBRARIES( - ovqt_plugin_gui_editor - ovqt_plugin_core + studio_plugin_gui_editor + studio_plugin_core nelmisc nel3d nelgui @@ -80,23 +80,23 @@ TARGET_LINK_LIBRARIES( qt_property_browser ) -NL_DEFAULT_PROPS(ovqt_plugin_gui_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: GUI Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_gui_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_gui_editor) +NL_DEFAULT_PROPS(studio_plugin_gui_editor "Tools: Studio Plugin: GUI Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_gui_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_gui_editor) ADD_DEFINITIONS(-DGUI_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_gui_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml b/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml index 3703509bb..9ba1452e9 100644 --- a/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml +++ b/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_gui_editor + studio_plugin_gui_editor GUI Editor 0.0.1 Ryzom Core diff --git a/code/studio/src/plugins/landscape_editor/CMakeLists.txt b/code/studio/src/plugins/landscape_editor/CMakeLists.txt index 129f672c5..9fc9e2a5a 100644 --- a/code/studio/src/plugins/landscape_editor/CMakeLists.txt +++ b/code/studio/src/plugins/landscape_editor/CMakeLists.txt @@ -41,17 +41,17 @@ SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} SOURCE_GROUP("Landscape Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_landscape_editor SHARED ${SRC} +ADD_LIBRARY(studio_plugin_landscape_editor SHARED ${SRC} ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS} ${OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_landscape_editor ovqt_plugin_core nelmisc nel3d nelgeorges nelligo ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_landscape_editor studio_plugin_core nelmisc nel3d nelgeorges nelligo ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_landscape_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Landscape Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_landscape_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_landscape_editor) +NL_DEFAULT_PROPS(studio_plugin_landscape_editor "Tools: Studio Plugin: Landscape Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_landscape_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_landscape_editor) ADD_DEFINITIONS(-DLANDSCAPE_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) @@ -59,15 +59,15 @@ ADD_DEFINITIONS(-DLANDSCAPE_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -D IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml b/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml index a0d32a22a..53dac537b 100644 --- a/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml +++ b/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_landscape_editor + studio_plugin_landscape_editor LandscapeEditor 0.8 GSoC2011_dnk-88 diff --git a/code/studio/src/plugins/log/CMakeLists.txt b/code/studio/src/plugins/log/CMakeLists.txt index 4cee3da24..4ff8b1888 100644 --- a/code/studio/src/plugins/log/CMakeLists.txt +++ b/code/studio/src/plugins/log/CMakeLists.txt @@ -26,28 +26,28 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_LOG_MOC_SRC}) SOURCE_GROUP("Log Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_log MODULE ${SRC} ${OVQT_PLUG_LOG_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_LOG_UI_HDRS}) +ADD_LIBRARY(studio_plugin_log MODULE ${SRC} ${OVQT_PLUG_LOG_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_LOG_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_log ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_log studio_plugin_core nelmisc ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_log "NeL, Tools, 3D: Object Viewer Qt Plugin: Log") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_log) -NL_ADD_LIB_SUFFIX(ovqt_plugin_log) +NL_DEFAULT_PROPS(studio_plugin_log "Tools: Studio Plugin: Log") +NL_ADD_RUNTIME_FLAGS(studio_plugin_log) +NL_ADD_LIB_SUFFIX(studio_plugin_log) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_log LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/log/ovqt_plugin_log.xml b/code/studio/src/plugins/log/ovqt_plugin_log.xml index 90b1b1e27..48d97bd87 100644 --- a/code/studio/src/plugins/log/ovqt_plugin_log.xml +++ b/code/studio/src/plugins/log/ovqt_plugin_log.xml @@ -1,5 +1,5 @@ - ovqt_plugin_log + studio_plugin_log LogPlugin 1.1 aquiles diff --git a/code/studio/src/plugins/mission_compiler/CMakeLists.txt b/code/studio/src/plugins/mission_compiler/CMakeLists.txt index 1dcbebfa8..d2c1a4180 100644 --- a/code/studio/src/plugins/mission_compiler/CMakeLists.txt +++ b/code/studio/src/plugins/mission_compiler/CMakeLists.txt @@ -36,13 +36,13 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/ryzom/tools/leveldesign/mission_compiler # Game Share Library INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common/src) -ADD_LIBRARY(ovqt_plugin_mission_compiler MODULE ${SRC} ${OVQT_PLUG_MISSION_COMPILER_MOC_SRC} ${OVQT_PLUG_MISSION_COMPILER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_MISSION_COMPILER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_mission_compiler MODULE ${SRC} ${OVQT_PLUG_MISSION_COMPILER_MOC_SRC} ${OVQT_PLUG_MISSION_COMPILER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_MISSION_COMPILER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_mission_compiler ovqt_plugin_core nelmisc nelligo ryzom_mission_compiler_lib ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_mission_compiler studio_plugin_core nelmisc nelligo ryzom_mission_compiler_lib ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_mission_compiler "NeL, Tools, 3D: Object Viewer Qt Plugin: Mission Compiler") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_mission_compiler) -NL_ADD_LIB_SUFFIX(ovqt_plugin_mission_compiler) +NL_DEFAULT_PROPS(studio_plugin_mission_compiler "Tools: Studio Plugin: Mission Compiler") +NL_ADD_RUNTIME_FLAGS(studio_plugin_mission_compiler) +NL_ADD_LIB_SUFFIX(studio_plugin_mission_compiler) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) @@ -50,15 +50,15 @@ ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS} IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_mission_compiler LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml b/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml index 072707e07..85bdca66f 100644 --- a/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml +++ b/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml @@ -1,5 +1,5 @@ - ovqt_plugin_mission_compiler + studio_plugin_mission_compiler MissionCompiler 0.1 Ryzom Core diff --git a/code/studio/src/plugins/object_viewer/CMakeLists.txt b/code/studio/src/plugins/object_viewer/CMakeLists.txt index b550e8ea0..79e535420 100644 --- a/code/studio/src/plugins/object_viewer/CMakeLists.txt +++ b/code/studio/src/plugins/object_viewer/CMakeLists.txt @@ -165,7 +165,7 @@ SOURCE_GROUP("ovqt Plugin PS Src" FILES ${OVQT_PS_SRC}) SOURCE_GROUP("ovqt Plugin Vegetable Src" FILES ${OVQT_VEGETABLE_SRC}) SOURCE_GROUP("ovqt Plugin Widgets Src" FILES ${OVQT_WIDGETS_SRC}) -ADD_LIBRARY(ovqt_plugin_object_viewer MODULE ${SRC} +ADD_LIBRARY(studio_plugin_object_viewer MODULE ${SRC} ${OVQT_SCENE_SRC} ${OVQT_PS_SRC} ${OVQT_VEGETABLE_SRC} @@ -175,8 +175,8 @@ ADD_LIBRARY(ovqt_plugin_object_viewer MODULE ${SRC} ${OBJECT_VIEWER_PLUGIN_UI_HDRS} ${OBJECT_VIEWER_PLUGIN_RC_SRCS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_object_viewer - ovqt_plugin_core +TARGET_LINK_LIBRARIES(studio_plugin_object_viewer + studio_plugin_core nelmisc nel3d nelsound @@ -185,30 +185,30 @@ TARGET_LINK_LIBRARIES(ovqt_plugin_object_viewer ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_object_viewer "NeL, Tools, 3D: Object Viewer Qt Plugin: Object Viewer") +NL_DEFAULT_PROPS(studio_plugin_object_viewer "Tools: Studio Plugin: Object Viewer") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_object_viewer) -NL_ADD_LIB_SUFFIX(ovqt_plugin_object_viewer) +NL_ADD_RUNTIME_FLAGS(studio_plugin_object_viewer) +NL_ADD_LIB_SUFFIX(studio_plugin_object_viewer) ADD_DEFINITIONS(-DQT_NO_KEYWORDS ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WITH_PCH) - ADD_NATIVE_PRECOMPILED_HEADER(ovqt_plugin_object_viewer ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) + ADD_NATIVE_PRECOMPILED_HEADER(studio_plugin_object_viewer ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.h ${CMAKE_CURRENT_SOURCE_DIR}/stdpch.cpp) ENDIF(WITH_PCH) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_object_viewer LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml b/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml index 6033c3985..c5ae8c081 100644 --- a/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml +++ b/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml @@ -1,5 +1,5 @@ - ovqt_plugin_object_viewer + studio_plugin_object_viewer ObjectViewer 0.8 Ryzom Core diff --git a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt index 34f237757..90764e7dd 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt +++ b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt @@ -19,28 +19,28 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC}) SOURCE_GROUP("Sheet builder Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_sheet_builder MODULE ${SRC} ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC} ${OVQT_EXT_SYS_SRC}) +ADD_LIBRARY(studio_plugin_sheet_builder MODULE ${SRC} ${OVQT_PLUG_SHEET_BUILDER_MOC_SRC} ${OVQT_EXT_SYS_SRC}) -TARGET_LINK_LIBRARIES(ovqt_plugin_sheet_builder ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_sheet_builder studio_plugin_core nelmisc ${QT_LIBRARIES}) -NL_DEFAULT_PROPS(ovqt_plugin_sheet_builder "NeL, Tools, 3D: Object Viewer Qt Plugin: Sheet builder") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_sheet_builder) -NL_ADD_LIB_SUFFIX(ovqt_plugin_sheet_builder) +NL_DEFAULT_PROPS(studio_plugin_sheet_builder "Tools: Studio Plugin: Sheet builder") +NL_ADD_RUNTIME_FLAGS(studio_plugin_sheet_builder) +NL_ADD_LIB_SUFFIX(studio_plugin_sheet_builder) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_sheet_builder LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml index 01dbefa8a..4f1f3210d 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml @@ -1,5 +1,5 @@ - ovqt_plugin_sheet_builder + studio_plugin_sheet_builder SheetBuilder 1.0 kharvd diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index f3458c909..889e40ffa 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -30,18 +30,18 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_P SOURCE_GROUP("Tile Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) +ADD_LIBRARY(studio_plugin_tile_editor MODULE ${SRC} ${OVQT_TILE_EDITOR_PLUGIN_MOC_SRC} ${OVQT_PLUG_TILE_EDITOR_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_TILE_EDITOR_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ovqt_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_tile_editor studio_plugin_core nelmisc ${QT_LIBRARIES}) IF(WITH_STLPORT) - TARGET_LINK_LIBRARIES(ovqt_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) + TARGET_LINK_LIBRARIES(studio_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) ENDIF(WITH_STLPORT) -NL_DEFAULT_PROPS(ovqt_plugin_tile_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Tile Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_tile_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_tile_editor) +NL_DEFAULT_PROPS(studio_plugin_tile_editor "Tools: Studio Plugin: Tile Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_tile_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_tile_editor) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) -INSTALL(TARGETS ovqt_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file +INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml index 0e21a2eb9..d69201f9b 100644 --- a/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml +++ b/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_tile_editor + studio_plugin_tile_editor TileEditor 1.0 Ryzom Core diff --git a/code/studio/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt index 1d96ebc77..64d081484 100644 --- a/code/studio/src/plugins/translation_manager/CMakeLists.txt +++ b/code/studio/src/plugins/translation_manager/CMakeLists.txt @@ -38,27 +38,27 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC}) SOURCE_GROUP("Translation Manager Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_translation_manager MODULE ${SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_translation_manager MODULE ${SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_TRANSLATION_MANAGER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_translation_manager ovqt_plugin_core nelmisc nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) +TARGET_LINK_LIBRARIES(studio_plugin_translation_manager studio_plugin_core nelmisc nelligo nelgeorges ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) -NL_DEFAULT_PROPS(ovqt_plugin_translation_manager "NeL, Tools, 3D: Object Viewer Qt Plugin: Translation Manager") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_translation_manager) -NL_ADD_LIB_SUFFIX(ovqt_plugin_translation_manager) +NL_DEFAULT_PROPS(studio_plugin_translation_manager "Tools: Studio Plugin: Translation Manager") +NL_ADD_RUNTIME_FLAGS(studio_plugin_translation_manager) +NL_ADD_LIB_SUFFIX(studio_plugin_translation_manager) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_translation_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml b/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml index c5574777a..261fbe65a 100644 --- a/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml +++ b/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml @@ -1,5 +1,5 @@ - ovqt_plugin_translation_manager + studio_plugin_translation_manager TranslationManager 0.8 Ryzom Core diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index 150cc4c4f..5f2d421f0 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -43,15 +43,15 @@ SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} OVQT SOURCE_GROUP("World Editor Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_world_editor MODULE ${SRC} +ADD_LIBRARY(studio_plugin_world_editor MODULE ${SRC} ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS} ${OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS}) -TARGET_LINK_LIBRARIES( ovqt_plugin_world_editor - ovqt_plugin_core - ovqt_plugin_landscape_editor +TARGET_LINK_LIBRARIES( studio_plugin_world_editor + studio_plugin_core + studio_plugin_landscape_editor nelmisc nel3d qt_property_browser @@ -59,23 +59,23 @@ TARGET_LINK_LIBRARIES( ovqt_plugin_world_editor ${QT_QTOPENGL_LIBRARY} ) -NL_DEFAULT_PROPS(ovqt_plugin_world_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: World Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_world_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_world_editor) +NL_DEFAULT_PROPS(studio_plugin_world_editor "Tools: Studio Plugin: World Editor") +NL_ADD_RUNTIME_FLAGS(studio_plugin_world_editor) +NL_ADD_LIB_SUFFIX(studio_plugin_world_editor) ADD_DEFINITIONS(-DWORLD_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml b/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml index 13a157a7e..1b15af6a0 100644 --- a/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml +++ b/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml @@ -1,5 +1,5 @@ - ovqt_plugin_world_editor + studio_plugin_world_editor WorldEditor 0.6 GSoC2011_dnk-88 diff --git a/code/studio/src/plugins/zone_painter/CMakeLists.txt b/code/studio/src/plugins/zone_painter/CMakeLists.txt index 729658ab4..70c72f94c 100644 --- a/code/studio/src/plugins/zone_painter/CMakeLists.txt +++ b/code/studio/src/plugins/zone_painter/CMakeLists.txt @@ -32,28 +32,28 @@ SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_PLUG_ZONE_PAINTER_MOC_SRC} ${OVQT_PL SOURCE_GROUP("Zone Painter Plugin" FILES ${SRC}) SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) -ADD_LIBRARY(ovqt_plugin_zone_painter MODULE ${SRC} ${OVQT_PLUG_ZONE_PAINTER_MOC_SRC} ${OVQT_PLUG_ZONE_PAINTER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_ZONE_PAINTER_UI_HDRS}) +ADD_LIBRARY(studio_plugin_zone_painter MODULE ${SRC} ${OVQT_PLUG_ZONE_PAINTER_MOC_SRC} ${OVQT_PLUG_ZONE_PAINTER_RC_SRCS} ${OVQT_EXT_SYS_SRC} ${OVQT_PLUG_ZONE_PAINTER_UI_HDRS}) -TARGET_LINK_LIBRARIES(ovqt_plugin_zone_painter ovqt_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) +TARGET_LINK_LIBRARIES(studio_plugin_zone_painter studio_plugin_core nelmisc nel3d ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) -NL_DEFAULT_PROPS(ovqt_plugin_zone_painter "NeL, Tools, 3D: Object Viewer Qt Plugin: Zone Painter") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_zone_painter) -NL_ADD_LIB_SUFFIX(ovqt_plugin_zone_painter) +NL_DEFAULT_PROPS(studio_plugin_zone_painter "Tools: Studio Plugin: Zone Painter") +NL_ADD_RUNTIME_FLAGS(studio_plugin_zone_painter) +NL_ADD_LIB_SUFFIX(studio_plugin_zone_painter) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) IF(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ELSE(WIN32) IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + INSTALL(TARGETS studio_plugin_zone_painter LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) diff --git a/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml b/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml index 9a07a6be6..eb796aa42 100644 --- a/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml +++ b/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml @@ -1,5 +1,5 @@ - ovqt_plugin_zone_painter + studio_plugin_zone_painter ZonePainter 0.0 Ryzom Core From 004bca69fa0448234ac5d62181c8bd656c07a1a7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 19 May 2014 01:45:19 +0200 Subject: [PATCH 024/220] Renamed the plugin XML files. --- code/studio/src/plugins/bnp_manager/CMakeLists.txt | 2 +- ...qt_plugin_bnp_manager.xml => studio_plugin_bnp_manager.xml} | 0 code/studio/src/plugins/core/CMakeLists.txt | 2 +- .../core/{ovqt_plugin_core.xml => studio_plugin_core.xml} | 0 code/studio/src/plugins/disp_sheet_id/CMakeLists.txt | 2 +- ...lugin_disp_sheet_id.xml => studio_plugin_disp_sheet_id.xml} | 0 code/studio/src/plugins/example/CMakeLists.txt | 2 +- .../{ovqt_plugin_example.xml => studio_plugin_example.xml} | 0 code/studio/src/plugins/georges_editor/CMakeLists.txt | 2 +- ...gin_georges_editor.xml => studio_plugin_georges_editor.xml} | 0 code/studio/src/plugins/gui_editor/CMakeLists.txt | 2 +- ...ovqt_plugin_gui_editor.xml => studio_plugin_gui_editor.xml} | 0 code/studio/src/plugins/landscape_editor/CMakeLists.txt | 2 +- ...landscape_editor.xml => studio_plugin_landscape_editor.xml} | 0 code/studio/src/plugins/log/CMakeLists.txt | 2 +- .../plugins/log/{ovqt_plugin_log.xml => studio_plugin_log.xml} | 0 code/studio/src/plugins/mission_compiler/CMakeLists.txt | 2 +- ...mission_compiler.xml => studio_plugin_mission_compiler.xml} | 0 code/studio/src/plugins/object_viewer/CMakeLists.txt | 2 +- ...lugin_object_viewer.xml => studio_plugin_object_viewer.xml} | 0 code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt | 2 +- ...lugin_sheet_builder.xml => studio_plugin_sheet_builder.xml} | 0 code/studio/src/plugins/tile_editor/CMakeLists.txt | 3 ++- ...qt_plugin_tile_editor.xml => studio_plugin_tile_editor.xml} | 0 code/studio/src/plugins/translation_manager/CMakeLists.txt | 2 +- ...ation_manager.xml => studio_plugin_translation_manager.xml} | 0 code/studio/src/plugins/world_editor/CMakeLists.txt | 2 +- ..._plugin_world_editor.xml => studio_plugin_world_editor.xml} | 0 code/studio/src/plugins/zone_painter/CMakeLists.txt | 2 +- ..._plugin_zone_painter.xml => studio_plugin_zone_painter.xml} | 0 30 files changed, 16 insertions(+), 15 deletions(-) rename code/studio/src/plugins/bnp_manager/{ovqt_plugin_bnp_manager.xml => studio_plugin_bnp_manager.xml} (100%) rename code/studio/src/plugins/core/{ovqt_plugin_core.xml => studio_plugin_core.xml} (100%) rename code/studio/src/plugins/disp_sheet_id/{ovqt_plugin_disp_sheet_id.xml => studio_plugin_disp_sheet_id.xml} (100%) rename code/studio/src/plugins/example/{ovqt_plugin_example.xml => studio_plugin_example.xml} (100%) rename code/studio/src/plugins/georges_editor/{ovqt_plugin_georges_editor.xml => studio_plugin_georges_editor.xml} (100%) rename code/studio/src/plugins/gui_editor/{ovqt_plugin_gui_editor.xml => studio_plugin_gui_editor.xml} (100%) rename code/studio/src/plugins/landscape_editor/{ovqt_plugin_landscape_editor.xml => studio_plugin_landscape_editor.xml} (100%) rename code/studio/src/plugins/log/{ovqt_plugin_log.xml => studio_plugin_log.xml} (100%) rename code/studio/src/plugins/mission_compiler/{ovqt_plugin_mission_compiler.xml => studio_plugin_mission_compiler.xml} (100%) rename code/studio/src/plugins/object_viewer/{ovqt_plugin_object_viewer.xml => studio_plugin_object_viewer.xml} (100%) rename code/studio/src/plugins/ovqt_sheet_builder/{ovqt_plugin_sheet_builder.xml => studio_plugin_sheet_builder.xml} (100%) rename code/studio/src/plugins/tile_editor/{ovqt_plugin_tile_editor.xml => studio_plugin_tile_editor.xml} (100%) rename code/studio/src/plugins/translation_manager/{ovqt_plugin_translation_manager.xml => studio_plugin_translation_manager.xml} (100%) rename code/studio/src/plugins/world_editor/{ovqt_plugin_world_editor.xml => studio_plugin_world_editor.xml} (100%) rename code/studio/src/plugins/zone_painter/{ovqt_plugin_zone_painter.xml => studio_plugin_zone_painter.xml} (100%) diff --git a/code/studio/src/plugins/bnp_manager/CMakeLists.txt b/code/studio/src/plugins/bnp_manager/CMakeLists.txt index be56bc704..406a927b8 100644 --- a/code/studio/src/plugins/bnp_manager/CMakeLists.txt +++ b/code/studio/src/plugins/bnp_manager/CMakeLists.txt @@ -45,5 +45,5 @@ NL_ADD_LIB_SUFFIX(studio_plugin_bnp_manager) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) INSTALL(TARGETS studio_plugin_bnp_manager LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_bnp_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_bnp_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml b/code/studio/src/plugins/bnp_manager/studio_plugin_bnp_manager.xml similarity index 100% rename from code/studio/src/plugins/bnp_manager/ovqt_plugin_bnp_manager.xml rename to code/studio/src/plugins/bnp_manager/studio_plugin_bnp_manager.xml diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt index add4665bc..964f95b11 100644 --- a/code/studio/src/plugins/core/CMakeLists.txt +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -69,5 +69,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/core/ovqt_plugin_core.xml b/code/studio/src/plugins/core/studio_plugin_core.xml similarity index 100% rename from code/studio/src/plugins/core/ovqt_plugin_core.xml rename to code/studio/src/plugins/core/studio_plugin_core.xml diff --git a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt index 65f880f07..bce24b667 100644 --- a/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt +++ b/code/studio/src/plugins/disp_sheet_id/CMakeLists.txt @@ -55,5 +55,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_disp_sheet_id.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_disp_sheet_id.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml b/code/studio/src/plugins/disp_sheet_id/studio_plugin_disp_sheet_id.xml similarity index 100% rename from code/studio/src/plugins/disp_sheet_id/ovqt_plugin_disp_sheet_id.xml rename to code/studio/src/plugins/disp_sheet_id/studio_plugin_disp_sheet_id.xml diff --git a/code/studio/src/plugins/example/CMakeLists.txt b/code/studio/src/plugins/example/CMakeLists.txt index 9eda8916e..fd4008fc4 100644 --- a/code/studio/src/plugins/example/CMakeLists.txt +++ b/code/studio/src/plugins/example/CMakeLists.txt @@ -52,5 +52,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_example.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_example.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/example/ovqt_plugin_example.xml b/code/studio/src/plugins/example/studio_plugin_example.xml similarity index 100% rename from code/studio/src/plugins/example/ovqt_plugin_example.xml rename to code/studio/src/plugins/example/studio_plugin_example.xml diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index 044d1ed39..bab12b7e1 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -65,5 +65,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_georges_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_georges_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml b/code/studio/src/plugins/georges_editor/studio_plugin_georges_editor.xml similarity index 100% rename from code/studio/src/plugins/georges_editor/ovqt_plugin_georges_editor.xml rename to code/studio/src/plugins/georges_editor/studio_plugin_georges_editor.xml diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 909d2e993..ff248a261 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -100,4 +100,4 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_gui_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_gui_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml b/code/studio/src/plugins/gui_editor/studio_plugin_gui_editor.xml similarity index 100% rename from code/studio/src/plugins/gui_editor/ovqt_plugin_gui_editor.xml rename to code/studio/src/plugins/gui_editor/studio_plugin_gui_editor.xml diff --git a/code/studio/src/plugins/landscape_editor/CMakeLists.txt b/code/studio/src/plugins/landscape_editor/CMakeLists.txt index 9fc9e2a5a..448d86a48 100644 --- a/code/studio/src/plugins/landscape_editor/CMakeLists.txt +++ b/code/studio/src/plugins/landscape_editor/CMakeLists.txt @@ -71,4 +71,4 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_landscape_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_landscape_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml b/code/studio/src/plugins/landscape_editor/studio_plugin_landscape_editor.xml similarity index 100% rename from code/studio/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml rename to code/studio/src/plugins/landscape_editor/studio_plugin_landscape_editor.xml diff --git a/code/studio/src/plugins/log/CMakeLists.txt b/code/studio/src/plugins/log/CMakeLists.txt index 4ff8b1888..7a27f370a 100644 --- a/code/studio/src/plugins/log/CMakeLists.txt +++ b/code/studio/src/plugins/log/CMakeLists.txt @@ -51,5 +51,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_log.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_log.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/log/ovqt_plugin_log.xml b/code/studio/src/plugins/log/studio_plugin_log.xml similarity index 100% rename from code/studio/src/plugins/log/ovqt_plugin_log.xml rename to code/studio/src/plugins/log/studio_plugin_log.xml diff --git a/code/studio/src/plugins/mission_compiler/CMakeLists.txt b/code/studio/src/plugins/mission_compiler/CMakeLists.txt index d2c1a4180..cbf35b9c7 100644 --- a/code/studio/src/plugins/mission_compiler/CMakeLists.txt +++ b/code/studio/src/plugins/mission_compiler/CMakeLists.txt @@ -62,5 +62,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_mission_compiler.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_mission_compiler.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml b/code/studio/src/plugins/mission_compiler/studio_plugin_mission_compiler.xml similarity index 100% rename from code/studio/src/plugins/mission_compiler/ovqt_plugin_mission_compiler.xml rename to code/studio/src/plugins/mission_compiler/studio_plugin_mission_compiler.xml diff --git a/code/studio/src/plugins/object_viewer/CMakeLists.txt b/code/studio/src/plugins/object_viewer/CMakeLists.txt index 79e535420..3a4ce9c65 100644 --- a/code/studio/src/plugins/object_viewer/CMakeLists.txt +++ b/code/studio/src/plugins/object_viewer/CMakeLists.txt @@ -212,5 +212,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_object_viewer.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_object_viewer.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml b/code/studio/src/plugins/object_viewer/studio_plugin_object_viewer.xml similarity index 100% rename from code/studio/src/plugins/object_viewer/ovqt_plugin_object_viewer.xml rename to code/studio/src/plugins/object_viewer/studio_plugin_object_viewer.xml diff --git a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt index 90764e7dd..a543421c5 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt +++ b/code/studio/src/plugins/ovqt_sheet_builder/CMakeLists.txt @@ -44,5 +44,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_sheet_builder.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_sheet_builder.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml b/code/studio/src/plugins/ovqt_sheet_builder/studio_plugin_sheet_builder.xml similarity index 100% rename from code/studio/src/plugins/ovqt_sheet_builder/ovqt_plugin_sheet_builder.xml rename to code/studio/src/plugins/ovqt_sheet_builder/studio_plugin_sheet_builder.xml diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index 889e40ffa..d546beba1 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -44,4 +44,5 @@ NL_ADD_LIB_SUFFIX(studio_plugin_tile_editor) ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) -INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) \ No newline at end of file +INSTALL(TARGETS studio_plugin_tile_editor LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_tile_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml similarity index 100% rename from code/studio/src/plugins/tile_editor/ovqt_plugin_tile_editor.xml rename to code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml diff --git a/code/studio/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt index 64d081484..6f0f7a1c2 100644 --- a/code/studio/src/plugins/translation_manager/CMakeLists.txt +++ b/code/studio/src/plugins/translation_manager/CMakeLists.txt @@ -62,5 +62,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_translation_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_translation_manager.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml b/code/studio/src/plugins/translation_manager/studio_plugin_translation_manager.xml similarity index 100% rename from code/studio/src/plugins/translation_manager/ovqt_plugin_translation_manager.xml rename to code/studio/src/plugins/translation_manager/studio_plugin_translation_manager.xml diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index 5f2d421f0..7b76ed810 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -79,5 +79,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_world_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_world_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml b/code/studio/src/plugins/world_editor/studio_plugin_world_editor.xml similarity index 100% rename from code/studio/src/plugins/world_editor/ovqt_plugin_world_editor.xml rename to code/studio/src/plugins/world_editor/studio_plugin_world_editor.xml diff --git a/code/studio/src/plugins/zone_painter/CMakeLists.txt b/code/studio/src/plugins/zone_painter/CMakeLists.txt index 70c72f94c..94f5e85f7 100644 --- a/code/studio/src/plugins/zone_painter/CMakeLists.txt +++ b/code/studio/src/plugins/zone_painter/CMakeLists.txt @@ -57,5 +57,5 @@ ELSE(WIN32) ENDIF(WITH_INSTALL_LIBRARIES) ENDIF(WIN32) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_zone_painter.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/studio_plugin_zone_painter.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml b/code/studio/src/plugins/zone_painter/studio_plugin_zone_painter.xml similarity index 100% rename from code/studio/src/plugins/zone_painter/ovqt_plugin_zone_painter.xml rename to code/studio/src/plugins/zone_painter/studio_plugin_zone_painter.xml From e57241fe4a1413a8013737707e6aeda20d248a20 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 19 May 2014 02:08:03 +0200 Subject: [PATCH 025/220] Renames. --- code/studio/CMakeLists.txt | 2 +- code/studio/ovqt_config.h.cmake | 4 ++-- code/studio/src/main.cpp | 6 +++--- code/studio/src/plugins/core/main_window.cpp | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/code/studio/CMakeLists.txt b/code/studio/CMakeLists.txt index b301430cf..bf9ee062c 100644 --- a/code/studio/CMakeLists.txt +++ b/code/studio/CMakeLists.txt @@ -27,7 +27,7 @@ ELSE(WIN32) ENDIF(WIN32) IF(UNIX AND WITH_STATIC) - MESSAGE(FATAL_ERROR "OVQT does not work with static NeL builds on Unix atm.") + MESSAGE(FATAL_ERROR "Studio does not work with static NeL builds on Unix atm.") ENDIF() ADD_SUBDIRECTORY(src) diff --git a/code/studio/ovqt_config.h.cmake b/code/studio/ovqt_config.h.cmake index 5b3a49654..9d4907473 100644 --- a/code/studio/ovqt_config.h.cmake +++ b/code/studio/ovqt_config.h.cmake @@ -1,7 +1,7 @@ #ifndef OVQT_CONFIG_H #define OVQT_CONFIG_H -#define DATA_DIR "${NL_SHARE_ABSOLUTE_PREFIX}/object_viewer_qt" -#define PLUGINS_DIR "${NL_LIB_ABSOLUTE_PREFIX}/object_viewer_qt" +#define DATA_DIR "${NL_SHARE_ABSOLUTE_PREFIX}/studio" +#define PLUGINS_DIR "${NL_LIB_ABSOLUTE_PREFIX}/studio" #endif diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index d0407ccfd..e94bac9d6 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -164,7 +164,7 @@ int main(int argc, char **argv) pluginManager.setSettings(settings); QStringList pluginPaths; #if defined(NL_OS_MAC) - pluginPaths << settings->value("PluginPath", qApp->applicationDirPath() + QString("/../PlugIns/ovqt")).toString(); + pluginPaths << settings->value("PluginPath", qApp->applicationDirPath() + QString("/../PlugIns/studio")).toString(); #else pluginPaths << settings->value("PluginPath", QString("%1/plugins").arg(DATA_DIR)).toString(); #endif @@ -180,7 +180,7 @@ int main(int argc, char **argv) { QDir absolutePluginPaths(pluginPaths.join(QLatin1String(","))); QString absolutePaths = absolutePluginPaths.absolutePath(); - const QString reason = QCoreApplication::translate("Application", "Could not find ovqt_plugin_core in %1").arg(absolutePaths); + const QString reason = QCoreApplication::translate("Application", "Could not find studio_plugin_core in %1").arg(absolutePaths); displayError(msgCoreLoadFailure(reason)); QString newPath = QFileDialog::getExistingDirectory(0, QCoreApplication::translate("Application", "Change the plugins path"), QDir::homePath()); @@ -205,7 +205,7 @@ int main(int argc, char **argv) errors.append(spec->fileName() + " : " + spec->errorString()); if (!errors.isEmpty()) - QMessageBox::warning(0, QCoreApplication::translate("Application", "Object Viewer Qt - Plugin loader messages"), + QMessageBox::warning(0, QCoreApplication::translate("Application", "Studio - Plugin loader messages"), errors.join(QString::fromLatin1("\n\n"))); int result = app.exec(); diff --git a/code/studio/src/plugins/core/main_window.cpp b/code/studio/src/plugins/core/main_window.cpp index a90e67bc0..fcde24fbf 100644 --- a/code/studio/src/plugins/core/main_window.cpp +++ b/code/studio/src/plugins/core/main_window.cpp @@ -46,13 +46,13 @@ MainWindow::MainWindow(ExtensionSystem::IPluginManager *pluginManager, QWidget * m_undoGroup(0), m_settings(0) { - QCoreApplication::setApplicationName(QLatin1String("ObjectViewerQt")); + QCoreApplication::setApplicationName(QLatin1String("Studio")); QCoreApplication::setApplicationVersion(QLatin1String(Core::Constants::OVQT_VERSION_LONG)); QCoreApplication::setOrganizationName(QLatin1String("RyzomCore")); setObjectName(Constants::MAIN_WINDOW); setWindowIcon(QIcon(Constants::ICON_PILL)); - setWindowTitle(tr("Object Viewer Qt")); + setWindowTitle(tr("Ryzom Core Studio")); m_pluginManager = pluginManager; m_settings = m_pluginManager->settings(); @@ -232,8 +232,8 @@ bool MainWindow::showOptionsDialog(const QString &group, void MainWindow::about() { - QMessageBox::about(this, tr("About Object Viewer Qt"), - tr("

Object Viewer Qt

" + QMessageBox::about(this, tr("About Ryzom Core Studio"), + tr("

Ryzom Core Studio

" "

Ryzom Core team

Compiled on %1 %2").arg(__DATE__).arg(__TIME__)); } From b8ea03816bb1056ca65ca1e0127b4ebc3025c80f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 22 May 2014 15:06:40 +0200 Subject: [PATCH 026/220] Rename. --- code/studio/src/CMakeLists.txt | 4 ++-- code/studio/src/{object_viewer_qt.qrc => studio.qrc} | 0 code/studio/src/{object_viewer_qt.rc => studio.rc} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename code/studio/src/{object_viewer_qt.qrc => studio.qrc} (100%) rename code/studio/src/{object_viewer_qt.rc => studio.rc} (100%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index cc0c5d452..2954909fb 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -12,7 +12,7 @@ FILE(GLOB STUDIO_SRC extension_system/*.h SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h) -SET(STUDIO_RCS object_viewer_qt.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) +SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) SET(STUDIO_TS translations/object_viewer_qt_en.ts translations/object_viewer_qt_fr.ts @@ -23,7 +23,7 @@ SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) IF(WIN32) - SET(STUDIO object_viewer_qt.rc) + SET(STUDIO studio.rc) ENDIF(WIN32) QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) diff --git a/code/studio/src/object_viewer_qt.qrc b/code/studio/src/studio.qrc similarity index 100% rename from code/studio/src/object_viewer_qt.qrc rename to code/studio/src/studio.qrc diff --git a/code/studio/src/object_viewer_qt.rc b/code/studio/src/studio.rc similarity index 100% rename from code/studio/src/object_viewer_qt.rc rename to code/studio/src/studio.rc From 52666ced93fb5461531ba7adfb40d6347dbb1003 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 22 May 2014 15:56:38 +0200 Subject: [PATCH 027/220] More renames. --- code/studio/src/CMakeLists.txt | 2 +- .../images/{nel_ide_load.png => studio_splash.png} | Bin code/studio/src/{ic_nel_pill.ico => studio.ico} | Bin code/studio/src/studio.qrc | 2 +- code/studio/src/studio.rc | 6 +++--- 5 files changed, 5 insertions(+), 5 deletions(-) rename code/studio/src/images/{nel_ide_load.png => studio_splash.png} (100%) rename code/studio/src/{ic_nel_pill.ico => studio.ico} (100%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 2954909fb..4ccc932c5 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -23,7 +23,7 @@ SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) IF(WIN32) - SET(STUDIO studio.rc) + SET(STUDIO_RC studio.rc) ENDIF(WIN32) QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) diff --git a/code/studio/src/images/nel_ide_load.png b/code/studio/src/images/studio_splash.png similarity index 100% rename from code/studio/src/images/nel_ide_load.png rename to code/studio/src/images/studio_splash.png diff --git a/code/studio/src/ic_nel_pill.ico b/code/studio/src/studio.ico similarity index 100% rename from code/studio/src/ic_nel_pill.ico rename to code/studio/src/studio.ico diff --git a/code/studio/src/studio.qrc b/code/studio/src/studio.qrc index 13d47d75b..17306e2cc 100644 --- a/code/studio/src/studio.qrc +++ b/code/studio/src/studio.qrc @@ -1,5 +1,5 @@ - images/nel_ide_load.png + images/studio_splash.png diff --git a/code/studio/src/studio.rc b/code/studio/src/studio.rc index a0f0e7099..05ade2766 100644 --- a/code/studio/src/studio.rc +++ b/code/studio/src/studio.rc @@ -28,12 +28,12 @@ BEGIN VALUE "CompanyName", "Ryzom Core\0" VALUE "FileDescription", "\0" VALUE "FileVersion", "1, 0, 0, 1\0" - VALUE "InternalName", "Object_Viewer_Qt\0" + VALUE "InternalName", "Ryzom Core Studio\0" VALUE "LegalCopyright", "Copyright (C) 2011\0" VALUE "LegalTrademarks", "\0" VALUE "OriginalFilename", "\0" VALUE "PrivateBuild", "\0" - VALUE "ProductName", "Object Viewer Qt\0" + VALUE "ProductName", "Ryzom Core Studio\0" VALUE "ProductVersion", "1, 0, 0, 1\0" VALUE "SpecialBuild", "\0" END @@ -51,4 +51,4 @@ END // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDR_MAINFRAME ICON DISCARDABLE "ic_nel_pill.ico" +IDR_MAINFRAME ICON DISCARDABLE "studio.ico" From e56af869abad93ebc7601b69003f07cf620d4d9e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 23 May 2014 02:26:31 +0200 Subject: [PATCH 028/220] Moved plugin menu items to their own sub-menu into the menubar. --- code/studio/src/plugins/core/main_window.cpp | 6 +-- .../plugins/gui_editor/gui_editor_window.cpp | 6 +-- .../src/plugins/object_viewer/main_window.cpp | 47 +++++++++---------- .../translation_manager_main_window.cpp | 7 ++- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/code/studio/src/plugins/core/main_window.cpp b/code/studio/src/plugins/core/main_window.cpp index fcde24fbf..4ccd32564 100644 --- a/code/studio/src/plugins/core/main_window.cpp +++ b/code/studio/src/plugins/core/main_window.cpp @@ -438,9 +438,6 @@ void MainWindow::createMenus() m_toolsMenu = m_menuBar->addMenu(tr("&Tools")); menuManager()->registerMenu(m_toolsMenu, Constants::M_TOOLS); - m_sheetMenu = m_toolsMenu->addMenu(tr("&Sheet")); - menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); - // m_toolsMenu->addSeparator(); m_toolsMenu->addAction(m_settingsAction); @@ -452,6 +449,9 @@ void MainWindow::createMenus() m_helpMenu->addAction(m_aboutAction); m_helpMenu->addAction(m_aboutQtAction); m_helpMenu->addAction(m_pluginViewAction); + + m_sheetMenu = m_menuBar->addMenu(tr("&Sheet")); + menuManager()->registerMenu(m_sheetMenu, Constants::M_SHEET); } void MainWindow::createStatusBar() diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 341338d8d..24ecc5cfc 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -360,11 +360,9 @@ namespace GUIEditor connect( delAction, SIGNAL( triggered( bool ) ), messageProcessor, SLOT( onDelete() ) ); } - QMenu *menu = mm->menu( Core::Constants::M_TOOLS ); - if( menu != NULL ) + QMenu *m = mm->menuBar()->addMenu( "GUI Editor" ); + if( m != NULL ) { - QMenu *m = menu->addMenu( "GUI Editor" ); - QAction *a = new QAction( "Widget Properties", this ); connect( a, SIGNAL( triggered( bool ) ), widgetProps, SLOT( show() ) ); m->addAction( a ); diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index bccf7a6b1..91f832ac0 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -270,55 +270,51 @@ void CMainWindow::createMenus() menuManager->registerAction(_reloadTexturesAction, "ObjectViewer.View.ReloadTextures"); menuManager->registerAction(_saveScreenshotAction, "ObjectViewer.View.SaveScreenshot"); - // add actions in view menu - QMenu *viewMenu = menuManager->menu(Core::Constants::M_VIEW); - viewMenu->addAction(_setBackColorAction); - viewMenu->addAction(_SetupFog->toggleViewAction()); - viewMenu->addAction(_resetSceneAction); - viewMenu->addAction(_reloadTexturesAction); - viewMenu->addAction(_saveScreenshotAction); - - // add actions in tools menu - QMenu *toolsMenu = menuManager->menu(Core::Constants::M_TOOLS); - QAction *settingsAction = menuManager->action(Core::Constants::SETTINGS); - QMenu *ovMenu = new QMenu("Object Viewer", this); + QMenu *ovMenu = menuManager->menuBar()->addMenu( "Object Viewer" ); menuManager->registerMenu(ovMenu, "ObjectViewerQt.ObjectViewer"); - toolsMenu->insertMenu(settingsAction, ovMenu); - ovMenu->insertAction(settingsAction ,_AnimationDialog->toggleViewAction()); + ovMenu->addAction(_setBackColorAction); + ovMenu->addAction(_SetupFog->toggleViewAction()); + ovMenu->addAction(_resetSceneAction); + ovMenu->addAction(_reloadTexturesAction); + ovMenu->addAction(_saveScreenshotAction); + + ovMenu->addSeparator(); + + ovMenu->addAction(_AnimationDialog->toggleViewAction() ); _AnimationDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_ANIM)); - ovMenu->insertAction(settingsAction ,_AnimationSetDialog->toggleViewAction()); + ovMenu->addAction(_AnimationSetDialog->toggleViewAction()); _AnimationSetDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_ANIMSET)); - ovMenu->insertAction(settingsAction ,_SlotManagerDialog->toggleViewAction()); + ovMenu->addAction(_SlotManagerDialog->toggleViewAction()); _SlotManagerDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_MIXER)); - ovMenu->insertAction(settingsAction ,_ParticleControlDialog->toggleViewAction()); + ovMenu->addAction(_ParticleControlDialog->toggleViewAction()); _ParticleControlDialog->toggleViewAction()->setIcon(QIcon(":/images/pqrticles.png")); - ovMenu->insertAction(settingsAction ,_DayNightDialog->toggleViewAction()); + ovMenu->addAction(_DayNightDialog->toggleViewAction()); _DayNightDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_DAYNIGHT)); - ovMenu->insertAction(settingsAction ,_WaterPoolDialog->toggleViewAction()); + ovMenu->addAction(_WaterPoolDialog->toggleViewAction()); _WaterPoolDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_WATER)); _WaterPoolDialog->toggleViewAction()->setEnabled(false); - ovMenu->insertAction(settingsAction ,_VegetableDialog->toggleViewAction()); + ovMenu->addAction(_VegetableDialog->toggleViewAction()); _VegetableDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_VEGET)); - ovMenu->insertAction(settingsAction ,_GlobalWindDialog->toggleViewAction()); + ovMenu->addAction(_GlobalWindDialog->toggleViewAction()); _GlobalWindDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_WIND)); - ovMenu->insertAction(settingsAction ,_SkeletonScaleDialog->toggleViewAction()); + ovMenu->addAction(_SkeletonScaleDialog->toggleViewAction()); _SkeletonScaleDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_SKELSCALE)); - ovMenu->insertAction(settingsAction ,_TuneTimerDialog->toggleViewAction()); + ovMenu->addAction(_TuneTimerDialog->toggleViewAction()); _TuneTimerDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_FRAMEDELAY)); - ovMenu->insertAction(settingsAction ,_SunColorDialog->toggleViewAction()); + ovMenu->addAction(_SunColorDialog->toggleViewAction()); - ovMenu->insertAction(settingsAction ,_TuneMRMDialog->toggleViewAction()); + ovMenu->addAction(_TuneMRMDialog->toggleViewAction()); _TuneMRMDialog->toggleViewAction()->setIcon(QIcon(Constants::ICON_MRM_MESH)); connect(_ParticleControlDialog->toggleViewAction(), SIGNAL(triggered(bool)), @@ -327,7 +323,6 @@ void CMainWindow::createMenus() connect(_ParticleControlDialog->toggleViewAction(), SIGNAL(triggered(bool)), _ParticleWorkspaceDialog->_PropertyDialog, SLOT(setVisible(bool))); - toolsMenu->insertSeparator(settingsAction); } void CMainWindow::createToolBars() diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 9fcb9626a..d80ffe3f5 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -129,7 +129,12 @@ void CMainWindow::createToolbar() // Windows menu Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - windowMenu = menuManager->menuBar()->addMenu("Window"); + QMenu *m = menuManager->menuBar()->addMenu( "Translation Manager" ); + if( m != NULL ) + { + windowMenu = m->addMenu("Window"); + } + updateWindowsList(); connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); From 4175957faf03fe66a0ee421b5efacce3552b6c1b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 25 May 2014 22:45:34 +0200 Subject: [PATCH 029/220] More renames. --- code/studio/src/extension_system/plugin_manager.cpp | 2 +- code/studio/src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 9b9da508b..a976583fb 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -183,7 +183,7 @@ void PluginManager::readPluginPaths() while (!searchPaths.isEmpty()) { const QDir dir(searchPaths.takeFirst()); - const QFileInfoList files = dir.entryInfoList(QStringList() << QString("ovqt_plugin_*.%1").arg(m_extension), QDir::Files); + const QFileInfoList files = dir.entryInfoList(QStringList() << QString("studio_plugin_*.%1").arg(m_extension), QDir::Files); Q_FOREACH (const QFileInfo &file, files) pluginsList << file.absoluteFilePath(); const QFileInfoList dirs = dir.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot); diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index e94bac9d6..d4b3f8d75 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -139,7 +139,7 @@ int main(int argc, char **argv) QApplication app(argc, argv); #endif // NL_OS_WINDOWS QSplashScreen *splash = new QSplashScreen(); - splash->setPixmap(QPixmap(":/images/nel_ide_load.png")); + splash->setPixmap(QPixmap(":/images/studio_splash.png")); splash->show(); QSettings::setDefaultFormat(QSettings::IniFormat); From e85f3dc438101d0e28561e6f77b1e206dff20915 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 26 May 2014 21:04:05 +0200 Subject: [PATCH 030/220] Settings dialog on first startup. --- code/studio/src/CMakeLists.txt | 11 +- code/studio/src/main.cpp | 16 +- code/studio/src/settings_dialog.cpp | 236 +++++++++++++++++++++++++ code/studio/src/settings_dialog.h | 62 +++++++ code/studio/src/settings_dialog.ui | 255 ++++++++++++++++++++++++++++ 5 files changed, 576 insertions(+), 4 deletions(-) create mode 100644 code/studio/src/settings_dialog.cpp create mode 100644 code/studio/src/settings_dialog.h create mode 100644 code/studio/src/settings_dialog.ui diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 4ccc932c5..e41bd4778 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -10,7 +10,8 @@ FILE(GLOB STUDIO_SRC extension_system/*.h *.h *.cpp) SET(STUDIO_HDR extension_system/iplugin_manager.h - extension_system/plugin_manager.h) + extension_system/plugin_manager.h + settings_dialog.h ) SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) @@ -18,6 +19,8 @@ SET(STUDIO_TS translations/object_viewer_qt_en.ts translations/object_viewer_qt_fr.ts translations/object_viewer_qt_de.ts translations/object_viewer_qt_ru.ts) + +SET(STUDIO_PLUGIN_UIS settings_dialog.ui ) SET(QT_USE_QTGUI TRUE) SET(QT_USE_QTOPENGL TRUE) @@ -29,15 +32,17 @@ ENDIF(WIN32) QT4_ADD_TRANSLATION(STUDIO_QM ${STUDIO_TS}) QT4_ADD_RESOURCES( STUDIO_RC_SRCS ${STUDIO_RCS}) QT4_WRAP_CPP( STUDIO_MOC_SRCS ${STUDIO_HDR} ) +QT4_WRAP_UI( STUDIO_PLUGIN_UI_HDRS ${STUDIO_PLUGIN_UIS}) -SOURCE_GROUP(QtResources FILES ${STUDIO_RCS}) +SOURCE_GROUP(QtResources FILES ${STUDIO_RCS} ${STUDIO_PLUGIN_UIS} ) SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${STUDIO_MOC_SRCS} ${STUDIO_RC_SRCS}) ADD_EXECUTABLE(studio WIN32 MACOSX_BUNDLE ${STUDIO_SRC} ${STUDIO_MOC_SRCS} ${STUDIO_RC_SRCS} - ${STUDIO_RC}) + ${STUDIO_RC} + ${STUDIO_PLUGIN_UIS} ) TARGET_LINK_LIBRARIES(studio nelmisc diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index d4b3f8d75..1f316f677 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -41,11 +41,13 @@ #include #include +#include "settings_dialog.h" + #ifdef HAVE_OVQT_CONFIG_H #include "ovqt_config.h" #endif -static const char *appNameC = "ObjectViewerQt"; +static const char *appNameC = "RyzomCoreStudio"; // nel_qt log file name #define NLQT_LOG_FILE "nel_qt.log" @@ -138,6 +140,7 @@ int main(int argc, char **argv) #else // NL_OS_WINDOWS QApplication app(argc, argv); #endif // NL_OS_WINDOWS + QSplashScreen *splash = new QSplashScreen(); splash->setPixmap(QPixmap(":/images/studio_splash.png")); splash->show(); @@ -146,6 +149,17 @@ int main(int argc, char **argv) QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, QLatin1String("RyzomCore"), QLatin1String(appNameC)); + bool firstRun = settings->value( "FirstRun", true ).toBool(); + if( firstRun ) + { + settings->setValue( "FirstRun", false ); + + SettingsDialog sd; + sd.setSettings( settings ); + sd.load(); + sd.exec(); + } + QTranslator translator; QTranslator qtTranslator; QString locale = settings->value("Language", QLocale::system().name()).toString(); diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/settings_dialog.cpp new file mode 100644 index 000000000..30eb39f0f --- /dev/null +++ b/code/studio/src/settings_dialog.cpp @@ -0,0 +1,236 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "settings_dialog.h" +#include +#include +#include + +int findListItem( QListWidget *l, const QString &s ) +{ + for( int i = 0; i < l->count(); i++ ) + { + QListWidgetItem *item = l->item( i ); + if( item->text() == s ) + return i; + } + + return -1; +} + +SettingsDialog::SettingsDialog( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); + settings = NULL; +} + +SettingsDialog::~SettingsDialog() +{ +} + +void SettingsDialog::load() +{ + pluginsLE->setText( settings->value( "PluginPath" ).toString() ); + + settings->beginGroup( "DataPath" ); + + sheetsLE->setText( settings->value( "LevelDesignPath" ).toString() ); + assetsLE->setText( settings->value( "AssetsPath" ).toString() ); + primitivesLE->setText( settings->value( "PrimitivesPath" ).toString() ); + ligoLE->setText( settings->value( "LigoConfigFile" ).toString() ); + + QStringList l = settings->value( "SearchPaths" ).toStringList(); + { + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + QString p = itr.next(); + if( findListItem( searchLW, p ) == -1 ) + searchLW->addItem( p ); + } + } + + l.clear(); + + l = settings->value( "RecursiveSearchPathes" ).toStringList(); + { + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + QString p = itr.next(); + if( findListItem( recursiveLW, p ) == -1 ) + recursiveLW->addItem( p ); + } + } + + settings->endGroup(); +} + +void SettingsDialog::saveSearchPaths() +{ + QStringList l; + for( int i = 0; i < searchLW->count(); i++ ) + { + l.push_back( searchLW->item( i )->text() ); + } + + settings->setValue( "SearchPaths", l ); +} + +void SettingsDialog::saveRecursivePaths() +{ + QStringList l; + for( int i = 0; i < recursiveLW->count(); i++ ) + { + l.push_back( recursiveLW->item( i )->text() ); + } + + settings->setValue( "RecursiveSearchPathes", l ); +} + +void SettingsDialog::save() +{ + settings->setValue( "PluginPath", pluginsLE->text() ); + + settings->beginGroup( "DataPath" ); + + settings->setValue( "LevelDesignPath", sheetsLE->text() ); + settings->setValue( "AssetsPath", assetsLE->text() ); + settings->setValue( "PrimitivesPath", primitivesLE->text() ); + settings->setValue( "LigoConfigFile", ligoLE->text() ); + + saveSearchPaths(); + saveRecursivePaths(); + + settings->endGroup(); + + settings->sync(); +} + +void SettingsDialog::accept() +{ + save(); + QDialog::accept(); +} + +void SettingsDialog::reject() +{ + QDialog::reject(); +} + +void SettingsDialog::onOKClicked() +{ + accept(); +} + +void SettingsDialog::onCancelClicked() +{ + reject(); +} + +void SettingsDialog::onPluginBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Plugins directory" ), "" ); + pluginsLE->setText( p ); +} + +void SettingsDialog::onSheetsBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Sheets directory" ), "" ); + sheetsLE->setText( p ); +} + +void SettingsDialog::onAssetsBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Assets directory" ), "" ); + assetsLE->setText( p ); +} + +void SettingsDialog::onPrimitivesBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Primitives directory" ), "" ); + primitivesLE->setText( p ); +} + +void SettingsDialog::onLigoBClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "LIGO directory" ), "" ); + ligoLE->setText( p ); +} + +void SettingsDialog::onPathAddClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Search path" ), "" ); + if( p.isEmpty() ) + return; + + if( findListItem( searchLW, p ) != -1 ) + return; + + searchLW->addItem( p ); +} + +void SettingsDialog::onPathRemoveClicked() +{ + QListWidgetItem *i = searchLW->currentItem(); + if( i == NULL ) + return; + + delete i; +} + +void SettingsDialog::onRecursiveAddClicked() +{ + QString p = QFileDialog::getExistingDirectory( this, tr( "Recursive search path" ), "" ); + if( p.isEmpty() ) + return; + + if( findListItem( recursiveLW, p ) != -1 ) + return; + + recursiveLW->addItem( p ); +} + +void SettingsDialog::onRecursiveRemoveClicked() +{ + QListWidgetItem *i = recursiveLW->currentItem(); + if( i == NULL ) + return; + + delete i; +} + + +void SettingsDialog::setupConnections() +{ + connect( bb, SIGNAL( accepted() ), this, SLOT( onOKClicked() ) ); + connect( bb, SIGNAL( rejected() ), this, SLOT( onCancelClicked() ) ); + + connect( pluginsB, SIGNAL( clicked( bool ) ), this, SLOT( onPluginBClicked() ) ); + connect( sheetsB, SIGNAL( clicked( bool ) ), this, SLOT( onSheetsBClicked() ) ); + connect( assetsB, SIGNAL( clicked( bool ) ), this, SLOT( onAssetsBClicked() ) ); + connect( primitivesB, SIGNAL( clicked( bool ) ), this, SLOT( onPrimitivesBClicked() ) ); + connect( ligoB, SIGNAL( clicked( bool ) ), this, SLOT( onLigoBClicked() ) ); + + connect( pathAddB, SIGNAL( clicked( bool ) ), this, SLOT( onPathAddClicked() ) ); + connect( pathRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onPathRemoveClicked() ) ); + connect( recAddB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveAddClicked() ) ); + connect( recRemoveB, SIGNAL( clicked( bool ) ), this, SLOT( onRecursiveRemoveClicked() ) ); +} + diff --git a/code/studio/src/settings_dialog.h b/code/studio/src/settings_dialog.h new file mode 100644 index 000000000..11a3434f1 --- /dev/null +++ b/code/studio/src/settings_dialog.h @@ -0,0 +1,62 @@ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SETTINGS_DIALOG_H +#define SETTINGS_DIALOG_H + +#include "ui_settings_dialog.h" + +class QSettings; + +class SettingsDialog : public QDialog, public Ui::SettingsDialog +{ + Q_OBJECT +public: + SettingsDialog( QDialog *parent = NULL ); + ~SettingsDialog(); + + void setSettings( QSettings *s ){ settings = s; } + + void load(); + +public Q_SLOTS: + void accept(); + void reject(); + + void onOKClicked(); + void onCancelClicked(); + + void onPluginBClicked(); + void onSheetsBClicked(); + void onAssetsBClicked(); + void onPrimitivesBClicked(); + void onLigoBClicked(); + + void onPathAddClicked(); + void onPathRemoveClicked(); + void onRecursiveAddClicked(); + void onRecursiveRemoveClicked(); + +private: + void setupConnections(); + void save(); + void saveSearchPaths(); + void saveRecursivePaths(); + + QSettings *settings; +}; + +#endif diff --git a/code/studio/src/settings_dialog.ui b/code/studio/src/settings_dialog.ui new file mode 100644 index 000000000..2fb6151d3 --- /dev/null +++ b/code/studio/src/settings_dialog.ui @@ -0,0 +1,255 @@ + + + SettingsDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 451 + 539 + + + + Ryzom Core Studio settings + + + + + + Paths + + + + + + Plugins + + + + + + + + + + ... + + + + + + + Sheets + + + + + + + + + + ... + + + + + + + Assets database + + + + + + + + + + ... + + + + + + + Primitives + + + + + + + + + + ... + + + + + + + LIGO config file + + + + + + + + + + ... + + + + + + + + + + Search paths + + + + + + + + + + 0 + 0 + + + + Add + + + Qt::ToolButtonTextOnly + + + + + + + + 0 + 0 + + + + Remove + + + Qt::ToolButtonTextOnly + + + + + + + Qt::Vertical + + + + 20 + 75 + + + + + + + + + + + Recursive search paths + + + + + + + + + + 0 + 0 + + + + Add + + + Qt::ToolButtonTextOnly + + + + + + + + 0 + 0 + + + + Remove + + + Qt::ToolButtonTextOnly + + + + + + + Qt::Vertical + + + + 20 + 76 + + + + + + + + + + + Qt::Horizontal + + + + 120 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + From 06724d4cb0b2ccebdfa18a1cd265ffc34c683564 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 26 May 2014 21:07:39 +0200 Subject: [PATCH 031/220] rename. --- code/studio/src/settings_dialog.cpp | 2 +- code/studio/src/settings_dialog.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/settings_dialog.cpp index 30eb39f0f..6824b0f56 100644 --- a/code/studio/src/settings_dialog.cpp +++ b/code/studio/src/settings_dialog.cpp @@ -1,4 +1,4 @@ -// Object Viewer Qt - MMORPG Framework +// Ryzom Core - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify diff --git a/code/studio/src/settings_dialog.h b/code/studio/src/settings_dialog.h index 11a3434f1..c6e7cc93a 100644 --- a/code/studio/src/settings_dialog.h +++ b/code/studio/src/settings_dialog.h @@ -1,4 +1,4 @@ -// Object Viewer Qt - MMORPG Framework +// Ryzom Core - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify From 2eb031ac3c0dac7b5e992696932ae930759df5af Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 4 Jun 2014 22:09:11 +0200 Subject: [PATCH 032/220] First iteration of the new splash screen. --- code/studio/src/CMakeLists.txt | 3 +- code/studio/src/main.cpp | 10 +++- code/studio/src/splash_screen.cpp | 85 +++++++++++++++++++++++++++++++ code/studio/src/splash_screen.h | 42 +++++++++++++++ 4 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 code/studio/src/splash_screen.cpp create mode 100644 code/studio/src/splash_screen.h diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index e41bd4778..216acdac2 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -11,7 +11,8 @@ FILE(GLOB STUDIO_SRC extension_system/*.h SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h - settings_dialog.h ) + settings_dialog.h + splash_screen.h ) SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index 1f316f677..8cb056037 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -37,11 +37,12 @@ #include #include #include -#include +//#include #include #include #include "settings_dialog.h" +#include "splash_screen.h" #ifdef HAVE_OVQT_CONFIG_H #include "ovqt_config.h" @@ -141,8 +142,11 @@ int main(int argc, char **argv) QApplication app(argc, argv); #endif // NL_OS_WINDOWS - QSplashScreen *splash = new QSplashScreen(); + SplashScreen *splash = new SplashScreen(); splash->setPixmap(QPixmap(":/images/studio_splash.png")); + splash->setProgressBarEnabled( true ); + splash->setText( "Starting up..." ); + splash->setProgress( 0 ); splash->show(); QSettings::setDefaultFormat(QSettings::IniFormat); @@ -184,6 +188,8 @@ int main(int argc, char **argv) #endif pluginManager.setPluginPaths(pluginPaths); + splash->setText( "Loading plugins..." ); + splash->setProgress( 20 ); pluginManager.loadPlugins(); splash->hide(); diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp new file mode 100644 index 000000000..bddfd1dc2 --- /dev/null +++ b/code/studio/src/splash_screen.cpp @@ -0,0 +1,85 @@ +#include "splash_screen.h" +#include +#include +#include +#include + +SplashScreen::SplashScreen() : +QSplashScreen() +{ + progress = 0; + textX = 5; + textY = 20; + pbLeft = 0; + pbTop = 0; + pbWidth = 100; + pbHeight = 20; +} + +SplashScreen::~SplashScreen() +{ +} + +void SplashScreen::setPixmap( const QPixmap &pixmap ) +{ + QSplashScreen::setPixmap( pixmap ); + + if( this->pixmap().width() > 0 ) + pbWidth = this->pixmap().width(); + + if( this->pixmap().height() > 0 ) + pbTop = this->pixmap().height() - pbHeight; + + textY = pbTop - pbHeight; +} + +void SplashScreen::setText( const QString &text ) +{ + this->text = text; + repaint(); + QCoreApplication::instance()->processEvents(); +} + +void SplashScreen::clearText() +{ + setText( "" ); +} + +void SplashScreen::setProgress( int percent ) +{ + progress = percent; + repaint(); + QCoreApplication::instance()->processEvents(); +} + +void SplashScreen::drawContents( QPainter *painter ) +{ + QSplashScreen::drawContents( painter ); + + if( progressBarEnabled ) + { + QStyleOptionProgressBarV2 pbStyle; + pbStyle.initFrom( this ); + pbStyle.state = QStyle::State_Enabled; + pbStyle.textVisible = false; + pbStyle.minimum = 0; + pbStyle.maximum = 100; + pbStyle.progress = progress; + pbStyle.invertedAppearance = false; + pbStyle.rect = QRect( 0, pbTop, pbWidth, pbHeight ); + + style()->drawControl( QStyle::CE_ProgressBar, &pbStyle, painter, this ); + } + + if( !text.isEmpty() ) + { + QPen oldPen = painter->pen(); + QPen pen; + pen.setColor( Qt::white ); + painter->setPen( pen ); + painter->drawText( textX, textY, text ); + painter->setPen( oldPen ); + } +} + + diff --git a/code/studio/src/splash_screen.h b/code/studio/src/splash_screen.h new file mode 100644 index 000000000..5d1889da5 --- /dev/null +++ b/code/studio/src/splash_screen.h @@ -0,0 +1,42 @@ +#ifndef SPLASH_SCREEN_H +#define SPLASH_SCREEN_H + + +#include + +class SplashScreen : public QSplashScreen +{ + Q_OBJECT +public: + SplashScreen(); + ~SplashScreen(); + + void setPixmap( const QPixmap &pixmap ); + + void setText( const QString &text ); + void clearText(); + void setTextXY( int x, int y ){ textX = x; textY = y; } + void setProgress( int percent ); + + void setProgressBarEnabled( bool b ){ progressBarEnabled = b; } + void setProgressBarRect( int left, int top, int width, int height ){} + +protected: + void drawContents( QPainter *painter ); + +private: + int progress; + int pbLeft; + int pbTop; + int pbWidth; + int pbHeight; + + QString text; + int textX; + int textY; + + bool progressBarEnabled; +}; + +#endif + From 4473be7fc6ba1860d3fc70f976d16de86accc5ce Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 4 Jun 2014 22:30:32 +0200 Subject: [PATCH 033/220] Somehow I always forget the banners... --- code/studio/src/splash_screen.cpp | 17 +++++++++++++++++ code/studio/src/splash_screen.h | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index bddfd1dc2..303459ff0 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -1,3 +1,20 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "splash_screen.h" #include #include diff --git a/code/studio/src/splash_screen.h b/code/studio/src/splash_screen.h index 5d1889da5..3fa2458cb 100644 --- a/code/studio/src/splash_screen.h +++ b/code/studio/src/splash_screen.h @@ -1,3 +1,20 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef SPLASH_SCREEN_H #define SPLASH_SCREEN_H From 9d347a9993da7f218045f15cf3f9c7e8d1289455 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 5 Jun 2014 01:57:13 +0200 Subject: [PATCH 034/220] The splash screen will now inform the user about what's happening. --- code/studio/src/CMakeLists.txt | 3 +- .../src/extension_system/iplugin_manager.h | 4 ++ .../src/extension_system/plugin_manager.cpp | 3 + code/studio/src/main.cpp | 14 ++++- code/studio/src/pm_watcher.cpp | 61 ++++++++++++++++++ code/studio/src/pm_watcher.h | 63 +++++++++++++++++++ 6 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 code/studio/src/pm_watcher.cpp create mode 100644 code/studio/src/pm_watcher.h diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 216acdac2..9bc071bf2 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -12,7 +12,8 @@ FILE(GLOB STUDIO_SRC extension_system/*.h SET(STUDIO_HDR extension_system/iplugin_manager.h extension_system/plugin_manager.h settings_dialog.h - splash_screen.h ) + splash_screen.h + pm_watcher.h ) SET(STUDIO_RCS studio.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index e38748e77..1c8eea5d4 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -133,6 +133,10 @@ Q_SIGNALS: /// Signal that the list of available plugins has changed. void pluginsChanged(); + + void pluginLoading( const char *plugin ); + void pluginInitializing( const char *plugin ); + void pluginStarting( const char *plugin ); }; }; // namespace ExtensionSystem diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index a976583fb..4dcb40d31 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -218,6 +218,7 @@ void PluginManager::setPluginState(PluginSpec *spec, int destState) spec->resolveDependencies(m_pluginSpecs); return; case State::Running: + Q_EMIT pluginStarting( spec->name().toUtf8().data() ); spec->initializeExtensions(); return; case State::Deleted: @@ -239,9 +240,11 @@ void PluginManager::setPluginState(PluginSpec *spec, int destState) switch (destState) { case State::Loaded: + Q_EMIT pluginLoading( spec->name().toUtf8().data() ); spec->loadLibrary(); return; case State::Initialized: + Q_EMIT pluginInitializing( spec->name().toUtf8().data() ); spec->initializePlugin(); break; case State::Stopped: diff --git a/code/studio/src/main.cpp b/code/studio/src/main.cpp index 8cb056037..e758037c0 100644 --- a/code/studio/src/main.cpp +++ b/code/studio/src/main.cpp @@ -43,6 +43,7 @@ #include "settings_dialog.h" #include "splash_screen.h" +#include "pm_watcher.h" #ifdef HAVE_OVQT_CONFIG_H #include "ovqt_config.h" @@ -107,6 +108,7 @@ static inline QString msgCoreLoadFailure(const QString &why) return QCoreApplication::translate("Application", "Failed to load Core plugin: %1").arg(why); } + #ifdef NL_OS_WINDOWS int __stdcall WinMain(void *hInstance, void *hPrevInstance, void *lpCmdLine, int nShowCmd) #else // NL_OS_WINDOWS @@ -173,6 +175,9 @@ int main(int argc, char **argv) app.installTranslator(&translator); app.installTranslator(&qtTranslator); + splash->setText( "Loading plugins..." ); + splash->setProgress( 20 ); + #if defined(NL_OS_MAC) QDir::setCurrent(qApp->applicationDirPath() + QString("/../Resources")); NLMISC::CLibrary::addLibPath((qApp->applicationDirPath() + QString("/../PlugIns/nel")).toUtf8().constData()); @@ -188,10 +193,15 @@ int main(int argc, char **argv) #endif pluginManager.setPluginPaths(pluginPaths); - splash->setText( "Loading plugins..." ); - splash->setProgress( 20 ); + + PluginManagerWatcher watcher; + watcher.setPluginManager( &pluginManager ); + watcher.setSplashScreen( splash ); + watcher.connect(); + pluginManager.loadPlugins(); + watcher.disconnect(); splash->hide(); ExtensionSystem::IPluginSpec *corePlugin = pluginManager.pluginByName("Core"); diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp new file mode 100644 index 000000000..350fd886a --- /dev/null +++ b/code/studio/src/pm_watcher.cpp @@ -0,0 +1,61 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "pm_watcher.h" +#include "extension_system\iplugin_manager.h" +#include "splash_screen.h" + +void PluginManagerWatcher::connect() +{ + QObject::connect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::disconnect() +{ + QObject::disconnect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::onPluginLoading( const char *plugin ) +{ + QString s = "Loading plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginInitializing( const char *plugin ) +{ + QString s = "Initializing plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginStarting( const char *plugin ) +{ + QString s = "Starting plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + + + diff --git a/code/studio/src/pm_watcher.h b/code/studio/src/pm_watcher.h new file mode 100644 index 000000000..fe2755783 --- /dev/null +++ b/code/studio/src/pm_watcher.h @@ -0,0 +1,63 @@ +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef PM_WATCHER_H +#define PM_WATCHER_H + +#include + +namespace ExtensionSystem +{ + class IPluginManager; +} + +class SplashScreen; +class PluginManager; + +class PluginManagerWatcher : public QObject +{ + Q_OBJECT +public: + PluginManagerWatcher(){ + sp = NULL; + pm = NULL; + } + + ~PluginManagerWatcher(){ + sp = NULL; + pm = NULL; + } + + void setSplashScreen( SplashScreen *s ){ sp = s; } + void setPluginManager( ExtensionSystem::IPluginManager *m ){ pm = m; } + + void connect(); + void disconnect(); + +private Q_SLOTS: + void onPluginLoading( const char *plugin ); + void onPluginInitializing( const char *plugin ); + void onPluginStarting( const char *plugin ); + +private: + SplashScreen *sp; + ExtensionSystem::IPluginManager *pm; +}; + + +#endif + From 89d0222657a56a7bd682d32aaa5cd047a7eb81a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 16:41:39 +0200 Subject: [PATCH 035/220] Line endings... --- code/studio/src/pm_watcher.cpp | 114 ++++++++++++++++----------------- code/studio/src/pm_watcher.h | 70 ++++++++++---------- 2 files changed, 92 insertions(+), 92 deletions(-) diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp index 350fd886a..1a029a1a3 100644 --- a/code/studio/src/pm_watcher.cpp +++ b/code/studio/src/pm_watcher.cpp @@ -1,61 +1,61 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "pm_watcher.h" -#include "extension_system\iplugin_manager.h" -#include "splash_screen.h" - -void PluginManagerWatcher::connect() +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "pm_watcher.h" +#include "extension_system\iplugin_manager.h" +#include "splash_screen.h" + +void PluginManagerWatcher::connect() { QObject::connect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); - QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); - QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); -} - -void PluginManagerWatcher::disconnect() + QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::disconnect() { QObject::disconnect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); - QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); - QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); -} - -void PluginManagerWatcher::onPluginLoading( const char *plugin ) -{ - QString s = "Loading plugin "; - s += plugin; - s += "..."; - sp->setText( s ); -} - -void PluginManagerWatcher::onPluginInitializing( const char *plugin ) -{ - QString s = "Initializing plugin "; - s += plugin; - s += "..."; - sp->setText( s ); -} - -void PluginManagerWatcher::onPluginStarting( const char *plugin ) -{ - QString s = "Starting plugin "; - s += plugin; - s += "..."; - sp->setText( s ); -} - - - + QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); +} + +void PluginManagerWatcher::onPluginLoading( const char *plugin ) +{ + QString s = "Loading plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginInitializing( const char *plugin ) +{ + QString s = "Initializing plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + +void PluginManagerWatcher::onPluginStarting( const char *plugin ) +{ + QString s = "Starting plugin "; + s += plugin; + s += "..."; + sp->setText( s ); +} + + + diff --git a/code/studio/src/pm_watcher.h b/code/studio/src/pm_watcher.h index fe2755783..a36bae57b 100644 --- a/code/studio/src/pm_watcher.h +++ b/code/studio/src/pm_watcher.h @@ -1,33 +1,33 @@ -// Ryzom Core - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef PM_WATCHER_H -#define PM_WATCHER_H - -#include - -namespace ExtensionSystem -{ - class IPluginManager; -} - -class SplashScreen; -class PluginManager; - +// Ryzom Core - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef PM_WATCHER_H +#define PM_WATCHER_H + +#include + +namespace ExtensionSystem +{ + class IPluginManager; +} + +class SplashScreen; +class PluginManager; + class PluginManagerWatcher : public QObject { Q_OBJECT @@ -56,8 +56,8 @@ private Q_SLOTS: private: SplashScreen *sp; ExtensionSystem::IPluginManager *pm; -}; - - -#endif - +}; + + +#endif + From bfa4cec7e6a6117c0448b6e7fd171f1ab77c29d2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 16:56:10 +0200 Subject: [PATCH 036/220] Instead of drawing the progressbar on the splash image, draw it below it. Also move the status text closer to the progress bar. --- code/studio/src/splash_screen.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 303459ff0..984c8d62c 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -45,9 +45,11 @@ void SplashScreen::setPixmap( const QPixmap &pixmap ) pbWidth = this->pixmap().width(); if( this->pixmap().height() > 0 ) - pbTop = this->pixmap().height() - pbHeight; + pbTop = this->pixmap().height(); - textY = pbTop - pbHeight; + textY = pbTop - pbHeight / 2; + + resize( pbWidth, pbTop + pbHeight ); } void SplashScreen::setText( const QString &text ) From 6938777725d915cbed7f95b6fcac35077e28420e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 17:23:06 +0200 Subject: [PATCH 037/220] Progress bar will now actually show progress. --- .../src/extension_system/iplugin_manager.h | 6 +++ .../src/extension_system/plugin_manager.cpp | 7 ++++ code/studio/src/pm_watcher.cpp | 42 +++++++++++++++++++ code/studio/src/pm_watcher.h | 9 ++++ code/studio/src/splash_screen.cpp | 7 ++++ code/studio/src/splash_screen.h | 1 + 6 files changed, 72 insertions(+) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index 1c8eea5d4..15fa4a336 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -134,9 +134,15 @@ Q_SIGNALS: /// Signal that the list of available plugins has changed. void pluginsChanged(); + void pluginCount( int count ); + void pluginLoading( const char *plugin ); void pluginInitializing( const char *plugin ); void pluginStarting( const char *plugin ); + + void pluginsLoaded(); + void pluginsInitialized(); + void pluginsStarted(); }; }; // namespace ExtensionSystem diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 4dcb40d31..265268896 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -92,17 +92,24 @@ void PluginManager::loadPlugins() setPluginState(spec, State::Resolved); QList queue = loadQueue(); + Q_EMIT pluginCount( queue.count() ); Q_FOREACH (PluginSpec *spec, queue) setPluginState(spec, State::Loaded); + + Q_EMIT pluginsLoaded(); Q_FOREACH (PluginSpec *spec, queue) setPluginState(spec, State::Initialized); + + Q_EMIT pluginsInitialized(); QListIterator it(queue); it.toBack(); while (it.hasPrevious()) setPluginState(it.previous(), State::Running); + + Q_EMIT pluginsStarted(); Q_EMIT pluginsChanged(); } diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp index 1a029a1a3..85c6d267b 100644 --- a/code/studio/src/pm_watcher.cpp +++ b/code/studio/src/pm_watcher.cpp @@ -19,11 +19,25 @@ #include "extension_system\iplugin_manager.h" #include "splash_screen.h" +namespace +{ + enum Progress + { + PLUGINS_LOADED = 10, + PLUGINS_INITIALIZED = 90, + PLUGINS_STARTED = 100 + }; +} + void PluginManagerWatcher::connect() { QObject::connect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); QObject::connect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); QObject::connect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); + QObject::connect( pm, SIGNAL( pluginsLoaded() ), this, SLOT( onPluginsLoaded() ) ); + QObject::connect( pm, SIGNAL( pluginsInitialized() ), this, SLOT( onPluginsInitialized() ) ); + QObject::connect( pm, SIGNAL( pluginsStarted() ), this, SLOT( onPluginsStarted() ) ); + QObject::connect( pm, SIGNAL( pluginCount( int ) ), this, SLOT( onPluginCount( int ) ) ); } void PluginManagerWatcher::disconnect() @@ -31,6 +45,10 @@ void PluginManagerWatcher::disconnect() QObject::disconnect( pm, SIGNAL( pluginLoading( const char * ) ), this, SLOT( onPluginLoading( const char * ) ) ); QObject::disconnect( pm, SIGNAL( pluginInitializing( const char * ) ), this, SLOT( onPluginInitializing( const char * ) ) ); QObject::disconnect( pm, SIGNAL( pluginStarting( const char * ) ), this, SLOT( onPluginStarting( const char * ) ) ); + QObject::disconnect( pm, SIGNAL( pluginsLoaded() ), this, SLOT( onPluginsLoaded() ) ); + QObject::disconnect( pm, SIGNAL( pluginsInitialized() ), this, SLOT( onPluginsInitialized() ) ); + QObject::disconnect( pm, SIGNAL( pluginsStarted() ), this, SLOT( onPluginsStarted() ) ); + QObject::disconnect( pm, SIGNAL( pluginCount( int ) ), this, SLOT( onPluginCount( int ) ) ); } void PluginManagerWatcher::onPluginLoading( const char *plugin ) @@ -39,6 +57,8 @@ void PluginManagerWatcher::onPluginLoading( const char *plugin ) s += plugin; s += "..."; sp->setText( s ); + + sp->advanceProgress( PLUGINS_LOADED / pluginCount ); } void PluginManagerWatcher::onPluginInitializing( const char *plugin ) @@ -47,6 +67,8 @@ void PluginManagerWatcher::onPluginInitializing( const char *plugin ) s += plugin; s += "..."; sp->setText( s ); + + sp->advanceProgress( ( PLUGINS_INITIALIZED - PLUGINS_LOADED ) / pluginCount ); } void PluginManagerWatcher::onPluginStarting( const char *plugin ) @@ -55,7 +77,27 @@ void PluginManagerWatcher::onPluginStarting( const char *plugin ) s += plugin; s += "..."; sp->setText( s ); + + sp->advanceProgress( ( PLUGINS_STARTED - PLUGINS_INITIALIZED ) / pluginCount ); } +void PluginManagerWatcher::onPluginsLoaded() +{ + sp->setProgress( PLUGINS_LOADED ); +} +void PluginManagerWatcher::onPluginsInitialized() +{ + sp->setProgress( PLUGINS_INITIALIZED ); +} + +void PluginManagerWatcher::onPluginsStarted() +{ + sp->setProgress( PLUGINS_STARTED ); +} + +void PluginManagerWatcher::onPluginCount( int count ) +{ + pluginCount = count; +} \ No newline at end of file diff --git a/code/studio/src/pm_watcher.h b/code/studio/src/pm_watcher.h index a36bae57b..e37e81401 100644 --- a/code/studio/src/pm_watcher.h +++ b/code/studio/src/pm_watcher.h @@ -32,9 +32,11 @@ class PluginManagerWatcher : public QObject { Q_OBJECT public: + PluginManagerWatcher(){ sp = NULL; pm = NULL; + pluginCount = 0; } ~PluginManagerWatcher(){ @@ -53,9 +55,16 @@ private Q_SLOTS: void onPluginInitializing( const char *plugin ); void onPluginStarting( const char *plugin ); + void onPluginsLoaded(); + void onPluginsInitialized(); + void onPluginsStarted(); + + void onPluginCount( int count ); + private: SplashScreen *sp; ExtensionSystem::IPluginManager *pm; + int pluginCount; }; diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 984c8d62c..2bd67c11c 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -71,6 +71,13 @@ void SplashScreen::setProgress( int percent ) QCoreApplication::instance()->processEvents(); } +void SplashScreen::advanceProgress( int percent ) +{ + progress += percent; + repaint(); + QCoreApplication::instance()->processEvents(); +} + void SplashScreen::drawContents( QPainter *painter ) { QSplashScreen::drawContents( painter ); diff --git a/code/studio/src/splash_screen.h b/code/studio/src/splash_screen.h index 3fa2458cb..ec6cd3da8 100644 --- a/code/studio/src/splash_screen.h +++ b/code/studio/src/splash_screen.h @@ -34,6 +34,7 @@ public: void clearText(); void setTextXY( int x, int y ){ textX = x; textY = y; } void setProgress( int percent ); + void advanceProgress( int percent ); void setProgressBarEnabled( bool b ){ progressBarEnabled = b; } void setProgressBarRect( int left, int top, int width, int height ){} From 18cc789f48cac3eabdde0a54c51380fc138096a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 18:10:43 +0200 Subject: [PATCH 038/220] Progressbar should look nicer on the splash screen now. --- code/studio/src/images/studio_splash.png | Bin 137855 -> 154305 bytes code/studio/src/splash_screen.cpp | 10 ++++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/code/studio/src/images/studio_splash.png b/code/studio/src/images/studio_splash.png index 1ec9d823ff81a9644135871393fec9f49dab11ed..06f0504b9f7d5d426fddbf0b99541c2b48a1ffd0 100644 GIT binary patch literal 154305 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

SGVAI60S=cV9nu|~RkIu=! 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

HO4XGE| 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 literal 137855 zcmXt<2RPMl*vFALwjzmRj~ts$lD$LbF|t?4I#%|~E;Dqb?ajHs0V-&g;=)pTCo0gz_D@gG)vk+xcs$d||NYoW^WtLZh99TyzZY&! z!58BdPSVX6w*4RQF}Z>X>@i$jd@pZ3q)76qWMVxpHF2rEnVDHuX@z~3jp5;0fFLb< z>&F>~!?XFr&bSNvW}^k?7Z5i;zjgy&_qH5td-whe?o^GkWHEJ^P0?h=m~HodmCMiF zlil6j^V^AtpnrcX#d5#dK2o15PRS~@X`Bm?l7^B$R(BN1j*tsMEzHl?5yDE4m=>fa zXL52f)%c-pMJNA-~y4+!X%*n%R?oXFa$G?5MzUa9zMtcsqWsUuI z70prO99>61EVFDo7P{NpxoKkBYtlz;mQGF4W9#nP)LZR&W45N~T#Yh^KcxF7C;AZW z3f+IUZ6*#`zc0F1MZvF5AH5ed7}O&Wu618lwF2u`g2>b;v!wm2-es1r#%W3G+>sr> znvm^`}vDQ|d`Km3brn1 zFCl2wHWbTg?>#=}Z9^gRlPi`k?sJ)DzJ{h|3;__fb zoAUhp{HI%vASv!$mI3!RxH^?gduL}8FSaZ{Xk_D1?rnB<_L@r(7jdWsoDRG%zb;1n zKKC{gUYf=^-e}g*2I0)uRngT0T2Tpc@mnuTr(iN>)%p>Xc^fkh&0Nvksl?3OB}akM zq^MzQ))HQtm^KsVp<9x4aWdU%oQ)>@F@vmSRQP=!V%2D@MaEC5_|>xjGw#&$tL~KV zf}|)xuMhXrZ3Jm!hh9#>pO+x073JQlaq85f@5e;oF?wOJ$I}$gOTJqRtB_?>-H%+^ z@42aY&znDrhJ-S^n!bP}j&C3_{OP0G)Q{=nf_lukr~{VvkNt9Xtc5G| zt5k|5($2c`N7v)KF-6&&;g>Iq(haJM9jIV-_7@>z|*J3;uk4(s8TK zt0VX4pjEvxveG^a+wQ=4$u?KeeZSQHr?s$~skbN;e1;ed#

Ipmp4ZBtlLkd(2uG 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 OKY3{tsd5SU=l=r;@S|k_ diff --git a/code/studio/src/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 2bd67c11c..252472e8d 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -27,7 +27,7 @@ QSplashScreen() progress = 0; textX = 5; textY = 20; - pbLeft = 0; + pbLeft = 2; pbTop = 0; pbWidth = 100; pbHeight = 20; @@ -42,14 +42,12 @@ void SplashScreen::setPixmap( const QPixmap &pixmap ) QSplashScreen::setPixmap( pixmap ); if( this->pixmap().width() > 0 ) - pbWidth = this->pixmap().width(); + pbWidth = this->pixmap().width() - 4; if( this->pixmap().height() > 0 ) - pbTop = this->pixmap().height(); + pbTop = this->pixmap().height() - pbHeight - 2; textY = pbTop - pbHeight / 2; - - resize( pbWidth, pbTop + pbHeight ); } void SplashScreen::setText( const QString &text ) @@ -92,7 +90,7 @@ void SplashScreen::drawContents( QPainter *painter ) pbStyle.maximum = 100; pbStyle.progress = progress; pbStyle.invertedAppearance = false; - pbStyle.rect = QRect( 0, pbTop, pbWidth, pbHeight ); + pbStyle.rect = QRect( pbLeft, pbTop, pbWidth, pbHeight ); style()->drawControl( QStyle::CE_ProgressBar, &pbStyle, painter, this ); } From 6da11abef241daf22ca8cedca6d8c5288cb8eb30 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 20:04:15 +0200 Subject: [PATCH 039/220] Updated qrc location. --- code/studio/src/plugins/core/plugin_view_dialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/core/plugin_view_dialog.ui b/code/studio/src/plugins/core/plugin_view_dialog.ui index 9d7d395be..53ee0efb8 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.ui +++ b/code/studio/src/plugins/core/plugin_view_dialog.ui @@ -112,7 +112,7 @@ - + From 3eb5115a0bf5ed9fef65d8d28ac9801a453e7529 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 21:07:46 +0200 Subject: [PATCH 040/220] GUI for plugin loading / unloading in the plugin dialog. --- .../src/plugins/core/plugin_view_dialog.cpp | 38 +++++++++++++++++ .../src/plugins/core/plugin_view_dialog.h | 4 ++ .../src/plugins/core/plugin_view_dialog.ui | 41 +++++++++++++------ 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index 175902d39..316bb0097 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include // Project includes #include "../../extension_system/iplugin_spec.h" @@ -43,6 +45,10 @@ PluginView::PluginView(ExtensionSystem::IPluginManager *pluginManager, QWidget * connect(m_pluginManager, SIGNAL(pluginsChanged()), this, SLOT(updateList())); connect(this, SIGNAL(accepted()), this, SLOT(updateSettings())); + connect( m_ui.pluginTreeWidget, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ), this, SLOT( onItemClicked() ) ); + connect( m_ui.unloadButton, SIGNAL( clicked( bool ) ), this, SLOT( onUnloadClicked() ) ); + connect( m_ui.loadButton, SIGNAL( clicked( bool ) ), this, SLOT( onLoadClicked() ) ); + // WhiteList is list of plugins which can not disable. m_whiteList << Constants::OVQT_CORE_PLUGIN; updateList(); @@ -105,4 +111,36 @@ void PluginView::updateSettings() } } +void PluginView::onItemClicked() +{ + m_ui.unloadButton->setEnabled( true ); +} + +void PluginView::onUnloadClicked() +{ + QTreeWidgetItem *item = m_ui.pluginTreeWidget->currentItem(); + if( item == NULL ) + { + QMessageBox::warning( this, + tr( "Plugin unload" ), + tr( "No plugin selected!" ) ); + return; + } + + +} + +void PluginView::onLoadClicked() +{ + QString f = QFileDialog::getOpenFileName( this, + tr( "Loading a plugin" ), + ".", + "Plugin specifications ( *.xml )" ); + + if( f.isEmpty() ) + { + return; + } +} + } /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.h b/code/studio/src/plugins/core/plugin_view_dialog.h index aae16749d..e11449fdd 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.h +++ b/code/studio/src/plugins/core/plugin_view_dialog.h @@ -44,6 +44,10 @@ private Q_SLOTS: void updateList(); void updateSettings(); + void onItemClicked(); + void onUnloadClicked(); + void onLoadClicked(); + private: const int m_checkStateColumn; diff --git a/code/studio/src/plugins/core/plugin_view_dialog.ui b/code/studio/src/plugins/core/plugin_view_dialog.ui index 53ee0efb8..45c4695e8 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.ui +++ b/code/studio/src/plugins/core/plugin_view_dialog.ui @@ -17,7 +17,7 @@ true - + true @@ -79,7 +79,34 @@ + + + + false + + + All objects list + + + + + + false + + + Unload plugin + + + + + + + Load plugin + + + + Qt::Horizontal @@ -92,23 +119,13 @@ - + Close - - - - false - - - All objects list - - - From c3084d5661c83b65e2bb539e80bd986ccfdc11a1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:17:24 +0200 Subject: [PATCH 041/220] Implemented plugin unload. --- .../src/extension_system/iplugin_manager.h | 3 + .../src/extension_system/plugin_manager.cpp | 62 +++++++++++++++++++ .../src/extension_system/plugin_manager.h | 4 ++ .../src/plugins/core/plugin_view_dialog.cpp | 17 ++++- .../src/plugins/core/plugin_view_dialog.h | 1 + 5 files changed, 86 insertions(+), 1 deletion(-) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index 15fa4a336..efbf5ee2f 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -55,6 +55,9 @@ public: virtual void setPluginPaths(const QStringList &paths) = 0; virtual QList plugins() const = 0; + virtual bool loadPlugin( const char *plugin ) = 0; + virtual bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ) = 0; + // Settings virtual void setSettings(QSettings *settings) = 0; virtual QSettings *settings() const = 0; diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 265268896..c9f40e7bd 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -114,6 +114,68 @@ void PluginManager::loadPlugins() Q_EMIT pluginsChanged(); } +bool PluginManager::loadPlugin( const char *plugin ) +{ + return true; +} + +bool PluginManager::unloadPlugin( ExtensionSystem::IPluginSpec *plugin ) +{ + ExtensionSystem::PluginSpec *spec = static_cast< ExtensionSystem::PluginSpec* >( plugin ); + + // Let's see if anything depends on this one + QListIterator< ExtensionSystem::PluginSpec* > itr( m_pluginSpecs ); + while( itr.hasNext() ) + { + ExtensionSystem::PluginSpec *sp = itr.next(); + QList< ExtensionSystem::PluginSpec* > l = sp->dependencySpecs(); + if( l.contains( spec ) ) + return false; + } + + // Stop, delete then remove plugin + spec->stop(); + spec->kill(); + removePlugin( plugin ); + + return true; +} + +void PluginManager::removePlugin( ExtensionSystem::IPluginSpec *plugin ) +{ + QList< ExtensionSystem::IPluginSpec* >::iterator itr1; + QList< ExtensionSystem::PluginSpec* >::iterator itr2; + + QList< ExtensionSystem::IPluginSpec* >::iterator i1 = m_ipluginSpecs.begin(); + while( i1 != m_ipluginSpecs.end() ) + { + if( *i1 == plugin ) + { + itr1 = i1; + break; + } + i1++; + } + + QList< ExtensionSystem::PluginSpec* >::iterator i2 = m_pluginSpecs.begin(); + while( i2 != m_pluginSpecs.end() ) + { + if( *i2 == static_cast< ExtensionSystem::PluginSpec* >( plugin ) ) + { + itr2 = i2; + break; + } + i2++; + } + + m_ipluginSpecs.erase( itr1 ); + m_pluginSpecs.erase( itr2 ); + delete plugin; + + Q_EMIT pluginsChanged(); + +} + QStringList PluginManager::getPluginPaths() const { return m_pluginPaths; diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 9ab1ae135..10130ffc4 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,6 +51,10 @@ public: virtual QList plugins() const; QList loadQueue(); + bool loadPlugin( const char *plugin ); + bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); + void removePlugin( ExtensionSystem::IPluginSpec *plugin ); + // Settings virtual void setSettings(QSettings *settings); virtual QSettings *settings() const; diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index 316bb0097..bf62d4632 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -65,6 +65,7 @@ void PluginView::updateList() static QIcon notLoadedIcon = QApplication::style()->standardIcon(QStyle::SP_DialogResetButton); m_specToItem.clear(); + m_itemToSpec.clear(); QList items; Q_FOREACH (ExtensionSystem::IPluginSpec *spec, m_pluginManager->plugins()) @@ -87,6 +88,7 @@ void PluginView::updateList() items.append(item); m_specToItem.insert(spec, item); + m_itemToSpec.insert(item, spec); } m_ui.pluginTreeWidget->clear(); @@ -127,7 +129,18 @@ void PluginView::onUnloadClicked() return; } - + QMap< QTreeWidgetItem*, ExtensionSystem::IPluginSpec* >::const_iterator itr + = m_itemToSpec.find( item ); + if( itr == m_itemToSpec.end() ) + return; + + bool success = m_pluginManager->unloadPlugin( itr.value() ); + if( !success ) + { + QMessageBox::warning( this, + tr( "Plugin unload" ), + tr( "Failed to unload plugin." ) ); + } } void PluginView::onLoadClicked() @@ -141,6 +154,8 @@ void PluginView::onLoadClicked() { return; } + + this->m_pluginManager->loadPlugin( f.toAscii().data() ); } } /* namespace Core */ \ No newline at end of file diff --git a/code/studio/src/plugins/core/plugin_view_dialog.h b/code/studio/src/plugins/core/plugin_view_dialog.h index e11449fdd..e7c1123c1 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.h +++ b/code/studio/src/plugins/core/plugin_view_dialog.h @@ -52,6 +52,7 @@ private: const int m_checkStateColumn; QMap m_specToItem; + QMap m_itemToSpec; QStringList m_whiteList; ExtensionSystem::IPluginManager *m_pluginManager; Ui::PluginView m_ui; From 356973a1bd2389eec058872f7a0b79e66b6fa8ec Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:30:09 +0200 Subject: [PATCH 042/220] Remove GUI Editor menu when unloading the plugin. --- .../src/plugins/gui_editor/gui_editor_window.cpp | 11 +++++++++++ .../studio/src/plugins/gui_editor/gui_editor_window.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 24ecc5cfc..e48a37ba6 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -55,6 +55,7 @@ namespace GUIEditor GUIEditorWindow::GUIEditorWindow(QWidget *parent) : QMainWindow(parent) { + menu = NULL; m_ui.setupUi(this); messageProcessor = new CEditorMessageProcessor; m_undoStack = new QUndoStack(this); @@ -112,6 +113,8 @@ namespace GUIEditor { writeSettings(); + removeMenus(); + delete messageProcessor; messageProcessor = NULL; @@ -382,8 +385,16 @@ namespace GUIEditor a = new QAction( "Add Widget", this ); connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); + + menu = m; } } + + void GUIEditorWindow::removeMenus() + { + delete menu; + menu = NULL; + } void GUIEditorWindow::readSettings() { diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index e1a8b8b2d..1362e4671 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -26,6 +26,8 @@ class QtTreePropertyBrowser; +class QMenu; + namespace GUIEditor { @@ -66,6 +68,7 @@ private Q_SLOTS: private: void createMenus(); + void removeMenus(); void readSettings(); @@ -88,6 +91,8 @@ private: CPropBrowserCtrl browserCtrl; QString currentProject; QString currentProjectFile; + + QMenu *menu; }; } From 8111d9b9a56fc6dd8c13f0d4a7464c1fe2cccd0f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:45:13 +0200 Subject: [PATCH 043/220] Remove translation manager menu when unloading the plugin. --- .../translation_manager_main_window.cpp | 37 ++++++++++++++----- .../translation_manager_main_window.h | 6 ++- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index d80ffe3f5..244a5a92c 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -47,6 +47,7 @@ namespace TranslationManager CMainWindow::CMainWindow(QWidget *parent) : QMainWindow(parent) { + menu = NULL; _ui.setupUi(this); _ui.mdiArea->closeAllSubWindows(); @@ -59,10 +60,37 @@ CMainWindow::CMainWindow(QWidget *parent) connect(Core::ICore::instance(), SIGNAL(changeSettings()), this, SLOT(readSettings())); readSettings(); createToolbar(); + createMenus(); m_undoStack = new QUndoStack(this); } +CMainWindow::~CMainWindow() +{ + removeMenus(); +} + +void CMainWindow::removeMenus() +{ + delete menu; + menu = NULL; +} + +void CMainWindow::createMenus() +{ + // Windows menu + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + QMenu *m = menuManager->menuBar()->addMenu( "Translation Manager" ); + if( m != NULL ) + { + windowMenu = m->addMenu("Window"); + menu = m; + } + + updateWindowsList(); + connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); +} + // Functions that will insert the plugin buttons void CMainWindow::createToolbar() { @@ -126,17 +154,8 @@ void CMainWindow::createToolbar() mergeSingleFileAct->setStatusTip(tr("Merge worksheet file from local or remote directory")); connect(mergeSingleFileAct, SIGNAL(triggered()), this, SLOT(mergeSingleFile())); - // Windows menu Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - QMenu *m = menuManager->menuBar()->addMenu( "Translation Manager" ); - if( m != NULL ) - { - windowMenu = m->addMenu("Window"); - } - - updateWindowsList(); - connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowsList())); // Undo, Redo actions QAction *undoAction = menuManager->action(Core::Constants::UNDO); diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h index c67f282e0..73bccdd8e 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h @@ -58,7 +58,7 @@ class CMainWindow : public QMainWindow public: CMainWindow(QWidget *parent = 0); - virtual ~CMainWindow() {} + ~CMainWindow(); QUndoStack *m_undoStack; public: @@ -96,6 +96,7 @@ private: void updateToolbar(QMdiSubWindow *window); bool verifySettings(); void readSettings(); + void removeMenus(); void createMenus(); void createToolbar(); void initializeSettings(bool georges); @@ -105,6 +106,9 @@ private: CEditorWorksheet *getEditorByWorksheetType(const QString &type); bool isWorksheetEditor(QString filename); bool isPhraseEditor(QString filename); + + + QMenu *menu; }; class CCoreListener : public Core::ICoreListener From 4096166e6643f9b4a1169d3dad27f84484c7fa12 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:56:40 +0200 Subject: [PATCH 044/220] Remove sheet builder action when unloading the plugin. --- .../ovqt_sheet_builder/ovqt_sheet_builder.cpp | 12 ++++++++++++ .../plugins/ovqt_sheet_builder/ovqt_sheet_builder.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp index 4fd7dfb11..8ea90fdc5 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp @@ -35,6 +35,18 @@ using namespace Plugin; +SheetBuilderPlugin::SheetBuilderPlugin() +{ +} + +SheetBuilderPlugin::~SheetBuilderPlugin() +{ + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + QAction *a = menuManager->action( "SheetBuilder" ); + menuManager->unregisterAction( "SheetBuilder" ); + delete a; +} + bool SheetBuilderPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) { Q_UNUSED(errorString); diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h index 504d0914d..21e2855c1 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.h @@ -36,6 +36,8 @@ class SheetBuilderPlugin : public QObject, public ExtensionSystem::IPlugin Q_OBJECT Q_INTERFACES(ExtensionSystem::IPlugin) public: + SheetBuilderPlugin(); + ~SheetBuilderPlugin(); bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); void extensionsInitialized(); void setNelContext(NLMISC::INelContext *nelContext); From 892678952f2d60466d162438bf7c0a1ca72a83e9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:27:03 +0200 Subject: [PATCH 045/220] Remove display sheet id action when unloading the plugin. --- .../plugins/disp_sheet_id/disp_sheet_id_plugin.cpp | 12 ++++++++++++ .../src/plugins/disp_sheet_id/disp_sheet_id_plugin.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp index 62d2f0430..77e254081 100644 --- a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp +++ b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp @@ -34,6 +34,18 @@ using namespace SheetIdViewPlugin; +DispSheetIdPlugin::DispSheetIdPlugin() +{ +} + +DispSheetIdPlugin::~DispSheetIdPlugin() +{ + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + QAction *a = menuManager->action( "SheetIdView" ); + menuManager->unregisterAction( "SheetIdView" ); + delete a; +} + bool DispSheetIdPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) { Q_UNUSED(errorString); diff --git a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h index 8eaf3ead9..7506b84cc 100644 --- a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h +++ b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.h @@ -37,6 +37,9 @@ class DispSheetIdPlugin : public QObject, public ExtensionSystem::IPlugin Q_INTERFACES(ExtensionSystem::IPlugin) public: + DispSheetIdPlugin(); + ~DispSheetIdPlugin(); + bool initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString); void extensionsInitialized(); void setNelContext(NLMISC::INelContext *nelContext); From 686e1f20131b95a0fa9e1ace2a359dd375c3d02a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:28:19 +0200 Subject: [PATCH 046/220] Line endings... --- .../src/plugins/tile_editor/tile_editor_main_window.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index ae3520465..0effbe087 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -25,8 +25,8 @@ #include #include -namespace Ui { - class TileEditorMainWindow; +namespace Ui { + class TileEditorMainWindow; } class TileModel; @@ -37,7 +37,7 @@ class TileEditorMainWindow : public QMainWindow Q_OBJECT public: - explicit TileEditorMainWindow(QWidget *parent = 0); + explicit TileEditorMainWindow(QWidget *parent = 0); ~TileEditorMainWindow(); QUndoStack *getUndoStack() { return m_undoStack; } From bbfd0e15cbda7b408e54df7a0d52f7804fa4b2d3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:39:58 +0200 Subject: [PATCH 047/220] Remove Object Viewer menus when unloading the plugin. --- code/studio/src/plugins/object_viewer/main_window.cpp | 11 +++++++++++ code/studio/src/plugins/object_viewer/main_window.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index 91f832ac0..864896ca1 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -71,6 +71,7 @@ CMainWindow::CMainWindow(QWidget *parent) _lastDir("."), _mouseMode(NL3D::U3dMouseListener::edit3d) { + menu = NULL; nldebug("CMainWindow::CMainWindow:"); setObjectName("CMainWindow"); @@ -134,6 +135,8 @@ CMainWindow::~CMainWindow() settings->endGroup(); settings->sync(); + removeMenus(); + delete _AnimationDialog; delete _AnimationSetDialog; delete _SlotManagerDialog; @@ -323,6 +326,14 @@ void CMainWindow::createMenus() connect(_ParticleControlDialog->toggleViewAction(), SIGNAL(triggered(bool)), _ParticleWorkspaceDialog->_PropertyDialog, SLOT(setVisible(bool))); + menu = ovMenu; + +} + +void CMainWindow::removeMenus() +{ + delete menu; + menu = NULL; } void CMainWindow::createToolBars() diff --git a/code/studio/src/plugins/object_viewer/main_window.h b/code/studio/src/plugins/object_viewer/main_window.h index 5a392c191..dff4d9b4b 100644 --- a/code/studio/src/plugins/object_viewer/main_window.h +++ b/code/studio/src/plugins/object_viewer/main_window.h @@ -95,6 +95,7 @@ protected: private: void createActions(); void createMenus(); + void removeMenus(); void createToolBars(); void createDialogs(); @@ -144,6 +145,8 @@ private: uint _numTri; float _texMem; sint _mouseMode; + + QMenu *menu; };/* class CMainWindow */ } /* namespace NLQT */ From 4a381e857de6d1820ba63484130ae2b92f049e27 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 21:56:31 +0200 Subject: [PATCH 048/220] Don't crash when removing the plugin of the first tab. --- code/studio/src/plugins/core/context_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/core/context_manager.cpp b/code/studio/src/plugins/core/context_manager.cpp index 8355b5cb8..d81f62cf1 100644 --- a/code/studio/src/plugins/core/context_manager.cpp +++ b/code/studio/src/plugins/core/context_manager.cpp @@ -135,8 +135,8 @@ void ContextManager::removeContextObject(IContext *context) const int index = indexOf(context->id()); QWidget *widget = d->m_tabWidget->widget(index); - d->m_tabWidget->removeTab(index); d->m_contexts.remove(index); + d->m_tabWidget->removeTab(index); delete widget; } From b7a86fd99821b86ffa92a20e47dac2ed10f78ab3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 01:14:13 +0200 Subject: [PATCH 049/220] Plugin loading, with issues.. --- .../src/extension_system/plugin_manager.cpp | 60 +++++++++++++++++-- .../src/extension_system/plugin_manager.h | 1 + .../src/plugins/core/context_manager.cpp | 10 +--- .../studio/src/plugins/core/context_manager.h | 3 +- .../src/plugins/core/plugin_view_dialog.cpp | 15 ++++- 5 files changed, 72 insertions(+), 17 deletions(-) diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index c9f40e7bd..508a4b81b 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -114,8 +114,62 @@ void PluginManager::loadPlugins() Q_EMIT pluginsChanged(); } +bool PluginManager::loadPluginSpec( const char *plugin ) +{ + nlinfo( "Loading plugin spec %s", plugin ); + + PluginSpec *spec = new PluginSpec; + spec->m_pluginManager = this; + if( !spec->setSpecFileName( plugin ) ) + { + nlinfo( "Error loading plugin spec %s", plugin ); + return false; + } + + m_pluginSpecs.append( spec ); + m_ipluginSpecs.append( spec ); + + return true; +} + bool PluginManager::loadPlugin( const char *plugin ) { + if( !loadPluginSpec( plugin ) ) + return false; + + ExtensionSystem::PluginSpec *spec = m_pluginSpecs.last(); + + if( !spec->resolveDependencies( m_pluginSpecs ) ) + { + nlinfo( "Error resolving dependencies for plugin spec %s", plugin ); + return false; + } + + if( !spec->loadLibrary() ) + { + nlinfo( "Error loading plugin %s", spec->fileName().toUtf8().data() ); + return false; + } + + if( !spec->initializePlugin() ) + { + nlinfo( "Error initializing plugin %s", spec->fileName().toUtf8().data() ); + spec->kill(); + return false; + } + + if( !spec->initializeExtensions() ) + { + nlinfo( "Error starting plugin %s", spec->fileName().toUtf8().data() ); + spec->stop(); + spec->kill(); + return false; + } + + nlinfo( "Loaded plugin %s ( %s )", spec->name().data(), spec->fileName().toUtf8().data() ); + + Q_EMIT pluginsChanged(); + return true; } @@ -262,11 +316,7 @@ void PluginManager::readPluginPaths() Q_FOREACH (const QString &pluginFile, pluginsList) { - PluginSpec *spec = new PluginSpec; - spec->m_pluginManager = this; - spec->setSpecFileName(pluginFile); - m_pluginSpecs.append(spec); - m_ipluginSpecs.append(spec); + loadPluginSpec( pluginFile.toUtf8().data() ); } Q_EMIT pluginsChanged(); diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 10130ffc4..9b0d7a0dc 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,6 +51,7 @@ public: virtual QList plugins() const; QList loadQueue(); + bool loadPluginSpec( const char *plugin ); bool loadPlugin( const char *plugin ); bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); void removePlugin( ExtensionSystem::IPluginSpec *plugin ); diff --git a/code/studio/src/plugins/core/context_manager.cpp b/code/studio/src/plugins/core/context_manager.cpp index d81f62cf1..3b02b411c 100644 --- a/code/studio/src/plugins/core/context_manager.cpp +++ b/code/studio/src/plugins/core/context_manager.cpp @@ -36,13 +36,11 @@ struct ContextManagerPrivate Core::MainWindow *m_mainWindow; QTabWidget *m_tabWidget; QVector m_contexts; - int m_oldCurrent; }; ContextManagerPrivate::ContextManagerPrivate(Core::MainWindow *mainWindow, QTabWidget *tabWidget) : m_mainWindow(mainWindow), - m_tabWidget(tabWidget), - m_oldCurrent(-1) + m_tabWidget(tabWidget) { } @@ -145,11 +143,7 @@ void ContextManager::currentTabChanged(int index) if (index >= 0) { IContext *context = d->m_contexts.at(index); - IContext *oldContext = 0; - if (d->m_oldCurrent >= 0) - oldContext = d->m_contexts.at(d->m_oldCurrent); - d->m_oldCurrent = index; - Q_EMIT currentContextChanged(context, oldContext); + Q_EMIT currentContextChanged(context); } } diff --git a/code/studio/src/plugins/core/context_manager.h b/code/studio/src/plugins/core/context_manager.h index 8151648e7..9b0a62c7e 100644 --- a/code/studio/src/plugins/core/context_manager.h +++ b/code/studio/src/plugins/core/context_manager.h @@ -51,8 +51,7 @@ public: void unregisterUndoStack(QUndoStack *stack); Q_SIGNALS: - // the default argument '=0' is important for connects without the oldContext argument. - void currentContextChanged(Core::IContext *context, Core::IContext *oldContext = 0); + void currentContextChanged(Core::IContext *context); public Q_SLOTS: void activateContext(const QString &id); diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index bf62d4632..c47a1c75d 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -155,7 +155,18 @@ void PluginView::onLoadClicked() return; } - this->m_pluginManager->loadPlugin( f.toAscii().data() ); + QApplication::setOverrideCursor( Qt::WaitCursor ); + bool success = m_pluginManager->loadPlugin( f.toAscii().data() ); + QApplication::setOverrideCursor( Qt::ArrowCursor ); + + if( !success ) + { + QMessageBox::warning( this, + tr( "Loading plugin" ), + tr( "Error loading plugin!" ) ); + } } -} /* namespace Core */ \ No newline at end of file + +} /* namespace Core */ + From 4f09537f3181af0785fc838a4bfcf2d1b073d046 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:40:06 +0200 Subject: [PATCH 050/220] Destroy context when unloading plugins. --- code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp | 3 +++ code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp | 3 +++ .../src/plugins/georges_editor/georges_editor_plugin.cpp | 3 +++ code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp | 3 +++ .../src/plugins/landscape_editor/landscape_editor_plugin.cpp | 3 +++ code/studio/src/plugins/log/log_plugin.cpp | 3 +++ .../src/plugins/mission_compiler/mission_compiler_plugin.cpp | 3 +++ code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp | 3 +++ .../src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp | 3 +++ code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp | 3 +++ .../plugins/translation_manager/translation_manager_plugin.cpp | 3 +++ code/studio/src/plugins/world_editor/world_editor_plugin.cpp | 3 +++ 12 files changed, 36 insertions(+) diff --git a/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp index e4bf7f594..509dd2997 100644 --- a/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp +++ b/code/studio/src/plugins/bnp_manager/bnp_manager_plugin.cpp @@ -44,6 +44,9 @@ namespace BNPManager } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool BNPManagerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp index 77e254081..46a8ee6bd 100644 --- a/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp +++ b/code/studio/src/plugins/disp_sheet_id/disp_sheet_id_plugin.cpp @@ -44,6 +44,9 @@ DispSheetIdPlugin::~DispSheetIdPlugin() QAction *a = menuManager->action( "SheetIdView" ); menuManager->unregisterAction( "SheetIdView" ); delete a; + + delete m_LibContext; + m_LibContext = NULL; } bool DispSheetIdPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp b/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp index 075ac41b2..f1b419e4e 100644 --- a/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp +++ b/code/studio/src/plugins/georges_editor/georges_editor_plugin.cpp @@ -39,6 +39,9 @@ GeorgesEditorPlugin::~GeorgesEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool GeorgesEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp b/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp index d0fea4df3..d5f2403f1 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_plugin.cpp @@ -37,6 +37,9 @@ namespace GUIEditor qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool GUIEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp index 73a6f5b25..f97aff691 100644 --- a/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp +++ b/code/studio/src/plugins/landscape_editor/landscape_editor_plugin.cpp @@ -39,6 +39,9 @@ LandscapeEditorPlugin::~LandscapeEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool LandscapeEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp index 0f86ab90c..2017ed91a 100644 --- a/code/studio/src/plugins/log/log_plugin.cpp +++ b/code/studio/src/plugins/log/log_plugin.cpp @@ -62,6 +62,9 @@ namespace Plugin NLMISC::AssertLog->removeDisplayer(m_displayer); NLMISC::InfoLog->removeDisplayer(m_displayer); delete m_displayer; + + delete m_libContext; + m_libContext = NULL; } bool CLogPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp index 98b188fd3..46e51f36d 100644 --- a/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp +++ b/code/studio/src/plugins/mission_compiler/mission_compiler_plugin.cpp @@ -30,6 +30,9 @@ MissionCompilerPlugin::~MissionCompilerPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_LibContext; + m_LibContext = NULL; } bool MissionCompilerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp index 34fc0f1b4..dce7ad08f 100644 --- a/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp +++ b/code/studio/src/plugins/object_viewer/object_viewer_plugin.cpp @@ -23,6 +23,9 @@ ObjectViewerPlugin::~ObjectViewerPlugin() qDeleteAll(_autoReleaseObjects); _autoReleaseObjects.clear(); Modules::release(); + + delete _LibContext; + _LibContext = NULL; } bool ObjectViewerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp index 8ea90fdc5..21358ec6f 100644 --- a/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp +++ b/code/studio/src/plugins/ovqt_sheet_builder/ovqt_sheet_builder.cpp @@ -45,6 +45,9 @@ SheetBuilderPlugin::~SheetBuilderPlugin() QAction *a = menuManager->action( "SheetBuilder" ); menuManager->unregisterAction( "SheetBuilder" ); delete a; + + delete m_LibContext; + m_LibContext = NULL; } bool SheetBuilderPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp index ac12766b8..33a617cc1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp @@ -42,6 +42,9 @@ TileEditorPlugin::~TileEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_LibContext; + m_LibContext = NULL; } bool TileEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp b/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp index 20359ccbd..3fafc7510 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_plugin.cpp @@ -48,6 +48,9 @@ TranslationManagerPlugin::~TranslationManagerPlugin() } qDeleteAll(_autoReleaseObjects); _autoReleaseObjects.clear(); + + delete _LibContext; + _LibContext = NULL; } bool TranslationManagerPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) diff --git a/code/studio/src/plugins/world_editor/world_editor_plugin.cpp b/code/studio/src/plugins/world_editor/world_editor_plugin.cpp index 301939cb6..3170bce60 100644 --- a/code/studio/src/plugins/world_editor/world_editor_plugin.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_plugin.cpp @@ -43,6 +43,9 @@ WorldEditorPlugin::~WorldEditorPlugin() } qDeleteAll(m_autoReleaseObjects); m_autoReleaseObjects.clear(); + + delete m_libContext; + m_libContext = NULL; } bool WorldEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) From 6cd1f2c9d3cf002291f94cb3791f9583ca85b410 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:55:45 +0200 Subject: [PATCH 051/220] Move the log trigger menu item into it's own menu, and remove the menu when unloading the plugin. --- code/studio/src/plugins/log/log_plugin.cpp | 8 ++++++-- code/studio/src/plugins/log/log_plugin.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp index 2017ed91a..562b3bb6f 100644 --- a/code/studio/src/plugins/log/log_plugin.cpp +++ b/code/studio/src/plugins/log/log_plugin.cpp @@ -45,6 +45,7 @@ namespace Plugin CLogPlugin::CLogPlugin(QWidget *parent): QDockWidget(parent) { m_ui.setupUi(this); + logMenu = NULL; } CLogPlugin::~CLogPlugin() @@ -63,6 +64,9 @@ namespace Plugin NLMISC::InfoLog->removeDisplayer(m_displayer); delete m_displayer; + delete logMenu; + logMenu = NULL; + delete m_libContext; m_libContext = NULL; } @@ -82,13 +86,13 @@ namespace Plugin Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); - QMenu *viewMenu = menuManager->menu(Core::Constants::M_VIEW); QMainWindow *wnd = Core::ICore::instance()->mainWindow(); wnd->addDockWidget(Qt::RightDockWidgetArea, this); hide(); - viewMenu->addAction(this->toggleViewAction()); + logMenu = menuManager->menuBar()->addMenu( "Log" ); + logMenu->addAction(toggleViewAction()); } void CLogPlugin::setNelContext(NLMISC::INelContext *nelContext) diff --git a/code/studio/src/plugins/log/log_plugin.h b/code/studio/src/plugins/log/log_plugin.h index 2221195a8..9e4f64419 100644 --- a/code/studio/src/plugins/log/log_plugin.h +++ b/code/studio/src/plugins/log/log_plugin.h @@ -85,6 +85,8 @@ namespace Plugin NLQT::CQtDisplayer *m_displayer; + QMenu *logMenu; + }; } // namespace Plugin From 6cc76c96708de87de1327e0e6e081d26533c3ace Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:58:07 +0200 Subject: [PATCH 052/220] Updated qrc location. --- code/studio/src/plugins/log/log_settings_page.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/log/log_settings_page.ui b/code/studio/src/plugins/log/log_settings_page.ui index 92faef8b6..09ead5c17 100644 --- a/code/studio/src/plugins/log/log_settings_page.ui +++ b/code/studio/src/plugins/log/log_settings_page.ui @@ -89,7 +89,7 @@ - + From 844e93ec65661311152701df15b2f2fee0d1967a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 18:01:14 +0200 Subject: [PATCH 053/220] Rename log menu item. --- code/studio/src/plugins/log/log_plugin.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/log/log_plugin.cpp b/code/studio/src/plugins/log/log_plugin.cpp index 562b3bb6f..11da182a0 100644 --- a/code/studio/src/plugins/log/log_plugin.cpp +++ b/code/studio/src/plugins/log/log_plugin.cpp @@ -92,7 +92,9 @@ namespace Plugin hide(); logMenu = menuManager->menuBar()->addMenu( "Log" ); - logMenu->addAction(toggleViewAction()); + QAction *a = toggleViewAction(); + a->setText( tr( "View log" ) ); + logMenu->addAction( a ); } void CLogPlugin::setNelContext(NLMISC::INelContext *nelContext) From 23ad19d0ffc56dedc4fab2ddf097d750435756ca Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 17:28:33 +0200 Subject: [PATCH 054/220] Split Nel3DWidget and NelGUIWidget. --- .../plugins/gui_editor/gui_editor_window.cpp | 2 +- .../src/plugins/gui_editor/nelgui_widget.cpp | 32 ++++++++++++------- .../src/plugins/gui_editor/nelgui_widget.h | 10 ++++-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index e48a37ba6..923db1016 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -66,7 +66,7 @@ namespace GUIEditor addWidgetWidget = new AddWidgetWidget; connect( projectWindow, SIGNAL( projectFilesChanged() ), this, SLOT( onProjectFilesChanged() ) ); viewPort = new NelGUIWidget; - setCentralWidget( viewPort ); + setCentralWidget( viewPort->getViewPort() ); widgetInfoTree = new CWidgetInfoTree; diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index d86d31269..f8e34da3b 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -29,16 +29,19 @@ #include #include "editor_selection_watcher.h" +#include "nel3d_widget.h" + namespace GUIEditor { std::set< std::string > hwCursors; NelGUIWidget::NelGUIWidget( QWidget *parent ) : - Nel3DWidget( parent ) + QWidget( parent ) { timerID = 0; guiLoaded = false; watcher = NULL; + w = new Nel3DWidget(); } NelGUIWidget::~NelGUIWidget() @@ -49,7 +52,9 @@ namespace GUIEditor NLGUI::CViewRenderer::release(); NLMISC::CI18N::setNoResolution( false ); - + + delete w; + w = NULL; } void NelGUIWidget::init() @@ -59,15 +64,15 @@ namespace GUIEditor NLMISC::CPath::remapExtension( "dds", "png", true ); NLMISC::CPath::remapExtension( "png", "tga", true ); - Nel3DWidget::init(); - createTextContext( "Ryzom.ttf" ); + w->init(); + w->createTextContext( "Ryzom.ttf" ); NLGUI::CAHManager::setEditorMode( true ); NLGUI::CLuaManager::setEditorMode( true ); NLGUI::CInterfaceElement::setEditorMode( true ); - NLGUI::CViewRenderer::setDriver( getDriver() ); - NLGUI::CViewRenderer::setTextContext( getTextContext() ); + NLGUI::CViewRenderer::setDriver( w->getDriver() ); + NLGUI::CViewRenderer::setTextContext( w->getTextContext() ); NLGUI::CViewRenderer::hwCursors = &hwCursors; NLGUI::CViewRenderer::getInstance()->init(); @@ -125,21 +130,21 @@ namespace GUIEditor CWidgetManager::getInstance()->reset(); CWidgetManager::getInstance()->getParser()->removeAll(); CViewRenderer::getInstance()->reset(); - clear(); + w->clear(); } void NelGUIWidget::draw() { - getDriver()->clearBuffers( NLMISC::CRGBA::Black ); + w->getDriver()->clearBuffers( NLMISC::CRGBA::Black ); CWidgetManager::getInstance()->checkCoords(); CWidgetManager::getInstance()->drawViews( 0 ); - getDriver()->swapBuffers(); + w->getDriver()->swapBuffers(); } void NelGUIWidget::paintEvent( QPaintEvent *evnt ) { if( !guiLoaded ) - clear(); + w->clear(); } void NelGUIWidget::timerEvent( QTimerEvent *evnt ) @@ -148,7 +153,7 @@ namespace GUIEditor { if( guiLoaded ) { - getDriver()->EventServer.pump(); + w->getDriver()->EventServer.pump(); draw(); } } @@ -165,5 +170,10 @@ namespace GUIEditor if( timerID != 0 ) killTimer( timerID ); } + + QWidget* NelGUIWidget::getViewPort() + { + return w; + } } diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h index 34c510507..a1412257c 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.h +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.h @@ -18,15 +18,16 @@ #ifndef NELGUI_WIDGET_H #define NELGUI_WIDGET_H -#include "nel3d_widget.h" +#include #include "project_files.h" namespace GUIEditor { class CEditorSelectionWatcher; + class Nel3DWidget; /// Qt viewport for the Nel GUI library - class NelGUIWidget : public Nel3DWidget + class NelGUIWidget : public QWidget { Q_OBJECT public: @@ -39,6 +40,8 @@ namespace GUIEditor void reset(); CEditorSelectionWatcher* getWatcher(){ return watcher; } + QWidget* getViewPort(); + Q_SIGNALS: void guiLoadComplete(); @@ -53,6 +56,9 @@ Q_SIGNALS: int timerID; bool guiLoaded; CEditorSelectionWatcher *watcher; + + + Nel3DWidget *w; }; } From 86fe3045cf2cd92b7bee337cbb6445507772743e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:31:50 +0200 Subject: [PATCH 055/220] GUI Editor main window will now send the show/hide events to NelGUIWidget. --- .../src/plugins/gui_editor/gui_editor_window.cpp | 14 ++++++++++++++ .../src/plugins/gui_editor/gui_editor_window.h | 4 ++++ .../src/plugins/gui_editor/nelgui_widget.cpp | 4 ++-- code/studio/src/plugins/gui_editor/nelgui_widget.h | 6 +++--- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 923db1016..1d4050412 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -340,6 +340,20 @@ namespace GUIEditor addWidgetWidget->setupWidgetInfo( widgetInfoTree ); } + + + void GUIEditorWindow::hideEvent( QHideEvent *evnt ) + { + QWidget::hideEvent( evnt ); + viewPort->hide(); + } + + void GUIEditorWindow::showEvent( QShowEvent *evnt ) + { + QWidget::showEvent( evnt ); + viewPort->show(); + } + void GUIEditorWindow::createMenus() { Core::MenuManager *mm = Core::ICore::instance()->menuManager(); diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 1362e4671..6434b07d6 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -66,6 +66,10 @@ private Q_SLOTS: void onAddWidgetClicked(); void onTreeChanged(); +protected: + void hideEvent( QHideEvent *evnt ); + void showEvent( QShowEvent *evnt ); + private: void createMenus(); void removeMenus(); diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index f8e34da3b..e6a056390 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -159,13 +159,13 @@ namespace GUIEditor } } - void NelGUIWidget::showEvent( QShowEvent *evnt ) + void NelGUIWidget::show() { if( timerID == 0 ) timerID = startTimer( 200 ); } - void NelGUIWidget::hideEvent( QHideEvent *evnt ) + void NelGUIWidget::hide() { if( timerID != 0 ) killTimer( timerID ); diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h index a1412257c..dacee1668 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.h +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.h @@ -42,15 +42,15 @@ namespace GUIEditor QWidget* getViewPort(); + void show(); + void hide(); + Q_SIGNALS: void guiLoadComplete(); protected: void paintEvent( QPaintEvent *evnt ); void timerEvent( QTimerEvent *evnt ); - void showEvent( QShowEvent *evnt ); - void hideEvent( QHideEvent *evnt ); - private: int timerID; From 2a4af46577aca2cd440843f62b786f4a2bf6a0bd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:32:27 +0200 Subject: [PATCH 056/220] TimerId should be set to 0 when hiding. --- code/studio/src/plugins/gui_editor/nelgui_widget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index e6a056390..812e002df 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -168,7 +168,10 @@ namespace GUIEditor void NelGUIWidget::hide() { if( timerID != 0 ) + { killTimer( timerID ); + timerID = 0; + } } QWidget* NelGUIWidget::getViewPort() From 7b41b68186b814bb87e191710fff2088aa5d9a88 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:44:57 +0200 Subject: [PATCH 057/220] Renamed NelGUIWidget to NelGUICtrl, and changed it's base class from QWidget to QObject. --- .../plugins/gui_editor/gui_editor_window.cpp | 26 ++++++++--------- .../plugins/gui_editor/gui_editor_window.h | 4 +-- .../src/plugins/gui_editor/nelgui_widget.cpp | 28 ++++++++----------- .../src/plugins/gui_editor/nelgui_widget.h | 13 +++++---- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 1d4050412..236ff93a2 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -65,8 +65,8 @@ namespace GUIEditor projectWindow = new ProjectWindow; addWidgetWidget = new AddWidgetWidget; connect( projectWindow, SIGNAL( projectFilesChanged() ), this, SLOT( onProjectFilesChanged() ) ); - viewPort = new NelGUIWidget; - setCentralWidget( viewPort->getViewPort() ); + GUICtrl = new NelGUICtrl(); + setCentralWidget( GUICtrl->getViewPort() ); widgetInfoTree = new CWidgetInfoTree; @@ -97,9 +97,9 @@ namespace GUIEditor dock->setWidget( propBrowser ); addDockWidget( Qt::RightDockWidgetArea, dock ); - viewPort->init(); + GUICtrl->init(); - connect( viewPort, SIGNAL( guiLoadComplete() ), this, SLOT( onGUILoaded() ) ); + connect( GUICtrl, SIGNAL( guiLoadComplete() ), this, SLOT( onGUILoaded() ) ); connect( widgetProps, SIGNAL( treeChanged() ), this, SLOT( onTreeChanged() ) ); connect( addWidgetWidget, @@ -130,8 +130,8 @@ namespace GUIEditor delete projectWindow; projectWindow = NULL; - delete viewPort; - viewPort = NULL; + delete GUICtrl; + GUICtrl = NULL; delete addWidgetWidget; addWidgetWidget = NULL; @@ -181,7 +181,7 @@ namespace GUIEditor currentProject = projectFiles.projectName.c_str(); currentProjectFile = fileName; projectWindow->setupFiles( projectFiles ); - if( viewPort->parse( projectFiles ) ) + if( GUICtrl->parse( projectFiles ) ) { hierarchyView->buildHierarchy( projectFiles.masterGroup ); } @@ -282,14 +282,14 @@ namespace GUIEditor return false; - CEditorSelectionWatcher *w = viewPort->getWatcher(); + CEditorSelectionWatcher *w = GUICtrl->getWatcher(); disconnect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), hierarchyView, SLOT( onSelectionChanged( std::string& ) ) ); disconnect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), &browserCtrl, SLOT( onSelectionChanged( std::string& ) ) ); projectFiles.clearAll(); projectWindow->clear(); hierarchyView->clearHierarchy(); - viewPort->reset(); + GUICtrl->reset(); browserCtrl.clear(); linkList->clear(); procList->clear(); @@ -305,7 +305,7 @@ namespace GUIEditor setCursor( Qt::WaitCursor ); projectWindow->updateFiles( projectFiles ); - if( !viewPort->parse( projectFiles ) ) + if( !GUICtrl->parse( projectFiles ) ) { QMessageBox::critical( this, tr( "Error parsing GUI XML files" ), @@ -321,7 +321,7 @@ namespace GUIEditor procList->onGUILoaded(); linkList->onGUILoaded(); - CEditorSelectionWatcher *w = viewPort->getWatcher(); + CEditorSelectionWatcher *w = GUICtrl->getWatcher(); connect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), hierarchyView, SLOT( onSelectionChanged( std::string& ) ) ); connect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), &browserCtrl, SLOT( onSelectionChanged( std::string& ) ) ); } @@ -345,13 +345,13 @@ namespace GUIEditor void GUIEditorWindow::hideEvent( QHideEvent *evnt ) { QWidget::hideEvent( evnt ); - viewPort->hide(); + GUICtrl->hide(); } void GUIEditorWindow::showEvent( QShowEvent *evnt ) { QWidget::showEvent( evnt ); - viewPort->show(); + GUICtrl->show(); } void GUIEditorWindow::createMenus() diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 6434b07d6..517186739 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -36,7 +36,7 @@ namespace GUIEditor class LinkList; class ProcList; class ProjectWindow; - class NelGUIWidget; + class NelGUICtrl; class CWidgetInfoTree; class CEditorMessageProcessor; class AddWidgetWidget; @@ -87,7 +87,7 @@ private: LinkList *linkList; ProcList *procList; ProjectWindow *projectWindow; - NelGUIWidget *viewPort; + NelGUICtrl *GUICtrl; CWidgetInfoTree *widgetInfoTree; CEditorMessageProcessor *messageProcessor; AddWidgetWidget *addWidgetWidget; diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp index 812e002df..6fc9db7e3 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.cpp @@ -35,8 +35,8 @@ namespace GUIEditor { std::set< std::string > hwCursors; - NelGUIWidget::NelGUIWidget( QWidget *parent ) : - QWidget( parent ) + NelGUICtrl::NelGUICtrl( QObject *parent ) : + QObject( parent ) { timerID = 0; guiLoaded = false; @@ -44,7 +44,7 @@ namespace GUIEditor w = new Nel3DWidget(); } - NelGUIWidget::~NelGUIWidget() + NelGUICtrl::~NelGUICtrl() { guiLoaded = false; if( timerID != 0 ) @@ -57,7 +57,7 @@ namespace GUIEditor w = NULL; } - void NelGUIWidget::init() + void NelGUICtrl::init() { NLMISC::CI18N::setNoResolution( true ); NLMISC::CPath::remapExtension( "dds", "tga", true ); @@ -81,7 +81,7 @@ namespace GUIEditor watcher = new CEditorSelectionWatcher(); } - bool NelGUIWidget::parse( SProjectFiles &files ) + bool NelGUICtrl::parse( SProjectFiles &files ) { reset(); IParser *parser = CWidgetManager::getInstance()->getParser(); @@ -120,7 +120,7 @@ namespace GUIEditor return true; } - void NelGUIWidget::reset() + void NelGUICtrl::reset() { guiLoaded = false; if( timerID != 0 ) @@ -133,7 +133,7 @@ namespace GUIEditor w->clear(); } - void NelGUIWidget::draw() + void NelGUICtrl::draw() { w->getDriver()->clearBuffers( NLMISC::CRGBA::Black ); CWidgetManager::getInstance()->checkCoords(); @@ -141,13 +141,7 @@ namespace GUIEditor w->getDriver()->swapBuffers(); } - void NelGUIWidget::paintEvent( QPaintEvent *evnt ) - { - if( !guiLoaded ) - w->clear(); - } - - void NelGUIWidget::timerEvent( QTimerEvent *evnt ) + void NelGUICtrl::timerEvent( QTimerEvent *evnt ) { if( evnt->timerId() == timerID ) { @@ -159,13 +153,13 @@ namespace GUIEditor } } - void NelGUIWidget::show() + void NelGUICtrl::show() { if( timerID == 0 ) timerID = startTimer( 200 ); } - void NelGUIWidget::hide() + void NelGUICtrl::hide() { if( timerID != 0 ) { @@ -174,7 +168,7 @@ namespace GUIEditor } } - QWidget* NelGUIWidget::getViewPort() + QWidget* NelGUICtrl::getViewPort() { return w; } diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_widget.h index dacee1668..38da599e4 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.h +++ b/code/studio/src/plugins/gui_editor/nelgui_widget.h @@ -18,21 +18,23 @@ #ifndef NELGUI_WIDGET_H #define NELGUI_WIDGET_H -#include +#include #include "project_files.h" +class QWidget; + namespace GUIEditor { class CEditorSelectionWatcher; class Nel3DWidget; - /// Qt viewport for the Nel GUI library - class NelGUIWidget : public QWidget + /// Qt viewport controller for the Nel GUI library + class NelGUICtrl : public QObject { Q_OBJECT public: - NelGUIWidget( QWidget *parent = NULL ); - ~NelGUIWidget(); + NelGUICtrl( QObject *parent = NULL ); + ~NelGUICtrl(); void init(); bool parse( SProjectFiles &files ); @@ -49,7 +51,6 @@ Q_SIGNALS: void guiLoadComplete(); protected: - void paintEvent( QPaintEvent *evnt ); void timerEvent( QTimerEvent *evnt ); private: From 1992e17172c5b924c0973e3e3596a2054a172a23 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 19:37:42 +0200 Subject: [PATCH 058/220] Renamed nelgui_widget.* to nelgui_ctrl.* --- code/studio/src/plugins/gui_editor/CMakeLists.txt | 2 +- code/studio/src/plugins/gui_editor/gui_editor_window.cpp | 2 +- .../plugins/gui_editor/{nelgui_widget.cpp => nelgui_ctrl.cpp} | 2 +- .../src/plugins/gui_editor/{nelgui_widget.h => nelgui_ctrl.h} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename code/studio/src/plugins/gui_editor/{nelgui_widget.cpp => nelgui_ctrl.cpp} (99%) rename code/studio/src/plugins/gui_editor/{nelgui_widget.h => nelgui_ctrl.h} (100%) diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index ff248a261..2ea82a6e4 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -25,7 +25,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR property_browser_ctrl.h project_window.h nel3d_widget.h - nelgui_widget.h + nelgui_ctrl.h new_property_widget.h new_widget_widget.h add_widget_widget.h diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 236ff93a2..4f66b61fc 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -40,7 +40,7 @@ #include "project_file_parser.h" #include "project_file_serializer.h" #include "project_window.h" -#include "nelgui_widget.h" +#include "nelgui_ctrl.h" #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp similarity index 99% rename from code/studio/src/plugins/gui_editor/nelgui_widget.cpp rename to code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 6fc9db7e3..2a9a433ee 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . -#include "nelgui_widget.h" +#include "nelgui_ctrl.h" #include "nel/misc/path.h" #include "nel/gui/view_renderer.h" #include "nel/gui/interface_group.h" diff --git a/code/studio/src/plugins/gui_editor/nelgui_widget.h b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h similarity index 100% rename from code/studio/src/plugins/gui_editor/nelgui_widget.h rename to code/studio/src/plugins/gui_editor/nelgui_ctrl.h From 29526906c49580fb20eeece08ee0010c03158e86 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 18:41:54 +0200 Subject: [PATCH 059/220] Fixed build error that was caused by two widgets having the same filenames. --- code/studio/src/plugins/core/settings_dialog.cpp | 2 +- code/studio/src/plugins/core/settings_dialog.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/core/settings_dialog.cpp b/code/studio/src/plugins/core/settings_dialog.cpp index 4b7bbac3a..0b38e4e80 100644 --- a/code/studio/src/plugins/core/settings_dialog.cpp +++ b/code/studio/src/plugins/core/settings_dialog.cpp @@ -17,7 +17,7 @@ // along with this program. If not, see . // Project includes -#include "settings_dialog.h" +#include "../core/settings_dialog.h" #include "ioptions_page.h" // Qt includes diff --git a/code/studio/src/plugins/core/settings_dialog.h b/code/studio/src/plugins/core/settings_dialog.h index 9e1c86444..a90f88b18 100644 --- a/code/studio/src/plugins/core/settings_dialog.h +++ b/code/studio/src/plugins/core/settings_dialog.h @@ -19,7 +19,7 @@ #ifndef SETTINGS_DIALOG_H #define SETTINGS_DIALOG_H -#include "ui_settings_dialog.h" +#include "../core/ui_settings_dialog.h" // Qt includes #include From 5d71cdd56de99ca7f73c55a015bc455721aef6d0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:16:52 +0200 Subject: [PATCH 060/220] Moved the event listener from the 3d widget to the gui control class. --- .../src/plugins/gui_editor/nel3d_widget.cpp | 7 +------ code/studio/src/plugins/gui_editor/nel3d_widget.h | 6 ------ .../studio/src/plugins/gui_editor/nelgui_ctrl.cpp | 15 +++++++++++++++ code/studio/src/plugins/gui_editor/nelgui_ctrl.h | 10 +++++++++- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 3fd7abb7b..5be8bacb8 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -21,8 +21,7 @@ #include "nel/3d/driver_user.h" #include "nel/misc/rgba.h" #include "nel/misc/path.h" -#include "nel/misc/event_listener.h" -#include "nel/gui/event_listener.h" +//#include "nel/misc/event_listener.h" #ifdef NL_OS_WINDOWS #include @@ -42,7 +41,6 @@ namespace GUIEditor // so that we can render the widget normally ourselves, without the image // disappearing when a widget is resized or shown on top of us setAttribute( Qt::WA_PaintOnScreen, true ); - eventListener = NULL; } Nel3DWidget::~Nel3DWidget() @@ -59,7 +57,6 @@ namespace GUIEditor delete driver; driver = NULL; } - delete eventListener; } void Nel3DWidget::init() @@ -69,8 +66,6 @@ namespace GUIEditor driver = NL3D::UDriver::createDriver( 0, false, 0 ); driver->setMatrixMode2D11(); driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); - eventListener = new NLGUI::CEventListener(); - eventListener->addToServer( &driver->EventServer ); } void Nel3DWidget::createTextContext( std::string fontFile ) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h index fb4321d49..07a74b8c3 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.h @@ -22,11 +22,6 @@ #include "nel/misc/types_nl.h" #include -namespace NLGUI -{ - class CEventListener; -} - namespace NL3D { class UDriver; @@ -71,7 +66,6 @@ namespace GUIEditor private: NL3D::UDriver *driver; NL3D::UTextContext *textContext; - NLGUI::CEventListener *eventListener; }; } diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 2a9a433ee..4e72ba614 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -22,6 +22,7 @@ #include "nel/gui/widget_manager.h" #include "nel/gui/action_handler.h" #include "nel/gui/lua_manager.h" +#include "nel/gui/event_listener.h" #include "nel/misc/path.h" #include "nel/misc/i18n.h" #include @@ -42,6 +43,8 @@ namespace GUIEditor guiLoaded = false; watcher = NULL; w = new Nel3DWidget(); + eventListener = new NLGUI::CEventListener(); + listening = false; } NelGUICtrl::~NelGUICtrl() @@ -157,6 +160,12 @@ namespace GUIEditor { if( timerID == 0 ) timerID = startTimer( 200 ); + + if( !listening ) + { + eventListener->addToServer( &w->getDriver()->EventServer ); + listening = true; + } } void NelGUICtrl::hide() @@ -166,6 +175,12 @@ namespace GUIEditor killTimer( timerID ); timerID = 0; } + + if( listening ) + { + eventListener->removeFromServer(); + listening = false; + } } QWidget* NelGUICtrl::getViewPort() diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h index 38da599e4..f13a57b9b 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h @@ -23,6 +23,11 @@ class QWidget; +namespace NLGUI +{ + class CEventListener; +} + namespace GUIEditor { class CEditorSelectionWatcher; @@ -58,8 +63,11 @@ Q_SIGNALS: bool guiLoaded; CEditorSelectionWatcher *watcher; + NLGUI::CEventListener *eventListener; - Nel3DWidget *w; + Nel3DWidget *w; + + bool listening; }; } From 4f0cae93d21fa3ac3f98feb149bfe79b78161329 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:28:57 +0200 Subject: [PATCH 061/220] Activate the driver when getting a show event, and clear the GUI Editor display widget when there's no GUI loaded. --- code/studio/src/plugins/gui_editor/nel3d_widget.cpp | 7 +++++++ code/studio/src/plugins/gui_editor/nel3d_widget.h | 2 ++ code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 5be8bacb8..1e030db25 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -102,6 +102,13 @@ namespace GUIEditor driver->swapBuffers(); } + void Nel3DWidget::showEvent( QShowEvent *evnt ) + { + QWidget::showEvent( evnt ); + + if( driver != NULL ) + driver->activate(); + } #if defined ( NL_OS_WINDOWS ) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h index 07a74b8c3..e2d5f00b6 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.h @@ -55,6 +55,8 @@ namespace GUIEditor protected: + void showEvent( QShowEvent *evnt ); + #if defined(NL_OS_WINDOWS) virtual bool winEvent( MSG *message, long *result ); #elif defined(NL_OS_MAC) diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 4e72ba614..72bb9524f 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -153,6 +153,10 @@ namespace GUIEditor w->getDriver()->EventServer.pump(); draw(); } + else + { + w->clear(); + } } } From 324fd79243833fcdab4bd19a92e1f33a9001dc61 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:42:41 +0200 Subject: [PATCH 062/220] Set some windows attributes. --- code/studio/src/plugins/gui_editor/nel3d_widget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 1e030db25..682645421 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -41,6 +41,8 @@ namespace GUIEditor // so that we can render the widget normally ourselves, without the image // disappearing when a widget is resized or shown on top of us setAttribute( Qt::WA_PaintOnScreen, true ); + setAttribute( Qt::WA_OpaquePaintEvent, true ); + setAttribute( Qt::WA_NoSystemBackground, true ); } Nel3DWidget::~Nel3DWidget() From b51660f2dda2cf603945f73635497e19ccaf9a89 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:52:04 +0200 Subject: [PATCH 063/220] Nel3DWidget is no longer in the GUI Editor namespace. --- .../src/plugins/gui_editor/nel3d_widget.cpp | 209 +++++++++--------- .../src/plugins/gui_editor/nel3d_widget.h | 54 +++-- .../src/plugins/gui_editor/nelgui_ctrl.h | 2 +- 3 files changed, 128 insertions(+), 137 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp index 682645421..8ebc393ba 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.cpp @@ -27,152 +27,145 @@ #include #endif - - -namespace GUIEditor +Nel3DWidget::Nel3DWidget( QWidget *parent ) : +QWidget( parent ) { - Nel3DWidget::Nel3DWidget( QWidget *parent ) : - QWidget( parent ) + driver = NULL; + textContext = NULL; + + // Need to set this attribute with a NULL paintengine returned to Qt + // so that we can render the widget normally ourselves, without the image + // disappearing when a widget is resized or shown on top of us + setAttribute( Qt::WA_PaintOnScreen, true ); + setAttribute( Qt::WA_OpaquePaintEvent, true ); + setAttribute( Qt::WA_NoSystemBackground, true ); +} + +Nel3DWidget::~Nel3DWidget() +{ + if( driver != NULL ) { - driver = NULL; - textContext = NULL; - - // Need to set this attribute with a NULL paintengine returned to Qt - // so that we can render the widget normally ourselves, without the image - // disappearing when a widget is resized or shown on top of us - setAttribute( Qt::WA_PaintOnScreen, true ); - setAttribute( Qt::WA_OpaquePaintEvent, true ); - setAttribute( Qt::WA_NoSystemBackground, true ); - } - - Nel3DWidget::~Nel3DWidget() - { - if( driver != NULL ) - { - if( textContext != NULL ) - { - driver->deleteTextContext( textContext ); - textContext = NULL; - } - - driver->release(); - delete driver; - driver = NULL; - } - } - - void Nel3DWidget::init() - { - nlassert( driver == NULL ); - - driver = NL3D::UDriver::createDriver( 0, false, 0 ); - driver->setMatrixMode2D11(); - driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); - } - - void Nel3DWidget::createTextContext( std::string fontFile ) - { - if( driver == NULL ) - return; - - std::string font; - - try - { - font = NLMISC::CPath::lookup( fontFile ); - } - catch( ... ) - { - nlinfo( "Font %s cannot be found, cannot create textcontext!", fontFile.c_str() ); - exit( EXIT_FAILURE ); - } - if( textContext != NULL ) { driver->deleteTextContext( textContext ); textContext = NULL; } - textContext = driver->createTextContext( font ); + driver->release(); + delete driver; + driver = NULL; } +} - void Nel3DWidget::clear() +void Nel3DWidget::init() +{ + nlassert( driver == NULL ); + + driver = NL3D::UDriver::createDriver( 0, false, 0 ); + driver->setMatrixMode2D11(); + driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); +} + +void Nel3DWidget::createTextContext( std::string fontFile ) +{ + if( driver == NULL ) + return; + + std::string font; + + try { - if( driver == NULL ) - return; - driver->clearBuffers( NLMISC::CRGBA::Black ); - driver->swapBuffers(); + font = NLMISC::CPath::lookup( fontFile ); } - - void Nel3DWidget::showEvent( QShowEvent *evnt ) + catch( ... ) { - QWidget::showEvent( evnt ); - - if( driver != NULL ) - driver->activate(); + nlinfo( "Font %s cannot be found, cannot create textcontext!", fontFile.c_str() ); + exit( EXIT_FAILURE ); } + if( textContext != NULL ) + { + driver->deleteTextContext( textContext ); + textContext = NULL; + } + + textContext = driver->createTextContext( font ); +} + +void Nel3DWidget::clear() +{ + if( driver == NULL ) + return; + driver->clearBuffers( NLMISC::CRGBA::Black ); + driver->swapBuffers(); +} + +void Nel3DWidget::showEvent( QShowEvent *evnt ) +{ + QWidget::showEvent( evnt ); + + if( driver != NULL ) + driver->activate(); +} + #if defined ( NL_OS_WINDOWS ) - typedef bool ( *winProc )( NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); +typedef bool ( *winProc )( NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); - bool Nel3DWidget::winEvent( MSG *message, long *result ) +bool Nel3DWidget::winEvent( MSG *message, long *result ) +{ + if( driver != NULL ) { - if( driver != NULL ) + NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); + if( iDriver != NULL ) { - NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); - if( iDriver != NULL ) - { - winProc proc = (winProc)iDriver->getWindowProc(); - return proc( iDriver, message->hwnd, message->message, message->wParam, message->lParam ); - } + winProc proc = (winProc)iDriver->getWindowProc(); + return proc( iDriver, message->hwnd, message->message, message->wParam, message->lParam ); } - - return false; } + return false; +} + #elif defined( NL_OS_MAC ) - typedef bool ( *cocoaProc )( NL3D::IDriver *, const void *e ); +typedef bool ( *cocoaProc )( NL3D::IDriver *, const void *e ); - bool Nel3DWidget::macEvent( EventHandlerCallRef caller, EventRef event ) +bool Nel3DWidget::macEvent( EventHandlerCallRef caller, EventRef event ) +{ + if( caller ) + nlerror( "You are using QtCarbon! Only QtCocoa supported, please upgrade Qt" ); + + if( driver != NULL ) { - if( caller ) - nlerror( "You are using QtCarbon! Only QtCocoa supported, please upgrade Qt" ); - - if( driver != NULL ) + NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); + if( iDriver != NULL ) { - NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); - if( iDriver != NULL ) - { - cocoaProc proc = ( cocoaProc )iDriver->getWindowProc(); - return proc( iDriver, event ); - } + cocoaProc proc = ( cocoaProc )iDriver->getWindowProc(); + return proc( iDriver, event ); } - - return false; } + return false; +} + #elif defined( NL_OS_UNIX ) - typedef bool ( *x11Proc )( NL3D::IDriver *drv, XEvent *e ); +typedef bool ( *x11Proc )( NL3D::IDriver *drv, XEvent *e ); - bool Nel3DWidget::x11Event( XEvent *event ) +bool Nel3DWidget::x11Event( XEvent *event ) +{ + if( driver != NULL ) { + NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); if( driver != NULL ) { - NL3D::IDriver *iDriver = dynamic_cast< NL3D::CDriverUser* >( driver )->getDriver(); - if( driver != NULL ) - { - x11Proc proc = ( x11Proc )iDriver->getWindowProc(); - return proc( iDriver, event ); - } + x11Proc proc = ( x11Proc )iDriver->getWindowProc(); + return proc( iDriver, event ); } - - return false; } + + return false; +} #endif -} - - diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/plugins/gui_editor/nel3d_widget.h index e2d5f00b6..672fc3fde 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/plugins/gui_editor/nel3d_widget.h @@ -28,48 +28,46 @@ namespace NL3D class UTextContext; } -namespace GUIEditor +/// Nel 3D interface to Qt +class Nel3DWidget : public QWidget { - /// Nel 3D interface to Qt - class Nel3DWidget : public QWidget - { - Q_OBJECT - public: - Nel3DWidget( QWidget *parent = NULL ); - virtual ~Nel3DWidget(); + Q_OBJECT +public: + Nel3DWidget( QWidget *parent = NULL ); + virtual ~Nel3DWidget(); - virtual void init(); - void createTextContext( std::string fontFile ); + void init(); + void createTextContext( std::string fontFile ); - NL3D::UDriver* getDriver() const{ return driver; } - NL3D::UTextContext* getTextContext() const{ return textContext; } + NL3D::UDriver* getDriver() const{ return driver; } + NL3D::UTextContext* getTextContext() const{ return textContext; } - // Need to return NULL paintengine to Qt so that we can - // render the widget normally ourselves, without the image - // disappearing when a widget is resized or shown on top of us - QPaintEngine* paintEngine() const{ return NULL; } + // Need to return NULL paintengine to Qt so that we can + // render the widget normally ourselves, without the image + // disappearing when a widget is resized or shown on top of us + QPaintEngine* paintEngine() const{ return NULL; } - public Q_SLOTS: - void clear(); +public Q_SLOTS: + void clear(); - protected: +protected: - void showEvent( QShowEvent *evnt ); + void showEvent( QShowEvent *evnt ); #if defined(NL_OS_WINDOWS) - virtual bool winEvent( MSG *message, long *result ); + bool winEvent( MSG *message, long *result ); #elif defined(NL_OS_MAC) - virtual bool macEvent( EventHandlerCallRef caller, EventRef event ); + bool macEvent( EventHandlerCallRef caller, EventRef event ); #elif defined(NL_OS_UNIX) - virtual bool x11Event( XEvent *event ); + bool x11Event( XEvent *event ); #endif - private: - NL3D::UDriver *driver; - NL3D::UTextContext *textContext; - }; -} +private: + NL3D::UDriver *driver; + NL3D::UTextContext *textContext; + +}; #endif diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h index f13a57b9b..b3c68ff32 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.h +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.h @@ -22,6 +22,7 @@ #include "project_files.h" class QWidget; +class Nel3DWidget; namespace NLGUI { @@ -31,7 +32,6 @@ namespace NLGUI namespace GUIEditor { class CEditorSelectionWatcher; - class Nel3DWidget; /// Qt viewport controller for the Nel GUI library class NelGUICtrl : public QObject From f28b134fb453ac47609b48be9e4e28f0dbb4e367 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 22:22:01 +0200 Subject: [PATCH 064/220] Moved the Nel 3d widget into it's own library. --- code/studio/src/CMakeLists.txt | 1 + code/studio/src/Nel3DWidget/CMakeLists.txt | 36 +++++++++++++++++++ .../nel3d_widget.cpp | 0 .../gui_editor => Nel3DWidget}/nel3d_widget.h | 8 ++++- .../src/plugins/gui_editor/CMakeLists.txt | 2 +- .../src/plugins/gui_editor/nelgui_ctrl.cpp | 2 +- 6 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 code/studio/src/Nel3DWidget/CMakeLists.txt rename code/studio/src/{plugins/gui_editor => Nel3DWidget}/nel3d_widget.cpp (100%) rename code/studio/src/{plugins/gui_editor => Nel3DWidget}/nel3d_widget.h (92%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 9bc071bf2..8670f516f 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_SUBDIRECTORY(3rdparty) +ADD_SUBDIRECTORY(Nel3DWidget) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${QT_INCLUDES}) INCLUDE( ${QT_USE_FILE} ) diff --git a/code/studio/src/Nel3DWidget/CMakeLists.txt b/code/studio/src/Nel3DWidget/CMakeLists.txt new file mode 100644 index 000000000..55b4b2a80 --- /dev/null +++ b/code/studio/src/Nel3DWidget/CMakeLists.txt @@ -0,0 +1,36 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${QT_INCLUDES} + ) + +INCLUDE( ${QT_USE_FILE} ) + +FILE(GLOB SRC *.cpp *.h) + +SET(NEL3DWIDGET_HDR + nel3d_widget.h + ) + +SET(QT_USE_QTGUI TRUE) + +QT4_WRAP_CPP( NEL3DWIDGET_MOC_SRC ${NEL3DWIDGET_HDR} ) + +SOURCE_GROUP(QtGeneratedMocSrc FILES ${NEL3DWIDGET_MOC_SRC} ) +SOURCE_GROUP("Nel 3D Widget files" FILES ${SRC}) + +ADD_LIBRARY(nel3dwidget SHARED + ${SRC} + ${NEL3DWIDGET_MOC_SRC} + ) + +TARGET_LINK_LIBRARIES( nel3dwidget + nelmisc + nel3d + ${QT_LIBRARIES} + ) + +NL_DEFAULT_PROPS(nel3dwidget "Nel3D Qt Widget") +NL_ADD_RUNTIME_FLAGS(nel3dwidget) +NL_ADD_LIB_SUFFIX(nel3dwidget) + +ADD_DEFINITIONS( -DN3DW_LIB -DQT_DLL -DQT_SHARED ${QT_DEFINITIONS} ) diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.cpp b/code/studio/src/Nel3DWidget/nel3d_widget.cpp similarity index 100% rename from code/studio/src/plugins/gui_editor/nel3d_widget.cpp rename to code/studio/src/Nel3DWidget/nel3d_widget.cpp diff --git a/code/studio/src/plugins/gui_editor/nel3d_widget.h b/code/studio/src/Nel3DWidget/nel3d_widget.h similarity index 92% rename from code/studio/src/plugins/gui_editor/nel3d_widget.h rename to code/studio/src/Nel3DWidget/nel3d_widget.h index 672fc3fde..d3e6c3ae1 100644 --- a/code/studio/src/plugins/gui_editor/nel3d_widget.h +++ b/code/studio/src/Nel3DWidget/nel3d_widget.h @@ -22,6 +22,12 @@ #include "nel/misc/types_nl.h" #include +#if defined( N3DW_LIB ) +#define N3DW_EXPORT Q_DECL_EXPORT +#else +#define N3DW_EXPORT Q_DECL_IMPORT +#endif + namespace NL3D { class UDriver; @@ -29,7 +35,7 @@ namespace NL3D } /// Nel 3D interface to Qt -class Nel3DWidget : public QWidget +class N3DW_EXPORT Nel3DWidget : public QWidget { Q_OBJECT public: diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 2ea82a6e4..5adf618d0 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -24,7 +24,6 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR action_editor.h property_browser_ctrl.h project_window.h - nel3d_widget.h nelgui_ctrl.h new_property_widget.h new_widget_widget.h @@ -78,6 +77,7 @@ TARGET_LINK_LIBRARIES( ${QT_QTOPENGL_LIBRARY} ${LIBXML2_LIBRARIES} qt_property_browser + nel3dwidget ) NL_DEFAULT_PROPS(studio_plugin_gui_editor "Tools: Studio Plugin: GUI Editor") diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index 72bb9524f..b2cf67ea2 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -30,7 +30,7 @@ #include #include "editor_selection_watcher.h" -#include "nel3d_widget.h" +#include "../../Nel3DWidget/nel3d_widget.h" namespace GUIEditor { From 320a9dd33a06c29deae680a6764738a700acc88a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 16 Jun 2014 15:30:35 +0200 Subject: [PATCH 065/220] Had to move the Nel3DWidget library to the core plugin, because Nel can only be used statically at this point. Which makes using the separate Nel3DWidget library inparctical. --- code/studio/src/CMakeLists.txt | 1 - code/studio/src/Nel3DWidget/CMakeLists.txt | 36 ------------------- code/studio/src/plugins/core/CMakeLists.txt | 8 ++++- .../core}/Nel3DWidget/nel3d_widget.cpp | 0 .../core}/Nel3DWidget/nel3d_widget.h | 8 ++--- .../src/plugins/gui_editor/CMakeLists.txt | 1 - .../src/plugins/gui_editor/nelgui_ctrl.cpp | 2 +- 7 files changed, 10 insertions(+), 46 deletions(-) delete mode 100644 code/studio/src/Nel3DWidget/CMakeLists.txt rename code/studio/src/{ => plugins/core}/Nel3DWidget/nel3d_widget.cpp (100%) rename code/studio/src/{ => plugins/core}/Nel3DWidget/nel3d_widget.h (92%) diff --git a/code/studio/src/CMakeLists.txt b/code/studio/src/CMakeLists.txt index 8670f516f..9bc071bf2 100644 --- a/code/studio/src/CMakeLists.txt +++ b/code/studio/src/CMakeLists.txt @@ -1,5 +1,4 @@ ADD_SUBDIRECTORY(3rdparty) -ADD_SUBDIRECTORY(Nel3DWidget) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${LIBXML2_INCLUDE_DIR} ${NEL_INCLUDE_DIR} ${QT_INCLUDES}) INCLUDE( ${QT_USE_FILE} ) diff --git a/code/studio/src/Nel3DWidget/CMakeLists.txt b/code/studio/src/Nel3DWidget/CMakeLists.txt deleted file mode 100644 index 55b4b2a80..000000000 --- a/code/studio/src/Nel3DWidget/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${QT_INCLUDES} - ) - -INCLUDE( ${QT_USE_FILE} ) - -FILE(GLOB SRC *.cpp *.h) - -SET(NEL3DWIDGET_HDR - nel3d_widget.h - ) - -SET(QT_USE_QTGUI TRUE) - -QT4_WRAP_CPP( NEL3DWIDGET_MOC_SRC ${NEL3DWIDGET_HDR} ) - -SOURCE_GROUP(QtGeneratedMocSrc FILES ${NEL3DWIDGET_MOC_SRC} ) -SOURCE_GROUP("Nel 3D Widget files" FILES ${SRC}) - -ADD_LIBRARY(nel3dwidget SHARED - ${SRC} - ${NEL3DWIDGET_MOC_SRC} - ) - -TARGET_LINK_LIBRARIES( nel3dwidget - nelmisc - nel3d - ${QT_LIBRARIES} - ) - -NL_DEFAULT_PROPS(nel3dwidget "Nel3D Qt Widget") -NL_ADD_RUNTIME_FLAGS(nel3dwidget) -NL_ADD_LIB_SUFFIX(nel3dwidget) - -ADD_DEFINITIONS( -DN3DW_LIB -DQT_DLL -DQT_SHARED ${QT_DEFINITIONS} ) diff --git a/code/studio/src/plugins/core/CMakeLists.txt b/code/studio/src/plugins/core/CMakeLists.txt index 964f95b11..2c21c9b58 100644 --- a/code/studio/src/plugins/core/CMakeLists.txt +++ b/code/studio/src/plugins/core/CMakeLists.txt @@ -4,6 +4,11 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${QT_INCLUDES}) FILE(GLOB SRC *.cpp *.h) +SET( SRC ${SRC} + ${CMAKE_CURRENT_SOURCE_DIR}/Nel3DWidget/nel3d_widget.h + ${CMAKE_CURRENT_SOURCE_DIR}/Nel3DWidget/nel3d_widget.cpp + ) + SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) @@ -22,6 +27,7 @@ SET(OVQT_CORE_PLUGIN_HDR search_paths_settings_page.h general_settings_page.h plugin_view_dialog.h + ${CMAKE_CURRENT_SOURCE_DIR}/Nel3DWidget/nel3d_widget.h ) SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui @@ -47,7 +53,7 @@ SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) ADD_LIBRARY(studio_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) -TARGET_LINK_LIBRARIES(studio_plugin_core nelmisc ${QT_LIBRARIES}) +TARGET_LINK_LIBRARIES(studio_plugin_core nelmisc nel3d ${QT_LIBRARIES}) NL_DEFAULT_PROPS(studio_plugin_core "Tools: Studio Plugin: Core") NL_ADD_RUNTIME_FLAGS(studio_plugin_core) diff --git a/code/studio/src/Nel3DWidget/nel3d_widget.cpp b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp similarity index 100% rename from code/studio/src/Nel3DWidget/nel3d_widget.cpp rename to code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp diff --git a/code/studio/src/Nel3DWidget/nel3d_widget.h b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h similarity index 92% rename from code/studio/src/Nel3DWidget/nel3d_widget.h rename to code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h index d3e6c3ae1..9cbf474bc 100644 --- a/code/studio/src/Nel3DWidget/nel3d_widget.h +++ b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h @@ -22,11 +22,7 @@ #include "nel/misc/types_nl.h" #include -#if defined( N3DW_LIB ) -#define N3DW_EXPORT Q_DECL_EXPORT -#else -#define N3DW_EXPORT Q_DECL_IMPORT -#endif +#include "../core_global.h" namespace NL3D { @@ -35,7 +31,7 @@ namespace NL3D } /// Nel 3D interface to Qt -class N3DW_EXPORT Nel3DWidget : public QWidget +class CORE_EXPORT Nel3DWidget : public QWidget { Q_OBJECT public: diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 5adf618d0..0c13c4cd6 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -77,7 +77,6 @@ TARGET_LINK_LIBRARIES( ${QT_QTOPENGL_LIBRARY} ${LIBXML2_LIBRARIES} qt_property_browser - nel3dwidget ) NL_DEFAULT_PROPS(studio_plugin_gui_editor "Tools: Studio Plugin: GUI Editor") diff --git a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp index b2cf67ea2..03f784944 100644 --- a/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/nelgui_ctrl.cpp @@ -30,7 +30,7 @@ #include #include "editor_selection_watcher.h" -#include "../../Nel3DWidget/nel3d_widget.h" +#include "../core/Nel3DWidget/nel3d_widget.h" namespace GUIEditor { From bfe1805927c82c77d8eb80c0bc337f530733ab13 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 16 Jun 2014 16:22:52 +0200 Subject: [PATCH 066/220] Object Viewer plugin will now use the Nel3DWidget in the Core plugin. --- .../plugins/core/Nel3DWidget/nel3d_widget.cpp | 13 ++- .../plugins/core/Nel3DWidget/nel3d_widget.h | 6 +- .../object_viewer/graphics_viewport.cpp | 100 ++++-------------- .../plugins/object_viewer/graphics_viewport.h | 40 ++----- .../src/plugins/object_viewer/main_window.cpp | 2 +- .../plugins/object_viewer/object_viewer.cpp | 17 +-- .../src/plugins/object_viewer/object_viewer.h | 2 +- 7 files changed, 52 insertions(+), 128 deletions(-) diff --git a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp index 8ebc393ba..dc0bb858b 100644 --- a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp +++ b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.cpp @@ -1,4 +1,4 @@ -// Object Viewer Qt GUI Editor plugin +// Ryzom Core MMORPG framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify @@ -21,12 +21,13 @@ #include "nel/3d/driver_user.h" #include "nel/misc/rgba.h" #include "nel/misc/path.h" -//#include "nel/misc/event_listener.h" #ifdef NL_OS_WINDOWS #include #endif +#include + Nel3DWidget::Nel3DWidget( QWidget *parent ) : QWidget( parent ) { @@ -62,7 +63,6 @@ void Nel3DWidget::init() nlassert( driver == NULL ); driver = NL3D::UDriver::createDriver( 0, false, 0 ); - driver->setMatrixMode2D11(); driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); } @@ -108,6 +108,13 @@ void Nel3DWidget::showEvent( QShowEvent *evnt ) driver->activate(); } +void Nel3DWidget::resizeEvent( QResizeEvent *evnt ) +{ + QWidget::resizeEvent( evnt ); + + Q_EMIT( evnt->size().width(), evnt->size().height() ); +} + #if defined ( NL_OS_WINDOWS ) typedef bool ( *winProc )( NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); diff --git a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h index 9cbf474bc..059e1b738 100644 --- a/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h +++ b/code/studio/src/plugins/core/Nel3DWidget/nel3d_widget.h @@ -1,4 +1,4 @@ -// Object Viewer Qt GUI Editor plugin +// Ryzom Core MMORPG framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify @@ -50,12 +50,16 @@ public: // disappearing when a widget is resized or shown on top of us QPaintEngine* paintEngine() const{ return NULL; } +Q_SIGNALS: + void resize( int width, int height ); + public Q_SLOTS: void clear(); protected: void showEvent( QShowEvent *evnt ); + void resizeEvent( QResizeEvent *evnt ); #if defined(NL_OS_WINDOWS) bool winEvent( MSG *message, long *result ); diff --git a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp index d8e36e785..8cf6f3f60 100644 --- a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp +++ b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp @@ -19,6 +19,7 @@ #include "stdpch.h" #include "graphics_viewport.h" +#include "../core/Nel3DWidget/nel3d_widget.h" // STL includes @@ -46,17 +47,18 @@ using namespace NL3D; namespace NLQT { -CGraphicsViewport::CGraphicsViewport(QWidget *parent) - : QNLWidget(parent) +CGraphicsViewport::CGraphicsViewport(QObject *parent) + : QObject(parent) { - setAttribute(Qt::WA_OpaquePaintEvent); - setAttribute(Qt::WA_NoSystemBackground); - setAttribute(Qt::WA_PaintOnScreen); + w = new Nel3DWidget(); + connect( w, SIGNAL( resize( int, int ) ), this, SLOT( onResize( int, int ) ) ); } CGraphicsViewport::~CGraphicsViewport() { - + disconnect( w, SIGNAL( resize( int, int ) ), this, SLOT( onResize( int, int ) ) ); + delete w; + w = NULL; } void CGraphicsViewport::init() @@ -68,12 +70,13 @@ void CGraphicsViewport::init() makeCurrent(); #endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC) - Modules::objView().init((nlWindow)winId(), width(), height()); + w->init(); + Modules::objView().init( w->getDriver() ); Modules::psEdit().init(); Modules::veget().init(); - setMouseTracking(true); - setFocusPolicy(Qt::StrongFocus); + w->setMouseTracking(true); + w->setFocusPolicy(Qt::StrongFocus); } void CGraphicsViewport::release() @@ -101,6 +104,11 @@ QAction *CGraphicsViewport::createSetBackgroundColor(QObject *parent) return action; } +QWidget* CGraphicsViewport::widget() +{ + return w; +} + void CGraphicsViewport::saveScreenshot() { Modules::objView().saveScreenshot("screenshot", false, true, false); @@ -115,81 +123,11 @@ void CGraphicsViewport::setBackgroundColor() Modules::objView().setBackgroundColor(NLMISC::CRGBA(color.red(), color.green(), color.blue())); } -void CGraphicsViewport::resizeEvent(QResizeEvent *resizeEvent) +void CGraphicsViewport::onResize( int width, int height ) { - QWidget::resizeEvent(resizeEvent); if (Modules::objView().getDriver()) - Modules::objView().setSizeViewport(resizeEvent->size().width(), resizeEvent->size().height()); + Modules::objView().setSizeViewport( width, height ); } -#if defined(NL_OS_WINDOWS) - -typedef bool (*winProc)(NL3D::IDriver *driver, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - -bool CGraphicsViewport::winEvent(MSG *message, long *result) -{ - if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive()) - { - NL3D::IDriver *driver = dynamic_cast(Modules::objView().getDriver())->getDriver(); - if (driver) - { - winProc proc = (winProc)driver->getWindowProc(); - - // TODO: shouldn't it return false like the others? - // see macEvent() and x11Event() below - return proc(driver, message->hwnd, message->message, message->wParam, message->lParam); - } - } - - return false; -} - -#elif defined(NL_OS_MAC) - -typedef bool (*cocoaProc)(NL3D::IDriver *, const void *e); - -bool CGraphicsViewport::macEvent(EventHandlerCallRef caller, EventRef event) -{ - if(caller) - nlerror("You are using QtCarbon! Only QtCocoa supported, please upgrade Qt"); - - if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive()) - { - NL3D::IDriver *driver = dynamic_cast(Modules::objView().getDriver())->getDriver(); - if (driver) - { - cocoaProc proc = (cocoaProc)driver->getWindowProc(); - proc(driver, event); - } - } - - // return false to let Qt handle the event as well, - // else the widget would never get focus - return false; -} - -#elif defined(NL_OS_UNIX) - -typedef bool (*x11Proc)(NL3D::IDriver *drv, XEvent *e); - -bool CGraphicsViewport::x11Event(XEvent *event) -{ - if (Modules::objView().getDriver() && Modules::objView().getDriver()->isActive()) - { - NL3D::IDriver *driver = dynamic_cast(Modules::objView().getDriver())->getDriver(); - if (driver) - { - x11Proc proc = (x11Proc)driver->getWindowProc(); - proc(driver, event); - } - } - - // return false to let Qt handle the event as well, - // else the widget would never get focus - // TODO: test me please, i have no linux at hand (rti) - return false; -} -#endif - } /* namespace NLQT */ diff --git a/code/studio/src/plugins/object_viewer/graphics_viewport.h b/code/studio/src/plugins/object_viewer/graphics_viewport.h index 0c01fa1ad..9bbad9806 100644 --- a/code/studio/src/plugins/object_viewer/graphics_viewport.h +++ b/code/studio/src/plugins/object_viewer/graphics_viewport.h @@ -26,23 +26,14 @@ // STL includes // Qt includes -#include -#include +#include // NeL includes // Project includes - -/* TODO every platform should use QWidget */ -#if defined(NL_OS_WINDOWS) -typedef QWidget QNLWidget; -#elif defined(NL_OS_MAC) -typedef QWidget QNLWidget; -#elif defined(NL_OS_UNIX) -typedef QGLWidget QNLWidget; -#endif // NL_OS_UNIX - +class QWidget; class QAction; +class Nel3DWidget; namespace NLQT { @@ -51,25 +42,22 @@ namespace NLQT @class CGraphicsViewport @brief Responsible for interaction between Qt and NeL. Initializes CObjectViewer, CParticleEditor and CVegetableEditor subsystem. */ -class CGraphicsViewport : public QNLWidget, public NLMISC::IEventEmitter +class CGraphicsViewport : public QObject, public NLMISC::IEventEmitter { Q_OBJECT public: - CGraphicsViewport(QWidget *parent); + CGraphicsViewport(QObject *parent); virtual ~CGraphicsViewport(); - virtual QPaintEngine *paintEngine() const - { - return NULL; - } - void init(); void release(); QAction *createSaveScreenshotAction(QObject *parent); QAction *createSetBackgroundColor(QObject *parent); + QWidget* widget(); + private Q_SLOTS: void saveScreenshot(); void setBackgroundColor(); @@ -77,21 +65,15 @@ private Q_SLOTS: void submitEvents(NLMISC::CEventServer &server, bool allWindows) { } void emulateMouseRawMode(bool) { } -protected: - virtual void resizeEvent(QResizeEvent *resizeEvent); - -#if defined(NL_OS_WINDOWS) - virtual bool winEvent(MSG *message, long *result); -#elif defined(NL_OS_MAC) - virtual bool macEvent(EventHandlerCallRef caller, EventRef event); -#elif defined(NL_OS_UNIX) - virtual bool x11Event(XEvent *event); -#endif + void onResize( int width, int height ); private: CGraphicsViewport(const CGraphicsViewport &); CGraphicsViewport &operator=(const CGraphicsViewport &); + + Nel3DWidget *w; + }; /* class CGraphicsViewport */ } /* namespace NLQT */ diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index 864896ca1..10da56ffa 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -77,7 +77,7 @@ CMainWindow::CMainWindow(QWidget *parent) // create NeL viewport _GraphicsViewport = new CGraphicsViewport(this); - setCentralWidget(_GraphicsViewport); + setCentralWidget(_GraphicsViewport->widget()); setDockNestingEnabled(true); diff --git a/code/studio/src/plugins/object_viewer/object_viewer.cpp b/code/studio/src/plugins/object_viewer/object_viewer.cpp index 48c679455..2cf803d3d 100644 --- a/code/studio/src/plugins/object_viewer/object_viewer.cpp +++ b/code/studio/src/plugins/object_viewer/object_viewer.cpp @@ -70,20 +70,16 @@ CObjectViewer::~CObjectViewer() saveConfig(); } -void CObjectViewer::init(nlWindow wnd, uint16 w, uint16 h) +void CObjectViewer::init( NL3D::UDriver *driver ) { //H_AUTO2 nldebug("CObjectViewert::init"); // create the driver nlassert(!_Driver); - - _Driver = NL3D::UDriver::createDriver(0, _Direct3D, 0); + _Driver = driver; nlassert(_Driver); - // initialize the window with config file values - _Driver->setDisplay(wnd, NL3D::UDriver::CMode(w, h, 32)); - // Create a scene _Scene = _Driver->createScene(false); _Scene->setPolygonBalancingMode(NL3D::UScene::PolygonBalancingClamp); @@ -128,8 +124,8 @@ void CObjectViewer::init(nlWindow wnd, uint16 w, uint16 h) NL3D::CBloomEffect::instance().setDensityBloom(uint8(_BloomDensity)); NL3D::CBloomEffect::instance().setSquareBloom(_BloomSquare); - NL3D::CDriverUser *driver = dynamic_cast(Modules::objView().getDriver()); - _IDriver = driver->getDriver(); + NL3D::CDriverUser *udriver = dynamic_cast(Modules::objView().getDriver()); + _IDriver = udriver->getDriver(); NL3D::CSceneUser *scene = dynamic_cast(Modules::objView().getScene()); _CScene = &scene->getScene(); @@ -158,11 +154,8 @@ void CObjectViewer::release() // delete the light delete _Light; - // release driver - nlassert(_Driver); - _Driver->release(); - delete _Driver; _Driver = 0; + _IDriver = NULL; } void CObjectViewer::updateInput() diff --git a/code/studio/src/plugins/object_viewer/object_viewer.h b/code/studio/src/plugins/object_viewer/object_viewer.h index 5e978d7e0..e8cc7304e 100644 --- a/code/studio/src/plugins/object_viewer/object_viewer.h +++ b/code/studio/src/plugins/object_viewer/object_viewer.h @@ -78,7 +78,7 @@ public: /// @param wnd - handle window. /// @param w - width window. /// @param h - height window. - void init(nlWindow wnd, uint16 w, uint16 h); + void init( NL3D::UDriver *driver ); /// Release class. void release(); From bf16d2addf3ff1b3141c321fcad33cfd3d63ff72 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 01:15:39 +0200 Subject: [PATCH 067/220] Unload plugins when killing them. --- .../src/extension_system/plugin_spec.cpp | 34 +++++++++++++++---- .../studio/src/extension_system/plugin_spec.h | 7 +++- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/code/studio/src/extension_system/plugin_spec.cpp b/code/studio/src/extension_system/plugin_spec.cpp index 89f8046bb..97a08ea64 100644 --- a/code/studio/src/extension_system/plugin_spec.cpp +++ b/code/studio/src/extension_system/plugin_spec.cpp @@ -84,6 +84,13 @@ PluginSpec::PluginSpec() #else # error "You must define the lib suffix for your platform" #endif + loader = NULL; +} + +PluginSpec::~PluginSpec() +{ + delete loader; + loader = NULL; } QString PluginSpec::name() const @@ -292,6 +299,8 @@ bool PluginSpec::isEnabled() const bool PluginSpec::loadLibrary() { + nlassert( loader == NULL ); + if (m_hasError) return false; if (m_state != State::Resolved) @@ -301,14 +310,16 @@ bool PluginSpec::loadLibrary() return reportError(QCoreApplication::translate("PluginSpec", "Loading the library failed because state != Resolved")); } - QPluginLoader loader(m_filePath); - if (!loader.load()) - return reportError(loader.errorString()); + loader = new QPluginLoader( m_filePath ); + if (!loader->load()) + return reportError(loader->errorString()); - IPlugin *pluginObject = qobject_cast(loader.instance()); + IPlugin *pluginObject = qobject_cast(loader->instance()); if (!pluginObject) { - loader.unload(); + loader->unload(); + delete loader; + loader = NULL; return reportError(QCoreApplication::translate("PluginSpec", "Plugin is not valid (does not derive from IPlugin)")); } @@ -412,8 +423,17 @@ void PluginSpec::kill() { if (!m_plugin) return; - delete m_plugin; - m_plugin = 0; + + bool b = loader->unload(); + if( !b ) + { + nlinfo( "Plugin %s couldn't be unloaded.", this->m_name.toAscii().data() ); + } + + //delete m_plugin; + m_plugin = NULL; + delete loader; + loader = NULL; m_state = State::Deleted; } diff --git a/code/studio/src/extension_system/plugin_spec.h b/code/studio/src/extension_system/plugin_spec.h index 0ce74d004..d2abe1ef8 100644 --- a/code/studio/src/extension_system/plugin_spec.h +++ b/code/studio/src/extension_system/plugin_spec.h @@ -25,12 +25,15 @@ #include #include +class QPluginLoader; + namespace ExtensionSystem { class PluginSpec: public IPluginSpec { public: + ~PluginSpec(); virtual QString name() const; virtual QString version() const; virtual QString vendor() const; @@ -54,7 +57,7 @@ public: private: PluginSpec(); - + bool setFileName(const QString &fileName); bool setSpecFileName(const QString &specFileName); bool readSpec(); @@ -96,6 +99,8 @@ private: IPluginManager *m_pluginManager; QList m_dependencySpecs; + QPluginLoader *loader; + friend class PluginManager; }; From c4da612ba6933c8325db3c3a8560a63856f42119 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 01:20:37 +0200 Subject: [PATCH 068/220] Crashfix: If the status info widget isn't removed it miraclously crashes the app on shutdown. TODO: investigate why. --- code/studio/src/plugins/object_viewer/main_window.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/object_viewer/main_window.cpp b/code/studio/src/plugins/object_viewer/main_window.cpp index 10da56ffa..dc0c221cc 100644 --- a/code/studio/src/plugins/object_viewer/main_window.cpp +++ b/code/studio/src/plugins/object_viewer/main_window.cpp @@ -117,7 +117,7 @@ CMainWindow::CMainWindow(QWidget *parent) _statusBarTimer = new QTimer(this); connect(_statusBarTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar())); - _statusInfo = new QLabel(this); + _statusInfo = new QLabel(); _statusInfo->hide(); Core::ICore::instance()->mainWindow()->statusBar()->addPermanentWidget(_statusInfo); } @@ -137,6 +137,12 @@ CMainWindow::~CMainWindow() removeMenus(); + // If the status info widget isn't removed it miraclously crashes the application on shutdown... + // Somehow it's deleted while being owned by the status bar, then the status bar also tries to delete is... + Core::ICore::instance()->mainWindow()->statusBar()->removeWidget( _statusInfo ); + delete _statusInfo; + _statusInfo = NULL; + delete _AnimationDialog; delete _AnimationSetDialog; delete _SlotManagerDialog; From 470896d85ad74b1a8927661623530ac82578e5e9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:41:58 +0200 Subject: [PATCH 069/220] Wrong slash... --- code/studio/src/pm_watcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/pm_watcher.cpp b/code/studio/src/pm_watcher.cpp index 85c6d267b..0bbd28ca1 100644 --- a/code/studio/src/pm_watcher.cpp +++ b/code/studio/src/pm_watcher.cpp @@ -16,7 +16,7 @@ #include "pm_watcher.h" -#include "extension_system\iplugin_manager.h" +#include "extension_system/iplugin_manager.h" #include "splash_screen.h" namespace From 625dc4cc3ea2eff591e2040d79c81a475e2054bd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:51:53 +0200 Subject: [PATCH 070/220] Making master Dnk happy. --- code/studio/src/extension_system/iplugin_manager.h | 2 +- code/studio/src/extension_system/plugin_manager.cpp | 10 +++++----- code/studio/src/extension_system/plugin_manager.h | 4 ++-- code/studio/src/plugins/core/plugin_view_dialog.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/studio/src/extension_system/iplugin_manager.h b/code/studio/src/extension_system/iplugin_manager.h index efbf5ee2f..f60f45890 100644 --- a/code/studio/src/extension_system/iplugin_manager.h +++ b/code/studio/src/extension_system/iplugin_manager.h @@ -55,7 +55,7 @@ public: virtual void setPluginPaths(const QStringList &paths) = 0; virtual QList plugins() const = 0; - virtual bool loadPlugin( const char *plugin ) = 0; + virtual bool loadPlugin( const QString &plugin ) = 0; virtual bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ) = 0; // Settings diff --git a/code/studio/src/extension_system/plugin_manager.cpp b/code/studio/src/extension_system/plugin_manager.cpp index 508a4b81b..37cd85237 100644 --- a/code/studio/src/extension_system/plugin_manager.cpp +++ b/code/studio/src/extension_system/plugin_manager.cpp @@ -114,15 +114,15 @@ void PluginManager::loadPlugins() Q_EMIT pluginsChanged(); } -bool PluginManager::loadPluginSpec( const char *plugin ) +bool PluginManager::loadPluginSpec( const QString &plugin ) { - nlinfo( "Loading plugin spec %s", plugin ); + nlinfo( "Loading plugin spec %s", plugin.toUtf8().data() ); PluginSpec *spec = new PluginSpec; spec->m_pluginManager = this; if( !spec->setSpecFileName( plugin ) ) { - nlinfo( "Error loading plugin spec %s", plugin ); + nlinfo( "Error loading plugin spec %s", plugin.toUtf8().data() ); return false; } @@ -132,7 +132,7 @@ bool PluginManager::loadPluginSpec( const char *plugin ) return true; } -bool PluginManager::loadPlugin( const char *plugin ) +bool PluginManager::loadPlugin( const QString &plugin ) { if( !loadPluginSpec( plugin ) ) return false; @@ -141,7 +141,7 @@ bool PluginManager::loadPlugin( const char *plugin ) if( !spec->resolveDependencies( m_pluginSpecs ) ) { - nlinfo( "Error resolving dependencies for plugin spec %s", plugin ); + nlinfo( "Error resolving dependencies for plugin spec %s", plugin.toUtf8().data() ); return false; } diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 9b0d7a0dc..654c48c18 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,8 +51,8 @@ public: virtual QList plugins() const; QList loadQueue(); - bool loadPluginSpec( const char *plugin ); - bool loadPlugin( const char *plugin ); + bool loadPluginSpec( const QString &plugin ); + bool loadPlugin( const QString &plugin ); bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); void removePlugin( ExtensionSystem::IPluginSpec *plugin ); diff --git a/code/studio/src/plugins/core/plugin_view_dialog.cpp b/code/studio/src/plugins/core/plugin_view_dialog.cpp index c47a1c75d..cccc98509 100644 --- a/code/studio/src/plugins/core/plugin_view_dialog.cpp +++ b/code/studio/src/plugins/core/plugin_view_dialog.cpp @@ -156,7 +156,7 @@ void PluginView::onLoadClicked() } QApplication::setOverrideCursor( Qt::WaitCursor ); - bool success = m_pluginManager->loadPlugin( f.toAscii().data() ); + bool success = m_pluginManager->loadPlugin( f ); QApplication::setOverrideCursor( Qt::ArrowCursor ); if( !success ) From 8fb7c1c5f0bbc921a115d9465fe03f52999421ce Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:53:39 +0200 Subject: [PATCH 071/220] Why did I make these public in the first place? --- code/studio/src/extension_system/plugin_manager.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/studio/src/extension_system/plugin_manager.h b/code/studio/src/extension_system/plugin_manager.h index 654c48c18..ca31e1552 100644 --- a/code/studio/src/extension_system/plugin_manager.h +++ b/code/studio/src/extension_system/plugin_manager.h @@ -51,10 +51,9 @@ public: virtual QList plugins() const; QList loadQueue(); - bool loadPluginSpec( const QString &plugin ); bool loadPlugin( const QString &plugin ); bool unloadPlugin( ExtensionSystem::IPluginSpec *plugin ); - void removePlugin( ExtensionSystem::IPluginSpec *plugin ); + // Settings virtual void setSettings(QSettings *settings); @@ -63,6 +62,8 @@ public: void writeSettings(); private: + bool loadPluginSpec( const QString &plugin ); + void removePlugin( ExtensionSystem::IPluginSpec *plugin ); void setPluginState(PluginSpec *spec, int destState); void readPluginPaths(); bool loadQueue(PluginSpec *spec, QList &queue, QList &circularityCheckQueue); From 03e4c5ccd4ed75fe872db9b6c8a3fe73436b4a20 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 16:48:33 +0200 Subject: [PATCH 072/220] Added color picking support to the GUI Editor. TODO: change all the widget definitions. --- .../gui_editor/property_browser_ctrl.cpp | 59 ++++++++++++++++--- .../gui_editor/property_browser_ctrl.h | 3 +- .../gui_editor/widgets/CtrlTextButton.xml | 29 +++++---- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 82330bfaf..da4ff1499 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -22,6 +22,7 @@ #include "nel/gui/widget_manager.h" #include #include "widget_info_tree.h" +#include namespace GUIEditor { @@ -62,8 +63,8 @@ namespace GUIEditor void CPropBrowserCtrl::clear() { browser->clear(); - disconnect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); } void CPropBrowserCtrl::onSelectionChanged( std::string &id ) @@ -71,16 +72,16 @@ namespace GUIEditor if( browser == NULL ) return; - disconnect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); browser->clear(); CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( id ); if( e == NULL ) { - connect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); return; } @@ -90,11 +91,11 @@ namespace GUIEditor std::string n = e->getClassName(); setupProperties( n, e ); - connect( propertyMgr, SIGNAL( propertyChanged( QtProperty* ) ), - this, SLOT( onPropertyChanged( QtProperty* ) ) ); + connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); } - void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop ) + void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop, const QVariant &v ) { QString propName = prop->propertyName(); QString propValue = prop->valueText(); @@ -107,6 +108,14 @@ namespace GUIEditor propValue = p->value().toString(); } + if( v.type() == QVariant::Color ) + { + QColor c = v.value< QColor >(); + QString val = "%1 %2 %3 %4"; + val = val.arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() ); + propValue = val; + } + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) return; @@ -163,6 +172,38 @@ namespace GUIEditor NLMISC::fromString( element->getProperty( prop.propName ), value ); v = value; } + else + if( prop.propType == "color" ) + { + p = propertyMgr->addProperty( QVariant::Color, prop.propName.c_str() ); + + std::string s = element->getProperty( prop.propName ); + // Parse string into a QColor + QString qs = s.c_str(); + QStringList l = qs.split( " " ); + int r = l[ 0 ].toInt(); + int g = l[ 1 ].toInt(); + int b = l[ 2 ].toInt(); + int a = l[ 3 ].toInt(); + + QColor value; + value.setRed( r ); + value.setGreen( g ); + value.setBlue( b ); + value.setAlpha( a ); + v = value; + + + // Remove the subproperties + QList< QtProperty* > pl = p->subProperties(); + QListIterator< QtProperty* > itr( pl ); + while( itr.hasNext() ) + { + delete itr.next(); + } + pl.clear(); + + } if( p == NULL ) return; diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index 4c5ebce63..e126b86ea 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -26,6 +26,7 @@ class QtTreePropertyBrowser; class QtVariantPropertyManager; class QtProperty; +class QVariant; namespace NLGUI { @@ -53,7 +54,7 @@ namespace GUIEditor void onSelectionChanged( std::string &id ); private Q_SLOTS: - void onPropertyChanged( QtProperty *prop ); + void onPropertyChanged( QtProperty *prop, const QVariant &v ); private: void setupProperties( const std::string &type, const NLGUI::CInterfaceElement *element ); diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml index cacc45ccb..32541cc1f 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml @@ -2,7 +2,6 @@

CtrlTextButton CCtrlTextButton - text_button CtrlBaseButton false @@ -12,27 +11,27 @@ tx_normal string - but + tx_pushed string - but + tx_over string - but_over + hardtext string - text + wmargin int - 20 + 0 wmin @@ -61,32 +60,32 @@ text_color_normal - string + color 255 255 255 255 text_color_pushed - string + color 255 255 255 255 text_color_over - string + color 255 255 255 255 text_shadow_color_normal - string + color 0 0 0 255 text_shadow_color_pushed - string + color 0 0 0 255 text_shadow_color_over - string + color 0 0 0 255 @@ -116,7 +115,7 @@ color - string + color 255 255 255 255 @@ -136,7 +135,7 @@ shadow_color - string + color 0 0 0 255 @@ -152,7 +151,7 @@ line_maxw int - 200 + 0 multi_line_space From 8f6fb7ea99c8776d391f3b5d186762783950a050 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 19 Jun 2014 17:21:11 +0200 Subject: [PATCH 073/220] More widgets can use the color picker now. --- .../gui_editor/widgets/CtrlBaseButton.xml | 8 ++++---- .../plugins/gui_editor/widgets/CtrlButton.xml | 7 +++---- .../gui_editor/widgets/CtrlColPick.xml | 1 - .../plugins/gui_editor/widgets/CtrlScroll.xml | 1 - .../widgets/DBGroupSelectNumber.xml | 1 - .../plugins/gui_editor/widgets/DBViewBar.xml | 3 +-- .../plugins/gui_editor/widgets/DBViewBar3.xml | 13 ++++++------- .../gui_editor/widgets/DBViewDigit.xml | 5 ++--- .../gui_editor/widgets/DBViewNumber.xml | 3 +-- .../gui_editor/widgets/DBViewQuantity.xml | 7 +++---- .../plugins/gui_editor/widgets/GroupCell.xml | 2 +- .../gui_editor/widgets/GroupContainer.xml | 3 +-- .../gui_editor/widgets/GroupEditBox.xml | 1 - .../plugins/gui_editor/widgets/GroupFrame.xml | 2 +- .../plugins/gui_editor/widgets/GroupHTML.xml | 19 +++++++++---------- .../gui_editor/widgets/GroupHeader.xml | 1 - .../plugins/gui_editor/widgets/GroupList.xml | 3 +-- .../plugins/gui_editor/widgets/GroupMenu.xml | 15 +++++++-------- .../plugins/gui_editor/widgets/GroupModal.xml | 1 - .../gui_editor/widgets/GroupParagraph.xml | 2 +- .../gui_editor/widgets/GroupScrollText.xml | 1 - .../plugins/gui_editor/widgets/GroupTab.xml | 1 - .../plugins/gui_editor/widgets/GroupTable.xml | 3 +-- .../plugins/gui_editor/widgets/GroupTree.xml | 7 +++---- .../gui_editor/widgets/InterfaceGroup.xml | 1 - .../widgets/InterfaceGroupWheel.xml | 1 - .../plugins/gui_editor/widgets/ViewBitmap.xml | 1 - .../gui_editor/widgets/ViewBitmapCombo.xml | 1 - .../plugins/gui_editor/widgets/ViewText.xml | 9 ++++----- .../gui_editor/widgets/ViewTextFormated.xml | 1 - .../plugins/gui_editor/widgets/ViewTextID.xml | 1 - .../gui_editor/widgets/ViewTextIDFormated.xml | 1 - 32 files changed, 49 insertions(+), 77 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml index 42e2bdef1..4c7d915be 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml @@ -11,7 +11,7 @@ button_type string - push_button + toggle_button pushed @@ -30,17 +30,17 @@ color - string + color 255 255 255 255 col_pushed - string + color 255 255 255 255 col_over - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml index fb2514e7c..12b82e7f6 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlButton.xml @@ -2,7 +2,6 @@
CtrlButton CCtrlButton - button CtrlBaseButton false @@ -12,17 +11,17 @@ tx_normal string - log_but_r.tga + tx_pushed string - log_but_r.tga + tx_over string - log_but_over_r.tga + scale diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml index 6ac05fbcc..ea2ba6171 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlColPick.xml @@ -2,7 +2,6 @@
CtrlColPick CCtrlColPick - colpick CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml index a5c8dae1e..1ad970f31 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlScroll.xml @@ -2,7 +2,6 @@
CtrlScroll CCtrlScroll - scroll CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml index 63be51b5e..624ded887 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBGroupSelectNumber.xml @@ -2,7 +2,6 @@
DBGroupSelectNumber CDBGroupSelectNumber - select_number InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml index c7f2e488c..c7f644fa4 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewBar.xml @@ -2,7 +2,6 @@
DBViewBar CDBViewBar - bar ViewBitmap false @@ -26,7 +25,7 @@ color_negative - string + color 0 0 0 0 diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml index 9b12a637a..8295c5f30 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewBar3.xml @@ -2,7 +2,6 @@
DBViewBar3 CDBViewBar3 - bar3 ViewBitmap false @@ -41,32 +40,32 @@ color1 - string + color 255 255 255 255 color2 - string + color 255 255 255 255 color3 - string + color 255 255 255 255 color1_negative - string + color 0 0 0 0 color2_negative - string + color 0 0 0 0 color3_negative - string + color 0 0 0 0 diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml index 8a2a28831..0c12445f9 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewDigit.xml @@ -2,7 +2,6 @@
DBViewDigit CDBViewDigit - digit CtrlBase false @@ -12,7 +11,7 @@ value string - 0 + numdigit @@ -26,7 +25,7 @@ color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml index 95a43025e..c1861df61 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewNumber.xml @@ -2,7 +2,6 @@
DBViewNumber CDBViewNumber - text_number ViewText false @@ -12,7 +11,7 @@ value string - 0 + positive diff --git a/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml b/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml index 1b812bccf..c24379c96 100644 --- a/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml +++ b/code/studio/src/plugins/gui_editor/widgets/DBViewQuantity.xml @@ -2,7 +2,6 @@
DBViewQuantity CDBViewQuantity - text_quantity ViewText false @@ -12,17 +11,17 @@ value string - 0 + valuemax string - 100 + emptytext string - empty text + diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml b/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml index 8f8592771..ad0ae6e02 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupCell.xml @@ -30,7 +30,7 @@ bgcolor - string + color 0 0 0 0 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml index bdbf9931a..b374bca19 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml @@ -2,7 +2,6 @@
GroupContainer CGroupContainer - container InterfaceGroup false @@ -46,7 +45,7 @@ header_color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml b/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml index 603af6c04..31ca205c7 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupEditBox.xml @@ -2,7 +2,6 @@
GroupEditBox CGroupEditBox - edit_box InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml b/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml index f414e67e7..c7ac89fa2 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupFrame.xml @@ -15,7 +15,7 @@ color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml index b76fe4cd4..5f0521be8 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupHTML.xml @@ -2,7 +2,6 @@
GroupHTML CGroupHTML - html GroupScrollText false @@ -21,47 +20,47 @@ background_color - string + color 0 0 0 255 error_color - string + color 255 0 0 255 link_color - string + color 0 0 255 255 h1_color - string + color 255 255 255 255 h2_color - string + color 255 255 255 255 h3_color - string + color 255 255 255 255 h4_color - string + color 255 255 255 255 h5_color - string + color 255 255 255 255 h6_color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml b/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml index bcb517c66..cc96fd742 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupHeader.xml @@ -2,7 +2,6 @@
GroupHeader CGroupHeader - header GroupList false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupList.xml b/code/studio/src/plugins/gui_editor/widgets/GroupList.xml index 1858cd5b3..3ca2db95c 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupList.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupList.xml @@ -2,7 +2,6 @@
GroupList CGroupList - list InterfaceGroup false @@ -41,7 +40,7 @@ col_over - string + color 255 255 255 32 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml b/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml index 4739f0352..cdd42ba95 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupMenu.xml @@ -2,7 +2,6 @@
GroupMenu CGroupMenu - menu GroupModal false @@ -16,7 +15,7 @@ color - string + color 255 255 255 255 @@ -26,32 +25,32 @@ shadow_color - string + color 0 0 0 255 color_over - string + color 255 255 255 255 shadow_color_over - string + color 0 0 0 255 highlight_over - string + color 128 0 0 255 color_grayed - string + color 128 128 128 255 shadow_color_grayed - string + color 0 0 0 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml b/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml index afc5005c8..034e3025e 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupModal.xml @@ -2,7 +2,6 @@
GroupModal CGroupModal - modal GroupFrame false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml b/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml index f05806757..e561e8c5f 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupParagraph.xml @@ -30,7 +30,7 @@ col_over - string + color 255 255 255 32 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml b/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml index 8cefb8df2..95719398d 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupScrollText.xml @@ -2,7 +2,6 @@
GroupScrollText CGroupScrollText - scroll_text InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml index 69db79466..df148a0a3 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupTab.xml @@ -2,7 +2,6 @@
GroupTab CGroupTab - tab InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml index 9c2240adc..9fa957741 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupTable.xml @@ -2,7 +2,6 @@
GroupTable CGroupTable - table InterfaceGroup false @@ -26,7 +25,7 @@ bgcolor - string + color 0 0 0 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml b/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml index 6bd10ad9f..73b1dea3b 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupTree.xml @@ -2,7 +2,6 @@
GroupTree CGroupTree - tree InterfaceGroup false @@ -11,17 +10,17 @@ col_over - string + color 255 255 255 128 col_select - string + color 255 128 128 128 col_over_back - string + color 64 64 64 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml index c9a8c1546..b9e99d336 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml @@ -2,7 +2,6 @@
InterfaceGroup CInterfaceGroup - interface_group CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml index 51590ee33..62d67cc0a 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml @@ -2,7 +2,6 @@
InterfaceGroupWheel CInterfaceGroupWheel - group_wheel InterfaceGroup false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index 8b931f78b..9da967b5a 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -2,7 +2,6 @@
ViewBitmap CViewBitmap - bitmap CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml index 190143be5..0b55f6932 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml @@ -2,7 +2,6 @@
ViewBitmapCombo CViewBitmapCombo - bitmap_combo CtrlBase false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml index 9490a1eee..fc4d30688 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml @@ -2,7 +2,6 @@
ViewText CViewText - text InterfaceElement false @@ -11,7 +10,7 @@ color - string + color 255 255 255 255 @@ -31,7 +30,7 @@ shadow_color - string + color 0 0 0 255 @@ -47,7 +46,7 @@ line_maxw int - 100 + 0 multi_line_space @@ -102,7 +101,7 @@ hardtext string - some text + hardtext_format diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml index c5749ca9c..cabd081f0 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewTextFormated.xml @@ -2,7 +2,6 @@
ViewTextFormated CViewTextFormated - text_formated ViewText false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml index b3edc86ab..52e010ec6 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewTextID.xml @@ -2,7 +2,6 @@
ViewTextID CViewTextID - text_id ViewText false diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml b/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml index 3ac6c7962..af8dd54eb 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewTextIDFormated.xml @@ -2,7 +2,6 @@
ViewTextIDFormated CViewTextIDFormated - text_id_formated ViewTextID false From 775278d9de1c68173aec4b0beaff1f22f784d596 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 19 Jun 2014 18:40:50 +0200 Subject: [PATCH 074/220] As Object Viewer no longer uses the QtOpenGL widget this is not needed. --- code/studio/src/plugins/object_viewer/graphics_viewport.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp index 8cf6f3f60..0cec0be10 100644 --- a/code/studio/src/plugins/object_viewer/graphics_viewport.cpp +++ b/code/studio/src/plugins/object_viewer/graphics_viewport.cpp @@ -66,10 +66,6 @@ void CGraphicsViewport::init() //H_AUTO2 nldebug("CGraphicsViewport::init"); -#if defined(NL_OS_UNIX) && !defined(NL_OS_MAC) - makeCurrent(); -#endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC) - w->init(); Modules::objView().init( w->getDriver() ); Modules::psEdit().init(); From 4a8bd7c7c141388e86500451bb9e5284b20a1a0d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 15:09:13 +0200 Subject: [PATCH 075/220] Line endings... --- code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index da4ff1499..1118a86bc 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -110,7 +110,7 @@ namespace GUIEditor if( v.type() == QVariant::Color ) { - QColor c = v.value< QColor >(); + QColor c = v.value< QColor >(); QString val = "%1 %2 %3 %4"; val = val.arg( c.red() ).arg( c.green() ).arg( c.blue() ).arg( c.alpha() ); propValue = val; From 701b7f29db486e4f986d593b0b6566f828c54ea2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 16:22:07 +0200 Subject: [PATCH 076/220] Button types can now be set using an enum property editor. --- .../gui_editor/property_browser_ctrl.cpp | 87 ++++++++++++++++++- .../gui_editor/property_browser_ctrl.h | 4 + .../gui_editor/widgets/CtrlBaseButton.xml | 2 +- 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 1118a86bc..77872d8b3 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -17,7 +17,9 @@ #include "property_browser_ctrl.h" #include "../../3rdparty/qtpropertybrowser/QtVariantPropertyManager" +#include "../../3rdparty/qtpropertybrowser/QtEnumPropertyManager" #include "../../3rdparty/qtpropertybrowser/QtTreePropertyBrowser" +#include "../../3rdparty/qtpropertybrowser/QtEnumEditorFactory" #include "nel/gui/interface_group.h" #include "nel/gui/widget_manager.h" #include @@ -26,16 +28,27 @@ namespace GUIEditor { + enum NELButtonTypes + { + BUTTON_TYPE_PUSH = 0, + BUTTON_TYPE_TOGGLE = 1, + BUTTON_TYPE_RADIO = 2 + }; + CPropBrowserCtrl::CPropBrowserCtrl() { browser = NULL; propertyMgr = new QtVariantPropertyManager; + enumMgr = new QtEnumPropertyManager; } CPropBrowserCtrl::~CPropBrowserCtrl() { + delete enumMgr; + enumMgr = NULL; delete propertyMgr; propertyMgr = NULL; + browser = NULL; } @@ -65,6 +78,9 @@ namespace GUIEditor browser->clear(); disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + + disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); } void CPropBrowserCtrl::onSelectionChanged( std::string &id ) @@ -74,6 +90,8 @@ namespace GUIEditor disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); browser->clear(); @@ -82,6 +100,8 @@ namespace GUIEditor { connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); return; } @@ -93,6 +113,8 @@ namespace GUIEditor setupProperties( n, e ); connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); } void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop, const QVariant &v ) @@ -107,7 +129,7 @@ namespace GUIEditor if( p != NULL ) propValue = p->value().toString(); } - + if( v.type() == QVariant::Color ) { QColor c = v.value< QColor >(); @@ -128,6 +150,32 @@ namespace GUIEditor e->setActive( active ); } + void CPropBrowserCtrl::onEnumPropertyChanged( QtProperty *prop, int value ) + { + QString propName = prop->propertyName(); + + if( propName == "button_type" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + if( ( value < 0 ) || ( value > 2 ) ) + return; + + std::string v; + + switch( value ) + { + case BUTTON_TYPE_PUSH: v = "push_button"; break; + case BUTTON_TYPE_TOGGLE: v = "toggle_button"; break; + case BUTTON_TYPE_RADIO: v = "radio_button"; break; + } + + e->setProperty( propName.toUtf8().constData(), v ); + } + } + void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) { std::map< std::string, SWidgetInfo >::iterator itr = widgetInfo.find( type ); @@ -144,6 +192,9 @@ namespace GUIEditor QtVariantEditorFactory *factory = new QtVariantEditorFactory; browser->setFactoryForManager( propertyMgr, factory ); + + QtEnumEditorFactory *efactory = new QtEnumEditorFactory; + browser->setFactoryForManager( enumMgr, efactory ); } void CPropBrowserCtrl::setupProperty( const SPropEntry &prop, const CInterfaceElement *element ) @@ -151,6 +202,40 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "button_type" ) + { + std::string btype = element->getProperty( prop.propName ); + if( btype.empty() ) + return; + + QStringList enums; + enums.push_back( "push_button" ); + enums.push_back( "toggle_button" ); + enums.push_back( "radio_button" ); + + int e = -1; + if( btype == "push_button" ) + e = BUTTON_TYPE_PUSH; + else + if( btype == "toggle_button" ) + e = BUTTON_TYPE_TOGGLE; + else + if( btype == "radio_button" ) + e = BUTTON_TYPE_RADIO; + + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index e126b86ea..648463bc6 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -25,6 +25,7 @@ class QtTreePropertyBrowser; class QtVariantPropertyManager; +class QtEnumPropertyManager; class QtProperty; class QVariant; @@ -55,6 +56,7 @@ namespace GUIEditor private Q_SLOTS: void onPropertyChanged( QtProperty *prop, const QVariant &v ); + void onEnumPropertyChanged( QtProperty *prop, int value ); private: void setupProperties( const std::string &type, const NLGUI::CInterfaceElement *element ); @@ -62,6 +64,8 @@ namespace GUIEditor QtTreePropertyBrowser *browser; QtVariantPropertyManager *propertyMgr; + QtEnumPropertyManager *enumMgr; + std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; }; diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml index 4c7d915be..72e362556 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml @@ -10,7 +10,7 @@ button_type - string + button_type toggle_button From 2c900d20e5214fe05dad1e927e64e0db4cddfb8e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 16:26:10 +0200 Subject: [PATCH 077/220] A little refactoring --- .../gui_editor/property_browser_ctrl.cpp | 39 ++++++++++--------- .../gui_editor/property_browser_ctrl.h | 3 ++ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 77872d8b3..c27d3ca6c 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -75,12 +75,8 @@ namespace GUIEditor void CPropBrowserCtrl::clear() { + disablePropertyWatchers(); browser->clear(); - disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - - disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); } void CPropBrowserCtrl::onSelectionChanged( std::string &id ) @@ -88,21 +84,13 @@ namespace GUIEditor if( browser == NULL ) return; - disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); - + disablePropertyWatchers(); browser->clear(); CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( id ); if( e == NULL ) { - connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); - + enablePropertyWatchers(); return; } @@ -111,10 +99,7 @@ namespace GUIEditor std::string n = e->getClassName(); setupProperties( n, e ); - connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), - this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); - connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), - this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + enablePropertyWatchers(); } void CPropBrowserCtrl::onPropertyChanged( QtProperty *prop, const QVariant &v ) @@ -176,6 +161,22 @@ namespace GUIEditor } } + void CPropBrowserCtrl::enablePropertyWatchers() + { + connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + } + + void CPropBrowserCtrl::disablePropertyWatchers() + { + disconnect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), + this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); + disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + } + void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) { std::map< std::string, SWidgetInfo >::iterator itr = widgetInfo.find( type ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index 648463bc6..f8d839bd6 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -59,6 +59,9 @@ namespace GUIEditor void onEnumPropertyChanged( QtProperty *prop, int value ); private: + void enablePropertyWatchers(); + void disablePropertyWatchers(); + void setupProperties( const std::string &type, const NLGUI::CInterfaceElement *element ); void setupProperty( const SPropEntry &prop, const NLGUI::CInterfaceElement *element ); From d506f6bc22cc677b846610fd992337818bfab61d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 17:07:27 +0200 Subject: [PATCH 078/220] Text justification can now be set using an enum property editor. --- .../gui_editor/property_browser_ctrl.cpp | 74 +++++++++++++++++-- .../gui_editor/widgets/CtrlTextButton.xml | 2 +- .../plugins/gui_editor/widgets/ViewText.xml | 2 +- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index c27d3ca6c..6408703f4 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -35,6 +35,13 @@ namespace GUIEditor BUTTON_TYPE_RADIO = 2 }; + enum NELTxtJustification + { + TEXT_CLIPWORD, + TEXT_DONTCLIPWORD, + TEXT_JUSTIFIED + }; + CPropBrowserCtrl::CPropBrowserCtrl() { browser = NULL; @@ -145,7 +152,7 @@ namespace GUIEditor if( e == NULL ) return; - if( ( value < 0 ) || ( value > 2 ) ) + if( ( value < BUTTON_TYPE_PUSH ) || ( value > BUTTON_TYPE_RADIO ) ) return; std::string v; @@ -157,6 +164,26 @@ namespace GUIEditor case BUTTON_TYPE_RADIO: v = "radio_button"; break; } + e->setProperty( propName.toUtf8().constData(), v ); + } + else + if( propName == "justification" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + if( ( value < TEXT_CLIPWORD ) || ( value > TEXT_JUSTIFIED ) ) + return; + + std::string v; + switch( value ) + { + case TEXT_CLIPWORD: v = "clip_word"; break; + case TEXT_DONTCLIPWORD: v = "dont_clip_word"; break; + case TEXT_JUSTIFIED: v = "justified"; break; + } + e->setProperty( propName.toUtf8().constData(), v ); } } @@ -209,11 +236,6 @@ namespace GUIEditor if( btype.empty() ) return; - QStringList enums; - enums.push_back( "push_button" ); - enums.push_back( "toggle_button" ); - enums.push_back( "radio_button" ); - int e = -1; if( btype == "push_button" ) e = BUTTON_TYPE_PUSH; @@ -231,12 +253,52 @@ namespace GUIEditor if( pp == NULL ) return; + QStringList enums; + enums.push_back( "push_button" ); + enums.push_back( "toggle_button" ); + enums.push_back( "radio_button" ); + enumMgr->setEnumNames( pp, enums ); enumMgr->setValue( pp, e ); browser->addProperty( pp ); return; } else + if( prop.propType == "text_justification" ) + { + std::string j = element->getProperty( prop.propName ); + if( j.empty() ) + return; + + int e = -1; + if( j == "clip_word" ) + e = TEXT_CLIPWORD; + else + if( j == "dont_clip_word" ) + e = TEXT_DONTCLIPWORD; + else + if( j == "justified" ) + e = TEXT_JUSTIFIED; + + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "clip_word" ); + enums.push_back( "dont_clip_word" ); + enums.push_back( "justified" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml index 32541cc1f..4553af272 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml @@ -145,7 +145,7 @@ justification - string + text_justification dont_clip_word diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml index fc4d30688..415c3167e 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewText.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewText.xml @@ -40,7 +40,7 @@ justification - string + text_justification dont_clip_word From 87778c86c92682aef45bfde89f761ce1f2ff398e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Jun 2014 18:25:14 +0200 Subject: [PATCH 079/220] Posref can now be set as an enum, instead of a string in the property editor. --- code/nel/src/gui/interface_element.cpp | 16 ++- .../gui_editor/property_browser_ctrl.cpp | 123 ++++++++++++++++++ .../gui_editor/widgets/InterfaceElement.xml | 13 +- 3 files changed, 145 insertions(+), 7 deletions(-) diff --git a/code/nel/src/gui/interface_element.cpp b/code/nel/src/gui/interface_element.cpp index 15f9cf812..0225d2797 100644 --- a/code/nel/src/gui/interface_element.cpp +++ b/code/nel/src/gui/interface_element.cpp @@ -130,12 +130,17 @@ namespace NLGUI if( name == "posref" ) { std::string posref; - posref = HotSpotToString( getParentPosRef() ); - posref += " "; posref += HotSpotToString( getPosRef() ); return posref; } else + if( name == "parentposref" ) + { + std::string parentPosRef; + parentPosRef = HotSpotToString( getParentPosRef() ); + return parentPosRef; + } + else if( name == "sizeref" ) { return getSizeRefAsString( _SizeRef, _SizeDivW, _SizeDivH ); @@ -221,10 +226,15 @@ namespace NLGUI else if( name == "posref" ) { - convertHotSpotCouple( value.c_str(), _ParentPosRef, _PosRef ); + convertHotSpot( value.c_str() ); return; } else + if( name == "parentposref" ) + { + convertHotSpot( value.c_str() ); + } + else if( name == "sizeref" ) { parseSizeRef( value.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 6408703f4..d5feba8f7 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -26,6 +26,83 @@ #include "widget_info_tree.h" #include +namespace +{ + + class NelPosRef + { + public: + + enum NELPosRef + { + POSREF_BL = 0, + POSREF_BM = 1, + POSREF_BR = 2, + POSREF_ML = 3, + POSREF_MM = 4, + POSREF_MR = 5, + POSREF_TL = 6, + POSREF_TM = 7, + POSREF_TR = 8 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "BL" ) + r = POSREF_BL; + else + if( s == "BM" ) + r = POSREF_BM; + else + if( s == "BR" ) + r = POSREF_BR; + else + if( s == "ML" ) + r = POSREF_ML; + else + if( s == "MM" ) + r = POSREF_MM; + else + if( s == "MR" ) + r = POSREF_MR; + else + if( s == "TL" ) + r = POSREF_TL; + else + if( s == "TM" ) + r = POSREF_TM; + else + if( s == "TR" ) + r = POSREF_TR; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case POSREF_BL: v = "BL"; break; + case POSREF_BM: v = "BM"; break; + case POSREF_BR: v = "BR"; break; + case POSREF_ML: v = "ML"; break; + case POSREF_MM: v = "MM"; break; + case POSREF_MR: v = "MR"; break; + case POSREF_TL: v = "TL"; break; + case POSREF_TM: v = "TM"; break; + case POSREF_TR: v = "TR"; break; + } + + return v; + } + }; + +} + namespace GUIEditor { enum NELButtonTypes @@ -184,6 +261,19 @@ namespace GUIEditor case TEXT_JUSTIFIED: v = "justified"; break; } + e->setProperty( propName.toUtf8().constData(), v ); + } + else + if( ( propName == "posref" ) || ( propName == "parentposref" ) ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelPosRef::toString( value ); + if( v.empty() ) + return; + e->setProperty( propName.toUtf8().constData(), v ); } } @@ -299,6 +389,39 @@ namespace GUIEditor return; } else + if( prop.propType == "posref" ) + { + std::string j = element->getProperty( prop.propName ); + if( j.empty() ) + return; + + int e = -1; + e = NelPosRef::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "BL" ); + enums.push_back( "BM" ); + enums.push_back( "BR" ); + enums.push_back( "ML" ); + enums.push_back( "MM" ); + enums.push_back( "MR" ); + enums.push_back( "TL" ); + enums.push_back( "TM" ); + enums.push_back( "TR" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml index 856480dc7..b16de9ed0 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceElement.xml @@ -36,12 +36,17 @@ h int 0 - + posref - string - BL BL - + posref + BL + + + parentposref + posref + BL + sizeref string From 762139cc1ee4f4e39a7daae3fa564d6982ecab2f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Jun 2014 22:55:10 +0200 Subject: [PATCH 080/220] Some refactoring. --- .../gui_editor/property_browser_ctrl.cpp | 145 ++++++++++++------ 1 file changed, 95 insertions(+), 50 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index d5feba8f7..6eef4e2f6 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -101,23 +101,97 @@ namespace } }; + + class NelButtonType + { + public: + + enum NELButtonTypes + { + BUTTON_TYPE_PUSH = 0, + BUTTON_TYPE_TOGGLE = 1, + BUTTON_TYPE_RADIO = 2 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "push_button" ) + r = BUTTON_TYPE_PUSH; + else + if( s == "toggle_button" ) + r = BUTTON_TYPE_TOGGLE; + else + if( s == "radio_button" ) + r = BUTTON_TYPE_RADIO; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case BUTTON_TYPE_PUSH: v = "push_button"; break; + case BUTTON_TYPE_TOGGLE: v = "toggle_button"; break; + case BUTTON_TYPE_RADIO: v = "radio_button"; break; + } + + return v; + } + + }; + + class NelTxtJustification + { + public: + + enum NELTxtJustification + { + TEXT_CLIPWORD, + TEXT_DONTCLIPWORD, + TEXT_JUSTIFIED + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "clip_word" ) + r = TEXT_CLIPWORD; + else + if( s == "dont_clip_word" ) + r = TEXT_DONTCLIPWORD; + else + if( s == "justified" ) + r = TEXT_JUSTIFIED; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case TEXT_CLIPWORD: v = "clip_word"; break; + case TEXT_DONTCLIPWORD: v = "dont_clip_word"; break; + case TEXT_JUSTIFIED: v = "justified"; break; + } + + return v; + } + + }; + } namespace GUIEditor { - enum NELButtonTypes - { - BUTTON_TYPE_PUSH = 0, - BUTTON_TYPE_TOGGLE = 1, - BUTTON_TYPE_RADIO = 2 - }; - - enum NELTxtJustification - { - TEXT_CLIPWORD, - TEXT_DONTCLIPWORD, - TEXT_JUSTIFIED - }; CPropBrowserCtrl::CPropBrowserCtrl() { @@ -229,17 +303,10 @@ namespace GUIEditor if( e == NULL ) return; - if( ( value < BUTTON_TYPE_PUSH ) || ( value > BUTTON_TYPE_RADIO ) ) - return; - std::string v; - - switch( value ) - { - case BUTTON_TYPE_PUSH: v = "push_button"; break; - case BUTTON_TYPE_TOGGLE: v = "toggle_button"; break; - case BUTTON_TYPE_RADIO: v = "radio_button"; break; - } + v = NelButtonType::toString( value ); + if( v.empty() ) + return; e->setProperty( propName.toUtf8().constData(), v ); } @@ -250,16 +317,10 @@ namespace GUIEditor if( e == NULL ) return; - if( ( value < TEXT_CLIPWORD ) || ( value > TEXT_JUSTIFIED ) ) - return; - std::string v; - switch( value ) - { - case TEXT_CLIPWORD: v = "clip_word"; break; - case TEXT_DONTCLIPWORD: v = "dont_clip_word"; break; - case TEXT_JUSTIFIED: v = "justified"; break; - } + v = NelTxtJustification::toString( value ); + if( v.empty() ) + return; e->setProperty( propName.toUtf8().constData(), v ); } @@ -327,15 +388,7 @@ namespace GUIEditor return; int e = -1; - if( btype == "push_button" ) - e = BUTTON_TYPE_PUSH; - else - if( btype == "toggle_button" ) - e = BUTTON_TYPE_TOGGLE; - else - if( btype == "radio_button" ) - e = BUTTON_TYPE_RADIO; - + e = NelButtonType::fromString( btype ); if( e == -1 ) return; @@ -361,15 +414,7 @@ namespace GUIEditor return; int e = -1; - if( j == "clip_word" ) - e = TEXT_CLIPWORD; - else - if( j == "dont_clip_word" ) - e = TEXT_DONTCLIPWORD; - else - if( j == "justified" ) - e = TEXT_JUSTIFIED; - + e = NelTxtJustification::fromString( j ); if( e == -1 ) return; From afd1d96363f05a091c66892046ae257c2e66a03f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:07:44 +0200 Subject: [PATCH 081/220] text posref is now an enum too. --- code/nel/src/gui/ctrl_text_button.cpp | 20 +++++++++++++------ .../gui_editor/property_browser_ctrl.cpp | 6 +++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/code/nel/src/gui/ctrl_text_button.cpp b/code/nel/src/gui/ctrl_text_button.cpp index cdf006a51..d3a0f6765 100644 --- a/code/nel/src/gui/ctrl_text_button.cpp +++ b/code/nel/src/gui/ctrl_text_button.cpp @@ -149,11 +149,16 @@ namespace NLGUI } else if( name == "text_posref" ) + { + std::string pr; + pr = CInterfaceElement::HotSpotToString( _TextPosRef ); + return pr; + } + else + if( name == "text_parent_posref" ) { std::string pr; pr = CInterfaceElement::HotSpotToString( _TextParentPosRef ); - pr += " "; - pr += CInterfaceElement::HotSpotToString( _TextPosRef ); return pr; } else @@ -324,10 +329,13 @@ namespace NLGUI else if( name == "text_posref" ) { - THotSpot parent, posref; - CInterfaceElement::convertHotSpotCouple( value.c_str(), parent, posref ); - _TextPosRef = posref; - _TextParentPosRef = parent; + _TextPosRef = convertHotSpot( value.c_str() ); + return; + } + else + if( name == "text_parent_posref" ) + { + _TextParentPosRef = convertHotSpot( value.c_str() ); return; } else diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 6eef4e2f6..3e25cbab8 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -325,7 +325,11 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } else - if( ( propName == "posref" ) || ( propName == "parentposref" ) ) + if( ( propName == "posref" ) || + ( propName == "parentposref" ) || + ( propName == "text_posref" ) || + ( propName == "text_parent_posref" ) + ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) From 78c83d83b01052932c638471a02e3d94de268794 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:24:31 +0200 Subject: [PATCH 082/220] The proper enum type is now determined by type not name. --- .../gui_editor/property_browser_ctrl.cpp | 23 +++++++++++++------ .../gui_editor/property_browser_ctrl.h | 1 + 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 3e25cbab8..7effe6765 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -296,8 +296,18 @@ namespace GUIEditor void CPropBrowserCtrl::onEnumPropertyChanged( QtProperty *prop, int value ) { QString propName = prop->propertyName(); + std::string n = propName.toUtf8().constData(); - if( propName == "button_type" ) + // Try to find the type for this property + std::map< std::string, std::string >::const_iterator itr = + nameToType.find( n ); + // Not found :( + if( itr == nameToType.end() ) + return; + std::string type = itr->second; + + + if( type == "button_type" ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) @@ -311,7 +321,7 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } else - if( propName == "justification" ) + if( type == "text_justification" ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) @@ -325,11 +335,7 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } else - if( ( propName == "posref" ) || - ( propName == "parentposref" ) || - ( propName == "text_posref" ) || - ( propName == "text_parent_posref" ) - ) + if( type == "posref" ) { CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); if( e == NULL ) @@ -366,10 +372,13 @@ namespace GUIEditor return; SWidgetInfo &w = itr->second; + nameToType.clear(); + std::vector< SPropEntry >::const_iterator pItr; for( pItr = w.props.begin(); pItr != w.props.end(); ++pItr ) { const SPropEntry &prop = *pItr; + nameToType[ prop.propName ] = prop.propType; setupProperty( prop, element ); } diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index f8d839bd6..f53648f79 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -71,6 +71,7 @@ namespace GUIEditor std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; + std::map< std::string, std::string > nameToType; }; } From 6dd11d7fad6b1f8165028c996f1f4db202c646a6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:47:29 +0200 Subject: [PATCH 083/220] Got rid of a memleak. --- .../gui_editor/property_browser_ctrl.cpp | 22 ++++++++++++++----- .../gui_editor/property_browser_ctrl.h | 5 +++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 7effe6765..4a839cbee 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -198,6 +198,9 @@ namespace GUIEditor browser = NULL; propertyMgr = new QtVariantPropertyManager; enumMgr = new QtEnumPropertyManager; + + variantFactory = new QtVariantEditorFactory; + enumFactory = new QtEnumEditorFactory; } CPropBrowserCtrl::~CPropBrowserCtrl() @@ -207,6 +210,11 @@ namespace GUIEditor delete propertyMgr; propertyMgr = NULL; + delete variantFactory; + variantFactory = NULL; + delete enumFactory; + enumFactory = NULL; + browser = NULL; } @@ -257,6 +265,14 @@ namespace GUIEditor std::string n = e->getClassName(); setupProperties( n, e ); + + + // Need to set these up every time, otherwise the editors won't work + // probably the clear() method clears them too... + browser->setFactoryForManager( propertyMgr, variantFactory ); + browser->setFactoryForManager( enumMgr, enumFactory ); + + enablePropertyWatchers(); } @@ -381,12 +397,6 @@ namespace GUIEditor nameToType[ prop.propName ] = prop.propType; setupProperty( prop, element ); } - - QtVariantEditorFactory *factory = new QtVariantEditorFactory; - browser->setFactoryForManager( propertyMgr, factory ); - - QtEnumEditorFactory *efactory = new QtEnumEditorFactory; - browser->setFactoryForManager( enumMgr, efactory ); } void CPropBrowserCtrl::setupProperty( const SPropEntry &prop, const CInterfaceElement *element ) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index f53648f79..efb785d9b 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -26,6 +26,8 @@ class QtTreePropertyBrowser; class QtVariantPropertyManager; class QtEnumPropertyManager; +class QtVariantEditorFactory; +class QtEnumEditorFactory; class QtProperty; class QVariant; @@ -69,6 +71,9 @@ namespace GUIEditor QtVariantPropertyManager *propertyMgr; QtEnumPropertyManager *enumMgr; + QtVariantEditorFactory *variantFactory; + QtEnumEditorFactory *enumFactory; + std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; std::map< std::string, std::string > nameToType; From 9690392ec66c1ca4195f8aaf7254340e619995e0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:49:31 +0200 Subject: [PATCH 084/220] Forgot the widget settings... --- .../plugins/gui_editor/widgets/CtrlTextButton.xml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml index 4553af272..ca66dbd62 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlTextButton.xml @@ -52,12 +52,17 @@ text_underlined bool false - - + + text_posref - string - MM MM - + posref + MM + + + text_parent_posref + posref + MM + text_color_normal color From 5deea1a13b21f3a4a551828c443b62da12b49662 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 01:44:06 +0200 Subject: [PATCH 085/220] Tooltip posrefs are now enums in the GUI Editor. --- code/nel/include/nel/gui/ctrl_base.h | 2 + code/nel/src/gui/ctrl_base.cpp | 115 +++++++++--- .../gui_editor/property_browser_ctrl.cpp | 170 ++++++++++++++++++ .../gui_editor/property_browser_ctrl.h | 2 + .../plugins/gui_editor/widgets/CtrlBase.xml | 20 ++- 5 files changed, 280 insertions(+), 29 deletions(-) diff --git a/code/nel/include/nel/gui/ctrl_base.h b/code/nel/include/nel/gui/ctrl_base.h index 28eeb2cd0..71e6cad56 100644 --- a/code/nel/include/nel/gui/ctrl_base.h +++ b/code/nel/include/nel/gui/ctrl_base.h @@ -171,7 +171,9 @@ namespace NLGUI THotSpot _ToolTipPosRefAlt : 6; protected: void convertTooltipHotSpot(const char *prop, THotSpot &parentHS, THotSpot &childHS); + void convertTooltipHotSpot(const char *prop, THotSpot &HS ); static std::string TooltipHotSpotToString( THotSpot parent, THotSpot child ); + static std::string TooltipHotSpotToString( THotSpot HS ); void mapAHString( const std::string &key, const std::string &value ); std::string getAHString( const std::string &key ) const; diff --git a/code/nel/src/gui/ctrl_base.cpp b/code/nel/src/gui/ctrl_base.cpp index f0a2c2f89..98cda02f4 100644 --- a/code/nel/src/gui/ctrl_base.cpp +++ b/code/nel/src/gui/ctrl_base.cpp @@ -220,28 +220,22 @@ namespace NLGUI else if( name == "tooltip_posref" ) { - std::string s; - if( ( _ToolTipParentPosRef == Hotspot_TTAuto ) && ( _ToolTipPosRef == Hotspot_TTAuto ) ) - return "auto"; - else{ - s = CInterfaceElement::HotSpotToString( _ToolTipParentPosRef ); - s += " "; - s += CInterfaceElement::HotSpotToString( _ToolTipPosRef ); - return s; - } + return TooltipHotSpotToString( _ToolTipPosRef ); + } + else + if( name == "tooltip_parent_posref" ) + { + return TooltipHotSpotToString( _ToolTipParentPosRef ); } else if( name == "tooltip_posref_alt" ) { - std::string s; - if( ( _ToolTipParentPosRefAlt == Hotspot_TTAuto ) && ( _ToolTipPosRefAlt == Hotspot_TTAuto ) ) - return "auto"; - else{ - s = CInterfaceElement::HotSpotToString( _ToolTipParentPosRefAlt ); - s += " "; - s += CInterfaceElement::HotSpotToString( _ToolTipPosRefAlt ); - return s; - } + return TooltipHotSpotToString( _ToolTipPosRefAlt ); + } + else + if( name == "tooltip_parent_posref_alt" ) + { + return TooltipHotSpotToString( _ToolTipParentPosRefAlt ); } else if( name == "instant_help" ) @@ -293,21 +287,65 @@ namespace NLGUI else if( name == "tooltip_posref" ) { - THotSpot parentHS; THotSpot HS; - convertTooltipHotSpot( value.c_str(), parentHS, HS ); - _ToolTipParentPosRef = parentHS; + convertTooltipHotSpot( value.c_str(), HS ); _ToolTipPosRef = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipPosRef == Hotspot_TTAuto ) + _ToolTipParentPosRef = Hotspot_TTAuto; + else + if( _ToolTipParentPosRef == Hotspot_TTAuto ) + _ToolTipParentPosRef = _ToolTipPosRef; + + return; + } + else + if( name == "tooltip_parent_posref" ) + { + THotSpot HS; + convertTooltipHotSpot( value.c_str(), HS ); + _ToolTipParentPosRef = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipParentPosRef == Hotspot_TTAuto ) + _ToolTipPosRef = Hotspot_TTAuto; + else + if( _ToolTipPosRef == Hotspot_TTAuto ) + _ToolTipPosRef = _ToolTipParentPosRef; + return; } else if( name == "tooltip_posref_alt" ) { - THotSpot parentHS; THotSpot HS; - convertTooltipHotSpot( value.c_str(), parentHS, HS ); - _ToolTipParentPosRefAlt = parentHS; + convertTooltipHotSpot( value.c_str(), HS ); _ToolTipPosRefAlt = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipPosRefAlt == Hotspot_TTAuto ) + _ToolTipParentPosRefAlt = Hotspot_TTAuto; + else + if( _ToolTipParentPosRefAlt == Hotspot_TTAuto ) + _ToolTipPosRefAlt = _ToolTipParentPosRefAlt; + + return; + } + else + if( name == "tooltip_parent_posref_alt" ) + { + THotSpot HS; + convertTooltipHotSpot( value.c_str(), HS ); + _ToolTipParentPosRefAlt = HS; + + // When auto is set, both of them need to be auto + if( _ToolTipParentPosRefAlt == Hotspot_TTAuto ) + _ToolTipPosRefAlt = Hotspot_TTAuto; + else + if( _ToolTipPosRefAlt == Hotspot_TTAuto ) + _ToolTipPosRefAlt = _ToolTipParentPosRefAlt; + return; } else @@ -374,6 +412,21 @@ namespace NLGUI } } + void CCtrlBase::convertTooltipHotSpot(const char *prop, THotSpot &HS ) + { + if(prop) + { + const char *ptr = (const char*)prop; + if(stricmp(ptr, "auto")==0) + { + HS = Hotspot_TTAuto; + } + else if(strlen(ptr)==2) + { + HS = convertHotSpot(ptr); + } + } + } std::string CCtrlBase::TooltipHotSpotToString( THotSpot parent, THotSpot child ) { @@ -393,6 +446,20 @@ namespace NLGUI return s; } + std::string CCtrlBase::TooltipHotSpotToString( THotSpot HS ) + { + std::string s; + if( HS == Hotspot_TTAuto ) + { + s = "auto"; + } + else + { + s = HotSpotToString( HS ); + } + return s; + } + // *************************************************************************** bool CCtrlBase::emptyContextHelp() const { diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 4a839cbee..017b4e5a7 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -102,6 +102,83 @@ namespace }; + class NelPosRefTT + { + public: + + enum NELPosRef + { + TTPOSREF_BL = 0, + TTPOSREF_BM = 1, + TTPOSREF_BR = 2, + TTPOSREF_ML = 3, + TTPOSREF_MM = 4, + TTPOSREF_MR = 5, + TTPOSREF_TL = 6, + TTPOSREF_TM = 7, + TTPOSREF_TR = 8, + TTPOSREF_AUTO = 9 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "BL" ) + r = TTPOSREF_BL; + else + if( s == "BM" ) + r = TTPOSREF_BM; + else + if( s == "BR" ) + r = TTPOSREF_BR; + else + if( s == "ML" ) + r = TTPOSREF_ML; + else + if( s == "MM" ) + r = TTPOSREF_MM; + else + if( s == "MR" ) + r = TTPOSREF_MR; + else + if( s == "TL" ) + r = TTPOSREF_TL; + else + if( s == "TM" ) + r = TTPOSREF_TM; + else + if( s == "TR" ) + r = TTPOSREF_TR; + else + r = TTPOSREF_AUTO; + + return r; + } + + static std::string toString( int value ) + { + std::string v; + + switch( value ) + { + case TTPOSREF_BL: v = "BL"; break; + case TTPOSREF_BM: v = "BM"; break; + case TTPOSREF_BR: v = "BR"; break; + case TTPOSREF_ML: v = "ML"; break; + case TTPOSREF_MM: v = "MM"; break; + case TTPOSREF_MR: v = "MR"; break; + case TTPOSREF_TL: v = "TL"; break; + case TTPOSREF_TM: v = "TM"; break; + case TTPOSREF_TR: v = "TR"; break; + case TTPOSREF_AUTO: v = "auto"; break; + } + + return v; + } + }; + + class NelButtonType { public: @@ -201,6 +278,12 @@ namespace GUIEditor variantFactory = new QtVariantEditorFactory; enumFactory = new QtEnumEditorFactory; + + ttPairs[ "tooltip_posref" ] = "tooltip_parent_posref"; + ttPairs[ "tooltip_parent_posref" ] = "tooltip_posref"; + ttPairs[ "tooltip_posref_alt" ] = "tooltip_parent_posref_alt"; + ttPairs[ "tooltip_parent_posref_alt" ] = "tooltip_posref_alt"; + } CPropBrowserCtrl::~CPropBrowserCtrl() @@ -363,6 +446,56 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } + else + if( type == "posreftt" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelPosRefTT::toString( value ); + if( v.empty() ) + return; + + e->setProperty( propName.toUtf8().constData(), v ); + + // When auto is set as posref for a tooltip, it's pair MUST be auto as well + // When we set anything other than auto, the pair MUST not be auto either + // Only need to set the widget here, since the actual property is changed in the GUI library automatically + { + // Find the pair + std::map< std::string, std::string >::const_iterator ttItr = + ttPairs.find( n ); + + // Found! + if( ttItr != ttPairs.end() ) + { + + // Find the QtProperty that belongs to the pair + std::map< std::string, QtProperty* >::const_iterator pItr = + ttPosRefProps.find( ttItr->second ); + + // Found! + if( pItr != ttPosRefProps.end() ) + { + disablePropertyWatchers(); + + if( value == NelPosRefTT::TTPOSREF_AUTO ) + enumMgr->setValue( pItr->second, NelPosRefTT::TTPOSREF_AUTO ); + else + { + int v = NelPosRefTT::fromString( pItr->second->valueText().toUtf8().constData() ); + if( v == NelPosRefTT::TTPOSREF_AUTO ) + { + enumMgr->setValue( pItr->second, value ); + } + } + + enablePropertyWatchers(); + } + } + } + } } void CPropBrowserCtrl::enablePropertyWatchers() @@ -389,6 +522,7 @@ namespace GUIEditor SWidgetInfo &w = itr->second; nameToType.clear(); + ttPosRefProps.clear(); std::vector< SPropEntry >::const_iterator pItr; for( pItr = w.props.begin(); pItr != w.props.end(); ++pItr ) @@ -490,6 +624,42 @@ namespace GUIEditor return; } else + if( prop.propType == "posreftt" ) + { + std::string j = element->getProperty( prop.propName ); + if( j.empty() ) + return; + + int e = -1; + e = NelPosRefTT::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "BL" ); + enums.push_back( "BM" ); + enums.push_back( "BR" ); + enums.push_back( "ML" ); + enums.push_back( "MM" ); + enums.push_back( "MR" ); + enums.push_back( "TL" ); + enums.push_back( "TM" ); + enums.push_back( "TR" ); + enums.push_back( "auto" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + ttPosRefProps[ prop.propName ] = pp; + + return; + } + else if( prop.propType == "string" ) { p = propertyMgr->addProperty( QVariant::String, prop.propName.c_str() ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index efb785d9b..bec4004d3 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -77,6 +77,8 @@ namespace GUIEditor std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; std::map< std::string, std::string > nameToType; + std::map< std::string, QtProperty * > ttPosRefProps; // Tooltip posref properties + std::map< std::string, std::string > ttPairs; }; } diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml index 5c334dea5..732930348 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml @@ -37,17 +37,27 @@ tooltip_special_parent string - + tooltip_posref - string + posreftt auto - + + + tooltip_parent_posref + posreftt + auto + tooltip_posref_alt - string + posreftt auto - + + + tooltip_parent_posref_alt + posreftt + auto + instant_help bool From c8c162308d835193b021e93bbca76ce712f9e6aa Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 02:53:33 +0200 Subject: [PATCH 086/220] tooltip parent is now changable using an enum. --- code/nel/src/gui/ctrl_base.cpp | 2 +- .../gui_editor/property_browser_ctrl.cpp | 87 +++++++++++++++++++ .../plugins/gui_editor/widgets/CtrlBase.xml | 2 +- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/code/nel/src/gui/ctrl_base.cpp b/code/nel/src/gui/ctrl_base.cpp index 98cda02f4..5c250a0da 100644 --- a/code/nel/src/gui/ctrl_base.cpp +++ b/code/nel/src/gui/ctrl_base.cpp @@ -86,7 +86,7 @@ namespace NLGUI break; } - return ""; + return "control"; } CCtrlBase::TToolTipParentType CCtrlBase::stringToToolTipParent( const std::string &str ) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index 017b4e5a7..d56062eda 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -28,6 +28,52 @@ namespace { + class NelTTParent + { + public: + + enum NELTTParent + { + TTPARENT_MOUSE = 0, + TTPARENT_CONTROL = 1, + TTPARENT_WINDOW = 2, + TTPARENT_SPECIAL_WINDOW = 3 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "mouse" ) + r = TTPARENT_MOUSE; + else + if( s == "control" ) + r = TTPARENT_CONTROL; + else + if( s == "window" ) + r = TTPARENT_WINDOW; + else + if( s == "special" ) + r = TTPARENT_SPECIAL_WINDOW; + + return r; + } + + static std::string toString( int value ) + { + std::string s; + + switch( value ) + { + case TTPARENT_MOUSE: s = "mouse"; break; + case TTPARENT_CONTROL: s = "control"; break; + case TTPARENT_WINDOW: s = "window"; break; + case TTPARENT_SPECIAL_WINDOW: s = "special"; break; + } + + return s; + } + }; class NelPosRef { @@ -496,6 +542,19 @@ namespace GUIEditor } } } + else + if( type == "tooltip_parent" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelTTParent::toString( value ); + if( v.empty() ) + return; + + e->setProperty( propName.toUtf8().constData(), v ); + } } void CPropBrowserCtrl::enablePropertyWatchers() @@ -538,6 +597,34 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "tooltip_parent" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + int e = -1; + e = NelTTParent::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "mouse" ); + enums.push_back( "control" ); + enums.push_back( "window" ); + enums.push_back( "special window" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + + } + else if( prop.propType == "button_type" ) { std::string btype = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml index 732930348..8ac372bdb 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBase.xml @@ -30,7 +30,7 @@ tooltip_parent - string + tooltip_parent From 0dfb7a091c84b0b50dd8e0dfaca4cbe340100d57 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 03:01:43 +0200 Subject: [PATCH 087/220] Quelled some compiler compliants. --- code/nel/src/gui/group_paragraph.cpp | 4 ++++ code/nel/src/gui/group_table.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/code/nel/src/gui/group_paragraph.cpp b/code/nel/src/gui/group_paragraph.cpp index 00ea5f3b7..9e065c878 100644 --- a/code/nel/src/gui/group_paragraph.cpp +++ b/code/nel/src/gui/group_paragraph.cpp @@ -209,6 +209,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "align" ) @@ -229,6 +231,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "space" ) diff --git a/code/nel/src/gui/group_table.cpp b/code/nel/src/gui/group_table.cpp index 9f019ed48..2fdd7e364 100644 --- a/code/nel/src/gui/group_table.cpp +++ b/code/nel/src/gui/group_table.cpp @@ -89,6 +89,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "valign" ) @@ -106,6 +108,8 @@ namespace NLGUI } nlassert(false); + + return ""; } else if( name == "left_margin" ) From 112f90fbbb4579aa147aa36eaf91b54d3fb580a2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 1 Jul 2014 01:51:41 +0200 Subject: [PATCH 088/220] Bitmap alignment can now be set as an enum. --- .../gui_editor/property_browser_ctrl.cpp | 87 +++++++++++++++++++ .../plugins/gui_editor/widgets/ViewBitmap.xml | 2 +- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index d56062eda..a8f129bfd 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -28,6 +28,53 @@ namespace { + class NelBMAlign + { + public: + + enum NELBMAlign + { + LB = 0, + RB = 1, + LT = 2, + RT = 3 + }; + + static int fromString( const std::string &s ) + { + int r = -1; + + if( s == "LB" ) + r = 0; + else + if( s == "RB" ) + r = 1; + else + if( s == "LT" ) + r = 2; + else + if( s == "RT" ) + r = 3; + + return r; + } + + static std::string toString( int value ) + { + std::string s; + + switch( value ) + { + case LB: s = "LB"; break; + case RB: s = "RB"; break; + case LT: s = "LT"; break; + case RT: s = "RT"; break; + } + + return s; + } + }; + class NelTTParent { public: @@ -555,6 +602,19 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v ); } + else + if( type == "bitmap_align" ) + { + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + std::string v = NelBMAlign::toString( value ); + if( v.empty() ) + return; + + e->setProperty( propName.toUtf8().constData(), v ); + } } void CPropBrowserCtrl::enablePropertyWatchers() @@ -597,6 +657,33 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "bitmap_align" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + int e = -1; + e = NelBMAlign::fromString( j ); + if( e == -1 ) + return; + + QtProperty *pp = enumMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + QStringList enums; + enums.push_back( "LB" ); + enums.push_back( "RB" ); + enums.push_back( "LT" ); + enums.push_back( "RT" ); + + enumMgr->setEnumNames( pp, enums ); + enumMgr->setValue( pp, e ); + browser->addProperty( pp ); + } + else if( prop.propType == "tooltip_parent" ) { std::string j = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index 9da967b5a..7dddfdbe1 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -60,7 +60,7 @@ align - string + bitmap_align From 40805d6526540359c6dbfa28a244c46f1c10a32c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 1 Jul 2014 01:54:55 +0200 Subject: [PATCH 089/220] Changed some property types. --- code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml | 2 +- .../src/plugins/gui_editor/widgets/ViewBitmapCombo.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index 7dddfdbe1..c39ecbabc 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -10,7 +10,7 @@ color - string + color 255 255 255 255 diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml index 0b55f6932..8fc579675 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmapCombo.xml @@ -25,17 +25,17 @@ col_normal - string + color col_over - string + color col_pushed - string + color From 0f489d209c18e0ddba76ab894bf2ace25fa70cf6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 2 Jul 2014 20:44:46 +0200 Subject: [PATCH 090/220] Line endings... --- code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index a8f129bfd..e3594edb0 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -34,8 +34,8 @@ namespace enum NELBMAlign { - LB = 0, - RB = 1, + LB = 0, + RB = 1, LT = 2, RT = 3 }; From 668bbc17805f06026e51daf1c344f51a5f557bbc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 2 Jul 2014 22:27:04 +0200 Subject: [PATCH 091/220] Added facilities for viewing the loaded actions. --- code/nel/include/nel/gui/action_handler.h | 2 + code/nel/src/gui/action_handler.cpp | 12 +++ .../src/plugins/gui_editor/CMakeLists.txt | 2 + .../src/plugins/gui_editor/action_list.cpp | 31 ++++++ .../src/plugins/gui_editor/action_list.h | 18 ++++ .../src/plugins/gui_editor/action_list.ui | 94 +++++++++++++++++++ .../plugins/gui_editor/gui_editor_window.cpp | 15 +++ .../plugins/gui_editor/gui_editor_window.h | 4 + 8 files changed, 178 insertions(+) create mode 100644 code/studio/src/plugins/gui_editor/action_list.cpp create mode 100644 code/studio/src/plugins/gui_editor/action_list.h create mode 100644 code/studio/src/plugins/gui_editor/action_list.ui diff --git a/code/nel/include/nel/gui/action_handler.h b/code/nel/include/nel/gui/action_handler.h index 70c4b386e..48b49e451 100644 --- a/code/nel/include/nel/gui/action_handler.h +++ b/code/nel/include/nel/gui/action_handler.h @@ -68,6 +68,8 @@ namespace NLGUI return _GlobalInstance; } + void getActionHandlers( std::vector< std::string > &handlers ); + /// return pointer to action handler or null if it doesn't exist IActionHandler *getActionHandler(const std::string &name) const { diff --git a/code/nel/src/gui/action_handler.cpp b/code/nel/src/gui/action_handler.cpp index 8b0d9c4ee..d7214ef06 100644 --- a/code/nel/src/gui/action_handler.cpp +++ b/code/nel/src/gui/action_handler.cpp @@ -111,6 +111,18 @@ namespace NLGUI } } + void CAHManager::getActionHandlers( std::vector< std::string > &handlers ) + { + handlers.clear(); + + std::map< string, IActionHandler* >::iterator itr = FactoryMap.begin(); + while( itr != FactoryMap.end() ) + { + handlers.push_back( itr->first ); + ++itr; + } + } + // ------------------------------------------------------------------------------------------------ IActionHandler* CAHManager::getAH(const std::string &name, std::string ¶ms) { diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 0c13c4cd6..33b016bd6 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -30,6 +30,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR add_widget_widget.h editor_selection_watcher.h editor_message_processor.h + action_list.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS @@ -45,6 +46,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_UIS new_property_widget.ui new_widget_widget.ui add_widget_widget.ui + action_list.ui ) SET(QT_USE_QTGUI TRUE) diff --git a/code/studio/src/plugins/gui_editor/action_list.cpp b/code/studio/src/plugins/gui_editor/action_list.cpp new file mode 100644 index 000000000..fa61dd6b6 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_list.cpp @@ -0,0 +1,31 @@ +#include "action_list.h" +#include "nel/gui/action_handler.h" +#include +#include + +ActionList::ActionList( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); +} + +ActionList::~ActionList() +{ +} + +void ActionList::load() +{ + actionList->clear(); + + NLGUI::CAHManager *am = NLGUI::CAHManager::getInstance(); + std::vector< std::string > handlers; + am->getActionHandlers( handlers ); + + std::vector< std::string >::const_iterator itr = handlers.begin(); + while( itr != handlers.end() ) + { + actionList->addItem( itr->c_str() ); + ++itr; + } +} + diff --git a/code/studio/src/plugins/gui_editor/action_list.h b/code/studio/src/plugins/gui_editor/action_list.h new file mode 100644 index 000000000..ba668f99e --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_list.h @@ -0,0 +1,18 @@ +#ifndef ACTION_LIST_H +#define ACTION_LIST_H + + +#include "ui_action_list.h" + + +class ActionList : public QDialog, public Ui::ActionListDialog +{ + Q_OBJECT + +public: + ActionList( QDialog *parent = NULL ); + ~ActionList(); + void load(); +}; + +#endif diff --git a/code/studio/src/plugins/gui_editor/action_list.ui b/code/studio/src/plugins/gui_editor/action_list.ui new file mode 100644 index 000000000..ba147cfc2 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_list.ui @@ -0,0 +1,94 @@ + + + ActionListDialog + + + + 0 + 0 + 359 + 258 + + + + Action List + + + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + okButton + clicked() + ActionListDialog + accept() + + + 278 + 253 + + + 96 + 254 + + + + + cancelButton + clicked() + ActionListDialog + reject() + + + 369 + 253 + + + 179 + 282 + + + + + diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 4f66b61fc..0cbc94947 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -44,6 +44,7 @@ #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" +#include "action_list.h" namespace GUIEditor { @@ -70,6 +71,8 @@ namespace GUIEditor widgetInfoTree = new CWidgetInfoTree; + actionList = new ActionList(); + createMenus(); readSettings(); @@ -115,6 +118,9 @@ namespace GUIEditor removeMenus(); + delete actionList; + actionList = NULL; + delete messageProcessor; messageProcessor = NULL; @@ -341,6 +347,11 @@ namespace GUIEditor } + void GUIEditorWindow::test_actionList() + { + actionList->load(); + actionList->show(); + } void GUIEditorWindow::hideEvent( QHideEvent *evnt ) { @@ -400,6 +411,10 @@ namespace GUIEditor connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); + a = new QAction( "Test actionlist", this ); + connect( a, SIGNAL( triggered( bool ) ), this, SLOT( test_actionList() ) ); + m->addAction( a ); + menu = m; } } diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 517186739..fc1f533cc 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -27,6 +27,7 @@ class QtTreePropertyBrowser; class QMenu; +class ActionList; namespace GUIEditor { @@ -66,6 +67,8 @@ private Q_SLOTS: void onAddWidgetClicked(); void onTreeChanged(); + void test_actionList(); + protected: void hideEvent( QHideEvent *evnt ); void showEvent( QShowEvent *evnt ); @@ -91,6 +94,7 @@ private: CWidgetInfoTree *widgetInfoTree; CEditorMessageProcessor *messageProcessor; AddWidgetWidget *addWidgetWidget; + ActionList *actionList; CPropBrowserCtrl browserCtrl; QString currentProject; From cf2e18143f535eeb49a201f8955dc2b133398ee0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 3 Jul 2014 00:44:38 +0200 Subject: [PATCH 092/220] ActionList dialog can now select an action, and is used with the proc editor. --- .../src/plugins/gui_editor/action_list.cpp | 18 +++++++++++++++ .../src/plugins/gui_editor/action_list.h | 11 ++++++++++ .../plugins/gui_editor/gui_editor_window.cpp | 16 -------------- .../plugins/gui_editor/gui_editor_window.h | 3 --- .../src/plugins/gui_editor/proc_editor.cpp | 22 ++++++++++--------- .../src/plugins/gui_editor/proc_editor.h | 4 ++++ 6 files changed, 45 insertions(+), 29 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/action_list.cpp b/code/studio/src/plugins/gui_editor/action_list.cpp index fa61dd6b6..8925e6d04 100644 --- a/code/studio/src/plugins/gui_editor/action_list.cpp +++ b/code/studio/src/plugins/gui_editor/action_list.cpp @@ -29,3 +29,21 @@ void ActionList::load() } } +void ActionList::accept() +{ + QListWidgetItem *item = actionList->currentItem(); + if( item == NULL ) + return; + + selectedAction = item->text(); + + QDialog::accept(); +} + +void ActionList::reject() +{ + selectedAction = ""; + + QDialog::reject(); +} + diff --git a/code/studio/src/plugins/gui_editor/action_list.h b/code/studio/src/plugins/gui_editor/action_list.h index ba668f99e..752d66467 100644 --- a/code/studio/src/plugins/gui_editor/action_list.h +++ b/code/studio/src/plugins/gui_editor/action_list.h @@ -3,6 +3,7 @@ #include "ui_action_list.h" +#include class ActionList : public QDialog, public Ui::ActionListDialog @@ -13,6 +14,16 @@ public: ActionList( QDialog *parent = NULL ); ~ActionList(); void load(); + + QString getSelectedAction(){ return selectedAction; } + + +public Q_SLOTS: + void accept(); + void reject(); + +private: + QString selectedAction; }; #endif diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 0cbc94947..9f6568936 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -44,7 +44,6 @@ #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" -#include "action_list.h" namespace GUIEditor { @@ -71,8 +70,6 @@ namespace GUIEditor widgetInfoTree = new CWidgetInfoTree; - actionList = new ActionList(); - createMenus(); readSettings(); @@ -118,9 +115,6 @@ namespace GUIEditor removeMenus(); - delete actionList; - actionList = NULL; - delete messageProcessor; messageProcessor = NULL; @@ -347,12 +341,6 @@ namespace GUIEditor } - void GUIEditorWindow::test_actionList() - { - actionList->load(); - actionList->show(); - } - void GUIEditorWindow::hideEvent( QHideEvent *evnt ) { QWidget::hideEvent( evnt ); @@ -411,10 +399,6 @@ namespace GUIEditor connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); - a = new QAction( "Test actionlist", this ); - connect( a, SIGNAL( triggered( bool ) ), this, SLOT( test_actionList() ) ); - m->addAction( a ); - menu = m; } } diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index fc1f533cc..15935fe74 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -27,7 +27,6 @@ class QtTreePropertyBrowser; class QMenu; -class ActionList; namespace GUIEditor { @@ -67,7 +66,6 @@ private Q_SLOTS: void onAddWidgetClicked(); void onTreeChanged(); - void test_actionList(); protected: void hideEvent( QHideEvent *evnt ); @@ -94,7 +92,6 @@ private: CWidgetInfoTree *widgetInfoTree; CEditorMessageProcessor *messageProcessor; AddWidgetWidget *addWidgetWidget; - ActionList *actionList; CPropBrowserCtrl browserCtrl; QString currentProject; diff --git a/code/studio/src/plugins/gui_editor/proc_editor.cpp b/code/studio/src/plugins/gui_editor/proc_editor.cpp index c36b16f64..e96a1cce1 100644 --- a/code/studio/src/plugins/gui_editor/proc_editor.cpp +++ b/code/studio/src/plugins/gui_editor/proc_editor.cpp @@ -17,6 +17,7 @@ #include "proc_editor.h" #include "action_editor.h" +#include "action_list.h" #include #include #include "nel/gui/interface_group.h" @@ -35,10 +36,15 @@ namespace GUIEditor connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveButtonClicked() ) ); connect( upButton, SIGNAL( clicked( bool ) ), this, SLOT( onUpButtonClicked() ) ); connect( downButton, SIGNAL( clicked( bool ) ), this, SLOT( onDownButtonClicked() ) ); + + alist = new ActionList(); } ProcEditor::~ProcEditor() { + delete alist; + alist = NULL; + delete actionEditor; actionEditor = NULL; } @@ -84,17 +90,13 @@ namespace GUIEditor void ProcEditor::onAddButtonClicked() { - bool ok; - QString name = - QInputDialog::getText( this, - tr( "Adding new Action" ), - tr( "Please specify the name of the new action handler" ), - QLineEdit::Normal, - QString(), - &ok ); - - if( ok ) + alist->load(); + int result = alist->exec(); + + if( result == QDialog::Accepted ) { + QString name = alist->getSelectedAction(); + CProcedure *proc = CWidgetManager::getInstance()->getParser()->getProc( currentProc.toUtf8().constData() ); if( proc != NULL ) diff --git a/code/studio/src/plugins/gui_editor/proc_editor.h b/code/studio/src/plugins/gui_editor/proc_editor.h index 90579daa4..8debfef02 100644 --- a/code/studio/src/plugins/gui_editor/proc_editor.h +++ b/code/studio/src/plugins/gui_editor/proc_editor.h @@ -20,6 +20,8 @@ #include "ui_proc_editor.h" +class ActionList; + namespace GUIEditor { class ActionEditor; @@ -46,6 +48,8 @@ namespace GUIEditor ActionEditor *actionEditor; QString currentProc; + + ActionList *alist; }; } From 95defff4480968b53dc1dec154446c8fb7fe481a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 02:55:46 +0200 Subject: [PATCH 093/220] Prototype of the texture chooser. --- .../src/plugins/gui_editor/CMakeLists.txt | 2 + .../plugins/gui_editor/gui_editor_window.cpp | 16 +++ .../plugins/gui_editor/gui_editor_window.h | 5 + .../plugins/gui_editor/texture_chooser.cpp | 98 +++++++++++++++ .../src/plugins/gui_editor/texture_chooser.h | 26 ++++ .../src/plugins/gui_editor/texture_chooser.ui | 116 ++++++++++++++++++ 6 files changed, 263 insertions(+) create mode 100644 code/studio/src/plugins/gui_editor/texture_chooser.cpp create mode 100644 code/studio/src/plugins/gui_editor/texture_chooser.h create mode 100644 code/studio/src/plugins/gui_editor/texture_chooser.ui diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 33b016bd6..31d83ae83 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -31,6 +31,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR editor_selection_watcher.h editor_message_processor.h action_list.h + texture_chooser.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS @@ -47,6 +48,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_UIS new_widget_widget.ui add_widget_widget.ui action_list.ui + texture_chooser.ui ) SET(QT_USE_QTGUI TRUE) diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp index 9f6568936..3f4e318db 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.cpp +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.cpp @@ -44,6 +44,7 @@ #include "editor_selection_watcher.h" #include "editor_message_processor.h" #include "add_widget_widget.h" +#include "texture_chooser.h" namespace GUIEditor { @@ -70,6 +71,8 @@ namespace GUIEditor widgetInfoTree = new CWidgetInfoTree; + tc = new TextureChooser(); + createMenus(); readSettings(); @@ -115,6 +118,9 @@ namespace GUIEditor removeMenus(); + delete tc; + tc = NULL; + delete messageProcessor; messageProcessor = NULL; @@ -353,6 +359,12 @@ namespace GUIEditor GUICtrl->show(); } + void GUIEditorWindow::onTCClicked() + { + tc->load(); + tc->exec(); + } + void GUIEditorWindow::createMenus() { Core::MenuManager *mm = Core::ICore::instance()->menuManager(); @@ -399,6 +411,10 @@ namespace GUIEditor connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); m->addAction( a ); + a = new QAction( "Texture Chooser", this ); + connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onTCClicked() ) ); + m->addAction( a ); + menu = m; } } diff --git a/code/studio/src/plugins/gui_editor/gui_editor_window.h b/code/studio/src/plugins/gui_editor/gui_editor_window.h index 15935fe74..d18a24813 100644 --- a/code/studio/src/plugins/gui_editor/gui_editor_window.h +++ b/code/studio/src/plugins/gui_editor/gui_editor_window.h @@ -28,6 +28,8 @@ class QtTreePropertyBrowser; class QMenu; +class TextureChooser; + namespace GUIEditor { @@ -65,6 +67,7 @@ private Q_SLOTS: void onGUILoaded(); void onAddWidgetClicked(); void onTreeChanged(); + void onTCClicked(); protected: @@ -98,6 +101,8 @@ private: QString currentProjectFile; QMenu *menu; + + TextureChooser *tc; }; } diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp new file mode 100644 index 000000000..11e5a30fd --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -0,0 +1,98 @@ +#include "texture_chooser.h" +#include "nel/misc/path.h" +#include "nel/misc/bitmap.h" +#include "nel/misc/file.h" +#include +#include +#include +#include + +TextureChooser::TextureChooser( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); + data = NULL; +} + +TextureChooser::~TextureChooser() +{ + delete data; + data = NULL; +} + + +void TextureChooser::load() +{ + listWidget->clear(); + + std::vector< std::string > textures; + NLMISC::CPath::getFileList( "tga", textures ); + + std::vector< std::string >::const_iterator itr = textures.begin(); + while( itr != textures.end() ) + { + listWidget->addItem( itr->c_str() ); + ++itr; + } +} + +void TextureChooser::onCurrentRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = listWidget->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + rfn = NLMISC::CPath::lookup( rfn ); + + NLMISC::CIFile f; + bool b = f.open( rfn ); + if( !b ) + { + return; + } + + NLMISC::CBitmap bm; + uint8 depth = bm.load( f ); + f.close(); + + uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image + + if( data != NULL ) + delete data; + + data = new uint8[ size ]; + bm.getData( data ); + + /// Convert from ABGR to ARGB + { + int i = 0; + while( i < size ) + { + uint8 t = 0; + + /// ABGR + t = data[ i ]; + data[ i ] = data[ i + 2 ]; + data[ i + 2 ] = t; + + i += 4; + } + } + + QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); + label->setPixmap( QPixmap::fromImage( img ) ); + +} + + +void TextureChooser::setupConnections() +{ + connect( listWidget, SIGNAL( currentRowChanged( int ) ), this, SLOT( onCurrentRowChanged( int ) ) ); +} + + + diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h new file mode 100644 index 000000000..fecd0aa1e --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -0,0 +1,26 @@ +#ifndef TEXTURE_CHOOSER_H +#define TEXTURE_CHOOSER_H + +#include "ui_texture_chooser.h" + +class TextureChooser : public QDialog, public Ui::TextureChooser +{ + Q_OBJECT + +public: + TextureChooser( QDialog *parent = NULL ); + ~TextureChooser(); + + void load(); + +private Q_SLOTS: + void onCurrentRowChanged( int row ); + +private: + void setupConnections(); + + unsigned char *data; +}; + +#endif + diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.ui b/code/studio/src/plugins/gui_editor/texture_chooser.ui new file mode 100644 index 000000000..0f635e96f --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_chooser.ui @@ -0,0 +1,116 @@ + + + TextureChooser + + + Qt::ApplicationModal + + + + 0 + 0 + 686 + 300 + + + + Texture Chooser + + + + + + + + + + 0 + 0 + + + + + 351 + 231 + + + + + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + okButton + clicked() + TextureChooser + accept() + + + 278 + 253 + + + 96 + 254 + + + + + cancelButton + clicked() + TextureChooser + reject() + + + 369 + 253 + + + 179 + 282 + + + + + From 2a47ce329207cba7b29752940f1f59ea9244b1fb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 03:13:01 +0200 Subject: [PATCH 094/220] No need to store the loaded image data after passing it to the label. --- .../studio/src/plugins/gui_editor/texture_chooser.cpp | 11 ++++------- code/studio/src/plugins/gui_editor/texture_chooser.h | 2 -- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 11e5a30fd..04328d9ef 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -12,13 +12,10 @@ QDialog( parent ) { setupUi( this ); setupConnections(); - data = NULL; } TextureChooser::~TextureChooser() { - delete data; - data = NULL; } @@ -61,10 +58,7 @@ void TextureChooser::onCurrentRowChanged( int row ) uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image - if( data != NULL ) - delete data; - - data = new uint8[ size ]; + uint8 *data = new uint8[ size ]; bm.getData( data ); /// Convert from ABGR to ARGB @@ -86,6 +80,9 @@ void TextureChooser::onCurrentRowChanged( int row ) QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); label->setPixmap( QPixmap::fromImage( img ) ); + delete data; + data = NULL; + } diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index fecd0aa1e..24b93fc40 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -18,8 +18,6 @@ private Q_SLOTS: private: void setupConnections(); - - unsigned char *data; }; #endif From 28807c5eea03492e63321f86252b82a3b96d701a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 03:31:21 +0200 Subject: [PATCH 095/220] Make sure to always convert to plain bitmap. --- code/studio/src/plugins/gui_editor/texture_chooser.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 04328d9ef..95a081897 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -55,6 +55,11 @@ void TextureChooser::onCurrentRowChanged( int row ) NLMISC::CBitmap bm; uint8 depth = bm.load( f ); f.close(); + b = bm.convertToType( NLMISC::CBitmap::RGBA ); + if( !b ) + { + return; + } uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image From c736145c2fc7c56b70bc593e011d51dbcf247f21 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 6 Jul 2014 23:21:25 +0200 Subject: [PATCH 096/220] CPath can now return the file list with a path filter. --- code/nel/include/nel/misc/path.h | 8 +++ code/nel/src/misc/path.cpp | 61 +++++++++++++++++++ .../plugins/gui_editor/texture_chooser.cpp | 3 +- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/code/nel/include/nel/misc/path.h b/code/nel/include/nel/misc/path.h index 73652a581..f3120c907 100644 --- a/code/nel/include/nel/misc/path.h +++ b/code/nel/include/nel/misc/path.h @@ -200,6 +200,10 @@ public: */ void getFileListByName(const std::string &extension, const std::string &name, std::vector &filenames); + /** Create a list of file having the requested string in the path and the requested extension. + */ + void getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames); + /** Make a path relative to another if possible, else doesn't change it. * \param basePath is the base path to be relative to. * \param relativePath is the path to make relative to basePath. @@ -492,6 +496,10 @@ public: */ static void getFileListByName(const std::string &extension, const std::string &name, std::vector &filenames); + /** Create a list of file having the requested string in the path and the requested extension + */ + static void getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames); + /** Make a path relative to another if possible, else doesn't change it. * \param basePath is the base path to be relative to. * \param relativePath is the path to make relative to basePath. diff --git a/code/nel/src/misc/path.cpp b/code/nel/src/misc/path.cpp index f92b0bda7..c5a80e830 100644 --- a/code/nel/src/misc/path.cpp +++ b/code/nel/src/misc/path.cpp @@ -219,6 +219,67 @@ void CFileContainer::getFileListByName(const std::string &extension, const std:: } } +void CPath::getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames) +{ + getInstance()->_FileContainer.getFileListByPath(extension, path, filenames); +} + +void CFileContainer::getFileListByPath(const std::string &extension, const std::string &path, std::vector &filenames) +{ + if (!_MemoryCompressed) + { + TFiles::iterator first(_Files.begin()), last(_Files.end()); + + if( !path.empty() ) + { + for (; first != last; ++ first) + { + string ext = SSMext.get(first->second.idExt); + string p = SSMpath.get(first->second.idPath); + if (p.find(path) != string::npos && (ext == extension || extension.empty())) + { + filenames.push_back(first->first); + } + } + } + // if extension is empty we keep all files + else + { + for (; first != last; ++ first) + { + filenames.push_back(first->first); + } + } + } + else + { + // compressed memory version + std::vector::iterator first(_MCFiles.begin()), last(_MCFiles.end()); + + if( !path.empty() ) + { + for (; first != last; ++ first) + { + string ext = SSMext.get(first->idExt); + string p = SSMpath.get(first->idPath); + + if (strstr(p.c_str(), path.c_str()) != NULL && (ext == extension || extension.empty())) + { + filenames.push_back(first->Name); + } + } + } + // if extension is empty we keep all files + else + { + for (; first != last; ++ first) + { + filenames.push_back(first->Name); + } + } + } +} + void CPath::clearMap () { getInstance()->_FileContainer.clearMap(); diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 95a081897..7545d2803 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -24,7 +24,8 @@ void TextureChooser::load() listWidget->clear(); std::vector< std::string > textures; - NLMISC::CPath::getFileList( "tga", textures ); + //NLMISC::CPath::getFileList( "tga", textures ); + NLMISC::CPath::getFileListByPath( "tga", "interfaces", textures ); std::vector< std::string >::const_iterator itr = textures.begin(); while( itr != textures.end() ) From 6f3e230cad0beb1933609c19c29823fc4b1a3084 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 7 Jul 2014 19:19:03 +0200 Subject: [PATCH 097/220] Allow TextureChooser's texture selection to be queried. --- .../plugins/gui_editor/texture_chooser.cpp | 19 +++++++++++++++++++ .../src/plugins/gui_editor/texture_chooser.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 7545d2803..d857d9bdc 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -33,6 +33,25 @@ void TextureChooser::load() listWidget->addItem( itr->c_str() ); ++itr; } + + listWidget->setCurrentRow( 0 ); +} + +void TextureChooser::accept() +{ + QListWidgetItem *item = listWidget->currentItem(); + if( item == NULL ) + return; + + selection = item->text(); + QDialog::accept(); +} + +void TextureChooser::reject() +{ + selection = ""; + + QDialog::reject(); } void TextureChooser::onCurrentRowChanged( int row ) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index 24b93fc40..bab1dd1dc 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -12,12 +12,19 @@ public: ~TextureChooser(); void load(); + QString getSelection(){ return selection; } + +public Q_SLOTS: + void accept(); + void reject(); private Q_SLOTS: void onCurrentRowChanged( int row ); private: void setupConnections(); + + QString selection; }; #endif From 3b0b82423f5d6ab9fd2edde3b064d9014fd9dd2c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 8 Jul 2014 18:26:20 +0200 Subject: [PATCH 098/220] Added action property editor, editor factory, manager. Actions can now be edited using the editor widget in the property tree. --- .../src/plugins/gui_editor/CMakeLists.txt | 1 + .../gui_editor/action_property_manager.cpp | 333 ++++++++++++++++++ .../gui_editor/action_property_manager.h | 125 +++++++ .../gui_editor/property_browser_ctrl.cpp | 45 ++- .../gui_editor/property_browser_ctrl.h | 6 + .../gui_editor/widgets/CtrlBaseButton.xml | 12 +- .../gui_editor/widgets/GroupContainer.xml | 16 +- .../gui_editor/widgets/InterfaceGroup.xml | 10 +- .../widgets/InterfaceGroupWheel.xml | 4 +- 9 files changed, 529 insertions(+), 23 deletions(-) create mode 100644 code/studio/src/plugins/gui_editor/action_property_manager.cpp create mode 100644 code/studio/src/plugins/gui_editor/action_property_manager.h diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index 31d83ae83..f95e6c0a7 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -32,6 +32,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR editor_message_processor.h action_list.h texture_chooser.h + action_property_manager.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS diff --git a/code/studio/src/plugins/gui_editor/action_property_manager.cpp b/code/studio/src/plugins/gui_editor/action_property_manager.cpp new file mode 100644 index 000000000..9e7690a56 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_property_manager.cpp @@ -0,0 +1,333 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "action_property_manager.h" +#include "action_list.h" +#include +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + + +struct ActionPropertyManagerPrivate +{ + QMap< const QtProperty*, QString > values; +}; + +ActionPropertyManager::ActionPropertyManager( QObject *parent ) : +QtAbstractPropertyManager( parent ) +{ + d_ptr = new ActionPropertyManagerPrivate(); +} + +ActionPropertyManager::~ActionPropertyManager() +{ + delete d_ptr; + d_ptr = NULL; +} + +QString ActionPropertyManager::value( const QtProperty *p ) const +{ + return valueText( p ); +} + +void ActionPropertyManager::setValue( QtProperty *p, const QString &value ) +{ + if( !d_ptr->values.contains( p ) ) + return; + + if( d_ptr->values[ p ] == value ) + return; + + d_ptr->values[ p ] = value; + + Q_EMIT propertyChanged( p ); + Q_EMIT valueChanged( p, value ); +} + +bool ActionPropertyManager::hasValue( const QtProperty *p ) const +{ + return d_ptr->values.contains( p ); +} + +QString ActionPropertyManager::valueText( const QtProperty *p ) const +{ + if( !d_ptr->values.contains( p ) ) + return ""; + + return d_ptr->values[ p ]; +} + +void ActionPropertyManager::initializeProperty( QtProperty *p ) +{ + if( d_ptr->values.contains( p ) ) + return; + + d_ptr->values[ p ] = ""; +} + +void ActionPropertyManager::uninitializeProperty( QtProperty *p ) +{ + d_ptr->values.remove( p ); +} + + + +//////////////////////////////////////////////////////////////////// Factory /////////////////////////////////////////////////////////////////////// + + + +struct ActionEditorFactoryPrivate +{ + QMap< QtProperty*, QList< ActionPropertyEditor* > > createdEditors; + QMap< ActionPropertyEditor*, QtProperty* > editorToProperty; + + ~ActionEditorFactoryPrivate() + { + createdEditors.clear(); + + QMap< ActionPropertyEditor*, QtProperty* >::iterator itr = editorToProperty.begin(); + while( itr != editorToProperty.end() ) + { + delete itr.key(); + ++itr; + } + editorToProperty.clear(); + } + + void addEditor( QtProperty *p, ActionPropertyEditor *editor ) + { + QMap< QtProperty*, QList< ActionPropertyEditor* > >::iterator itr = createdEditors.find( p ); + + if( itr != createdEditors.end() ) + { + itr->push_back( editor ); + } + else + { + QList< ActionPropertyEditor* > l; + l.push_back( editor ); + createdEditors.insert( p, l ); + } + + editorToProperty.insert( editor, p ); + } + + void removeEditor( QObject *o ) + { + // Remove from editorToProperty first + QMap< ActionPropertyEditor*, QtProperty* >::iterator itr1 = editorToProperty.begin(); + while( itr1 != editorToProperty.end() ) + { + if( itr1.key() == o ) + break; + + ++itr1; + } + if( itr1 != editorToProperty.end() ) + editorToProperty.erase( itr1 ); + + // Then from createdEditors + QMap< QtProperty*, QList< ActionPropertyEditor* > >::iterator itr2 = createdEditors.begin(); + while( itr2 != createdEditors.end() ) + { + QList< ActionPropertyEditor* > &l = *itr2; + QList< ActionPropertyEditor* >::iterator itr = l.begin(); + while( itr != l.end() ) + { + if( *itr == o ) + { + QList< ActionPropertyEditor* >::iterator d = itr; + ++itr; + l.erase( d ); + continue; + } + + ++itr; + } + + ++itr2; + } + } + +}; + +ActionEditorFactory::ActionEditorFactory( QObject *parent ) : +QtAbstractEditorFactory( parent ) +{ + d_ptr = new ActionEditorFactoryPrivate(); +} + +ActionEditorFactory::~ActionEditorFactory() +{ + delete d_ptr; + d_ptr = NULL; +} + +void ActionEditorFactory::connectPropertyManager( ActionPropertyManager *manager ) +{ + connect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +void ActionEditorFactory::disconnectPropertyManager( ActionPropertyManager *manager ) +{ + disconnect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +QWidget* ActionEditorFactory::createEditor( ActionPropertyManager *manager, QtProperty *p, QWidget *parent ) +{ + ActionPropertyEditor *editor = new ActionPropertyEditor( parent ); + editor->setValue( manager->value( p ) ); + + connect( editor, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onSetValue( const QString& ) ) ); + connect( editor, SIGNAL( destroyed( QObject* ) ), this, SLOT( onEditorDestroyed( QObject* ) ) ); + + d_ptr->addEditor( p, editor ); + + return editor; +} + +void ActionEditorFactory::onPropertyChanged( QtProperty *p, const QString &value ) +{ + QMap< QtProperty*, QList< ActionPropertyEditor* > >::iterator itr = d_ptr->createdEditors.find( p ); + if( itr == d_ptr->createdEditors.end() ) + return; + + QList< ActionPropertyEditor* > &l = *itr; + QList< ActionPropertyEditor* >::iterator i = l.begin(); + while( i != l.end() ) + { + ActionPropertyEditor *editor = *i; + + editor->blockSignals( true ); + editor->setValue( value ); + editor->blockSignals( false ); + + ++i; + } +} + +void ActionEditorFactory::onSetValue( const QString &value ) +{ + QObject *s = sender(); + ActionPropertyEditor *editor = qobject_cast< ActionPropertyEditor* >( s ); + if( editor == NULL ) + return; + + QMap< ActionPropertyEditor*, QtProperty* >::iterator itr = d_ptr->editorToProperty.find( editor ); + if( itr == d_ptr->editorToProperty.end() ) + return; + + QtProperty *p = *itr; + + ActionPropertyManager *manager = qobject_cast< ActionPropertyManager* >( p->propertyManager() ); + if( manager == NULL ) + return; + + blockSignals( true ); + manager->setValue( p, value ); + blockSignals( false ); +} + +void ActionEditorFactory::onEditorDestroyed( QObject *editor ) +{ + d_ptr->removeEditor( editor ); +} + + + +//////////////////////////////////////////////////////////////////////// Editor ////////////////////////////////////////////////////////////////// + + + +ActionPropertyEditor::ActionPropertyEditor( QWidget *parent ) : +QWidget( parent ) +{ + setupUi(); + setupConnections(); +} + +ActionPropertyEditor::~ActionPropertyEditor() +{ +} + +void ActionPropertyEditor::setValue( const QString &value ) +{ + if( lineEdit->text() == value ) + return; + + disableConnections(); + lineEdit->setText( value ); + setupConnections(); +} + +void ActionPropertyEditor::showEvent( QShowEvent *e ) +{ + QWidget::showEvent( e ); +} + +void ActionPropertyEditor::onToolButtonClicked() +{ + ActionList d; + d.load(); + + int result = d.exec(); + if( QDialog::Accepted != result ) + return; + + lineEdit->setText( d.getSelectedAction() ); +} + +void ActionPropertyEditor::onTextChanged( const QString &text ) +{ + Q_EMIT valueChanged( text ); +} + +void ActionPropertyEditor::setupConnections() +{ + connect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + connect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ActionPropertyEditor::disableConnections() +{ + disconnect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + disconnect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ActionPropertyEditor::setupUi() +{ + lineEdit = new QLineEdit(); + toolButton = new QToolButton(); + toolButton->setText( "..." ); + + QHBoxLayout *lt = new QHBoxLayout( this ); + lt->setContentsMargins( 0, 0, 0, 0 ); + lt->setSpacing( 0 ); + lt->addWidget( lineEdit ); + lt->addWidget( toolButton ); + + setFocusProxy( lineEdit ); + setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); + +} + + diff --git a/code/studio/src/plugins/gui_editor/action_property_manager.h b/code/studio/src/plugins/gui_editor/action_property_manager.h new file mode 100644 index 000000000..06cd714d7 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/action_property_manager.h @@ -0,0 +1,125 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef ACTION_PROPERTY_MANAGER +#define ACTION_PROPERTY_MANAGER + +#define QT_QTPROPERTYBROWSER_IMPORT + +#include "3rdparty/qtpropertybrowser/qtpropertybrowser.h" +#include + +/////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + +struct ActionPropertyManagerPrivate; + +class ActionPropertyManager : public QtAbstractPropertyManager +{ + Q_OBJECT + +public: + ActionPropertyManager( QObject *parent = NULL ); + ~ActionPropertyManager(); + + QString value( const QtProperty *p ) const; + +public Q_SLOTS: + void setValue( QtProperty *p, const QString &value ); + +Q_SIGNALS: + void valueChanged( QtProperty *p, const QString &value ); + +protected: + bool hasValue( const QtProperty *p ) const; + QString valueText( const QtProperty *p ) const; + void initializeProperty( QtProperty *p ); + void uninitializeProperty( QtProperty *p ); + +private: + ActionPropertyManagerPrivate *d_ptr; + + Q_DISABLE_COPY( ActionPropertyManager ); +}; + + +////////////////////////////////////////////////////////////////// Factory ///////////////////////////////////////////////////////////////////////// + +struct ActionEditorFactoryPrivate; + +class ActionEditorFactory : public QtAbstractEditorFactory< ActionPropertyManager > +{ + Q_OBJECT + +public: + ActionEditorFactory( QObject *parent = NULL ); + ~ActionEditorFactory(); + +protected: + void connectPropertyManager( ActionPropertyManager *manager ); + void disconnectPropertyManager( ActionPropertyManager *manager ); + + QWidget* createEditor( ActionPropertyManager *manager, QtProperty *p, QWidget *parent ); + +private Q_SLOTS: + void onPropertyChanged( QtProperty *p, const QString &value ); + void onSetValue( const QString &value ); + void onEditorDestroyed( QObject *editor ); + +private: + ActionEditorFactoryPrivate *d_ptr; + + Q_DISABLE_COPY( ActionEditorFactory ); +}; + + +///////////////////////////////////////////////////////////////// Editor /////////////////////////////////////////////////////////////////////////// + +class QLineEdit; +class QToolButton; + +class ActionPropertyEditor : public QWidget +{ + Q_OBJECT +public: + ActionPropertyEditor( QWidget *parent = NULL ); + ~ActionPropertyEditor(); + +public Q_SLOTS: + void setValue( const QString &value ); + +protected: + void showEvent( QShowEvent *e ); + +private Q_SLOTS: + void onToolButtonClicked(); + void onTextChanged( const QString &text ); + +Q_SIGNALS: + void valueChanged( const QString &value ); + +private: + void setupUi(); + void setupConnections(); + void disableConnections(); + + + QLineEdit *lineEdit; + QToolButton *toolButton; +}; + +#endif + diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index e3594edb0..e7029dd37 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -26,6 +26,8 @@ #include "widget_info_tree.h" #include +#include "action_property_manager.h" + namespace { class NelBMAlign @@ -368,9 +370,11 @@ namespace GUIEditor browser = NULL; propertyMgr = new QtVariantPropertyManager; enumMgr = new QtEnumPropertyManager; + actionMgr = new ActionPropertyManager; variantFactory = new QtVariantEditorFactory; enumFactory = new QtEnumEditorFactory; + actionFactory = new ActionEditorFactory; ttPairs[ "tooltip_posref" ] = "tooltip_parent_posref"; ttPairs[ "tooltip_parent_posref" ] = "tooltip_posref"; @@ -381,11 +385,15 @@ namespace GUIEditor CPropBrowserCtrl::~CPropBrowserCtrl() { + delete actionMgr; + actionMgr = NULL; delete enumMgr; enumMgr = NULL; delete propertyMgr; propertyMgr = NULL; + delete actionFactory; + actionFactory = NULL; delete variantFactory; variantFactory = NULL; delete enumFactory; @@ -447,7 +455,7 @@ namespace GUIEditor // probably the clear() method clears them too... browser->setFactoryForManager( propertyMgr, variantFactory ); browser->setFactoryForManager( enumMgr, enumFactory ); - + browser->setFactoryForManager( actionMgr, actionFactory ); enablePropertyWatchers(); } @@ -617,12 +625,27 @@ namespace GUIEditor } } + + void CPropBrowserCtrl::onActionPropertyChanged( QtProperty *p, const QString &v ) + { + QString propName = p->propertyName(); + + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); + } + void CPropBrowserCtrl::enablePropertyWatchers() { connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); connect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + + connect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::disablePropertyWatchers() @@ -631,6 +654,9 @@ namespace GUIEditor this, SLOT( onPropertyChanged( QtProperty*, const QVariant& ) ) ); disconnect( enumMgr, SIGNAL( valueChanged( QtProperty*, int ) ), this, SLOT( onEnumPropertyChanged( QtProperty*, int ) ) ); + + disconnect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) @@ -656,7 +682,22 @@ namespace GUIEditor { QtVariantProperty *p = NULL; QVariant v; - + + if( prop.propType == "action" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + QtProperty *pp = actionMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + actionMgr->setValue( pp, j.c_str() ); + browser->addProperty( pp ); + } + else if( prop.propType == "bitmap_align" ) { std::string j = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index bec4004d3..80118bc0b 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -31,6 +31,9 @@ class QtEnumEditorFactory; class QtProperty; class QVariant; +class ActionPropertyManager; +class ActionEditorFactory; + namespace NLGUI { class CInterfaceElement; @@ -59,6 +62,7 @@ namespace GUIEditor private Q_SLOTS: void onPropertyChanged( QtProperty *prop, const QVariant &v ); void onEnumPropertyChanged( QtProperty *prop, int value ); + void onActionPropertyChanged( QtProperty *p, const QString &v ); private: void enablePropertyWatchers(); @@ -70,9 +74,11 @@ namespace GUIEditor QtTreePropertyBrowser *browser; QtVariantPropertyManager *propertyMgr; QtEnumPropertyManager *enumMgr; + ActionPropertyManager *actionMgr; QtVariantEditorFactory *variantFactory; QtEnumEditorFactory *enumFactory; + ActionEditorFactory *actionFactory; std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; diff --git a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml index 72e362556..33f9f3a3f 100644 --- a/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml +++ b/code/studio/src/plugins/gui_editor/widgets/CtrlBaseButton.xml @@ -60,7 +60,7 @@ onover - string + action @@ -70,7 +70,7 @@ onclick_l - string + action @@ -80,7 +80,7 @@ ondblclick_l - string + action @@ -90,7 +90,7 @@ onclick_r - string + action @@ -100,7 +100,7 @@ onlongclick_l - string + action @@ -110,7 +110,7 @@ onclock_tick - string + action diff --git a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml index b374bca19..3d879a150 100644 --- a/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml +++ b/code/studio/src/plugins/gui_editor/widgets/GroupContainer.xml @@ -110,7 +110,7 @@ on_open - string + action @@ -120,7 +120,7 @@ on_close - string + action @@ -130,7 +130,7 @@ on_close_button - string + action @@ -140,7 +140,7 @@ on_move - string + action @@ -150,7 +150,7 @@ on_deactive_check - string + action @@ -160,7 +160,7 @@ on_resize - string + action @@ -170,7 +170,7 @@ on_alpha_settings_changed - string + action @@ -180,7 +180,7 @@ on_begin_move - string + action diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml index b9e99d336..ddcdf01e6 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroup.xml @@ -40,7 +40,7 @@ on_active - string + action @@ -50,7 +50,7 @@ on_deactive - string + action @@ -80,7 +80,7 @@ group_onclick_r - string + action @@ -90,7 +90,7 @@ group_onclick_l - string + action @@ -100,7 +100,7 @@ on_enter - string + action handler diff --git a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml index 62d67cc0a..b095ecac5 100644 --- a/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml +++ b/code/studio/src/plugins/gui_editor/widgets/InterfaceGroupWheel.xml @@ -10,7 +10,7 @@ on_wheel_up - string + action @@ -20,7 +20,7 @@ on_wheel_down - string + action From 559968ba41675479d2daeae3e6c5ca9eed492e14 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 8 Jul 2014 18:59:30 +0200 Subject: [PATCH 099/220] Added texture property editor, editor factory, manager. Textures can now be selected using these in the property tree browser. --- .../src/plugins/gui_editor/CMakeLists.txt | 1 + .../gui_editor/property_browser_ctrl.cpp | 38 ++ .../gui_editor/property_browser_ctrl.h | 5 + .../gui_editor/texture_property_manager.cpp | 333 ++++++++++++++++++ .../gui_editor/texture_property_manager.h | 125 +++++++ .../plugins/gui_editor/widgets/ViewBitmap.xml | 2 +- 6 files changed, 503 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/gui_editor/texture_property_manager.cpp create mode 100644 code/studio/src/plugins/gui_editor/texture_property_manager.h diff --git a/code/studio/src/plugins/gui_editor/CMakeLists.txt b/code/studio/src/plugins/gui_editor/CMakeLists.txt index f95e6c0a7..4b50ec8d1 100644 --- a/code/studio/src/plugins/gui_editor/CMakeLists.txt +++ b/code/studio/src/plugins/gui_editor/CMakeLists.txt @@ -33,6 +33,7 @@ SET(OVQT_PLUGIN_GUI_EDITOR_HDR action_list.h texture_chooser.h action_property_manager.h + texture_property_manager.h ) SET(OVQT_PLUGIN_GUI_EDITOR_UIS diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp index e7029dd37..bd73fb7fa 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.cpp @@ -27,6 +27,7 @@ #include #include "action_property_manager.h" +#include "texture_property_manager.h" namespace { @@ -371,10 +372,12 @@ namespace GUIEditor propertyMgr = new QtVariantPropertyManager; enumMgr = new QtEnumPropertyManager; actionMgr = new ActionPropertyManager; + textureMgr = new TexturePropertyManager; variantFactory = new QtVariantEditorFactory; enumFactory = new QtEnumEditorFactory; actionFactory = new ActionEditorFactory; + textureFactory = new TextureEditorFactory; ttPairs[ "tooltip_posref" ] = "tooltip_parent_posref"; ttPairs[ "tooltip_parent_posref" ] = "tooltip_posref"; @@ -385,6 +388,8 @@ namespace GUIEditor CPropBrowserCtrl::~CPropBrowserCtrl() { + delete textureMgr; + textureMgr = NULL; delete actionMgr; actionMgr = NULL; delete enumMgr; @@ -392,6 +397,8 @@ namespace GUIEditor delete propertyMgr; propertyMgr = NULL; + delete textureFactory; + textureFactory = NULL; delete actionFactory; actionFactory = NULL; delete variantFactory; @@ -456,6 +463,7 @@ namespace GUIEditor browser->setFactoryForManager( propertyMgr, variantFactory ); browser->setFactoryForManager( enumMgr, enumFactory ); browser->setFactoryForManager( actionMgr, actionFactory ); + browser->setFactoryForManager( textureMgr, textureFactory ); enablePropertyWatchers(); } @@ -637,6 +645,17 @@ namespace GUIEditor e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); } + void CPropBrowserCtrl::onTexturePropertyChanged( QtProperty *p, const QString &v ) + { + QString propName = p->propertyName(); + + CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); + if( e == NULL ) + return; + + e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); + } + void CPropBrowserCtrl::enablePropertyWatchers() { connect( propertyMgr, SIGNAL( valueChanged( QtProperty*, const QVariant& ) ), @@ -646,6 +665,8 @@ namespace GUIEditor connect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); + connect( textureMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onTexturePropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::disablePropertyWatchers() @@ -657,6 +678,8 @@ namespace GUIEditor disconnect( actionMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onActionPropertyChanged( QtProperty*, const QString& ) ) ); + disconnect( textureMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onTexturePropertyChanged( QtProperty*, const QString& ) ) ); } void CPropBrowserCtrl::setupProperties( const std::string &type, const CInterfaceElement *element ) @@ -683,6 +706,21 @@ namespace GUIEditor QtVariantProperty *p = NULL; QVariant v; + if( prop.propType == "texture" ) + { + std::string j = element->getProperty( prop.propName ); + + if( j.empty() ) + return; + + QtProperty *pp = textureMgr->addProperty( prop.propName.c_str() ); + if( pp == NULL ) + return; + + textureMgr->setValue( pp, j.c_str() ); + browser->addProperty( pp ); + } + else if( prop.propType == "action" ) { std::string j = element->getProperty( prop.propName ); diff --git a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h index 80118bc0b..abf80d7de 100644 --- a/code/studio/src/plugins/gui_editor/property_browser_ctrl.h +++ b/code/studio/src/plugins/gui_editor/property_browser_ctrl.h @@ -33,6 +33,8 @@ class QVariant; class ActionPropertyManager; class ActionEditorFactory; +class TexturePropertyManager; +class TextureEditorFactory; namespace NLGUI { @@ -63,6 +65,7 @@ namespace GUIEditor void onPropertyChanged( QtProperty *prop, const QVariant &v ); void onEnumPropertyChanged( QtProperty *prop, int value ); void onActionPropertyChanged( QtProperty *p, const QString &v ); + void onTexturePropertyChanged( QtProperty *p, const QString &v ); private: void enablePropertyWatchers(); @@ -75,10 +78,12 @@ namespace GUIEditor QtVariantPropertyManager *propertyMgr; QtEnumPropertyManager *enumMgr; ActionPropertyManager *actionMgr; + TexturePropertyManager *textureMgr; QtVariantEditorFactory *variantFactory; QtEnumEditorFactory *enumFactory; ActionEditorFactory *actionFactory; + TextureEditorFactory *textureFactory; std::string currentElement; std::map< std::string, SWidgetInfo > widgetInfo; diff --git a/code/studio/src/plugins/gui_editor/texture_property_manager.cpp b/code/studio/src/plugins/gui_editor/texture_property_manager.cpp new file mode 100644 index 000000000..6b40abc7f --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_property_manager.cpp @@ -0,0 +1,333 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "texture_property_manager.h" +#include "texture_chooser.h" +#include +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + + +struct TexturePropertyManagerPrivate +{ + QMap< const QtProperty*, QString > values; +}; + +TexturePropertyManager::TexturePropertyManager( QObject *parent ) : +QtAbstractPropertyManager( parent ) +{ + d_ptr = new TexturePropertyManagerPrivate(); +} + +TexturePropertyManager::~TexturePropertyManager() +{ + delete d_ptr; + d_ptr = NULL; +} + +QString TexturePropertyManager::value( const QtProperty *p ) const +{ + return valueText( p ); +} + +void TexturePropertyManager::setValue( QtProperty *p, const QString &value ) +{ + if( !d_ptr->values.contains( p ) ) + return; + + if( d_ptr->values[ p ] == value ) + return; + + d_ptr->values[ p ] = value; + + Q_EMIT propertyChanged( p ); + Q_EMIT valueChanged( p, value ); +} + +bool TexturePropertyManager::hasValue( const QtProperty *p ) const +{ + return d_ptr->values.contains( p ); +} + +QString TexturePropertyManager::valueText( const QtProperty *p ) const +{ + if( !d_ptr->values.contains( p ) ) + return ""; + + return d_ptr->values[ p ]; +} + +void TexturePropertyManager::initializeProperty( QtProperty *p ) +{ + if( d_ptr->values.contains( p ) ) + return; + + d_ptr->values[ p ] = ""; +} + +void TexturePropertyManager::uninitializeProperty( QtProperty *p ) +{ + d_ptr->values.remove( p ); +} + + + +//////////////////////////////////////////////////////////////////// Factory /////////////////////////////////////////////////////////////////////// + + + +struct TextureEditorFactoryPrivate +{ + QMap< QtProperty*, QList< TexturePropertyEditor* > > createdEditors; + QMap< TexturePropertyEditor*, QtProperty* > editorToProperty; + + ~TextureEditorFactoryPrivate() + { + createdEditors.clear(); + + QMap< TexturePropertyEditor*, QtProperty* >::iterator itr = editorToProperty.begin(); + while( itr != editorToProperty.end() ) + { + delete itr.key(); + ++itr; + } + editorToProperty.clear(); + } + + void addEditor( QtProperty *p, TexturePropertyEditor *editor ) + { + QMap< QtProperty*, QList< TexturePropertyEditor* > >::iterator itr = createdEditors.find( p ); + + if( itr != createdEditors.end() ) + { + itr->push_back( editor ); + } + else + { + QList< TexturePropertyEditor* > l; + l.push_back( editor ); + createdEditors.insert( p, l ); + } + + editorToProperty.insert( editor, p ); + } + + void removeEditor( QObject *o ) + { + // Remove from editorToProperty first + QMap< TexturePropertyEditor*, QtProperty* >::iterator itr1 = editorToProperty.begin(); + while( itr1 != editorToProperty.end() ) + { + if( itr1.key() == o ) + break; + + ++itr1; + } + if( itr1 != editorToProperty.end() ) + editorToProperty.erase( itr1 ); + + // Then from createdEditors + QMap< QtProperty*, QList< TexturePropertyEditor* > >::iterator itr2 = createdEditors.begin(); + while( itr2 != createdEditors.end() ) + { + QList< TexturePropertyEditor* > &l = *itr2; + QList< TexturePropertyEditor* >::iterator itr = l.begin(); + while( itr != l.end() ) + { + if( *itr == o ) + { + QList< TexturePropertyEditor* >::iterator d = itr; + ++itr; + l.erase( d ); + continue; + } + + ++itr; + } + + ++itr2; + } + } + +}; + +TextureEditorFactory::TextureEditorFactory( QObject *parent ) : +QtAbstractEditorFactory( parent ) +{ + d_ptr = new TextureEditorFactoryPrivate(); +} + +TextureEditorFactory::~TextureEditorFactory() +{ + delete d_ptr; + d_ptr = NULL; +} + +void TextureEditorFactory::connectPropertyManager( TexturePropertyManager *manager ) +{ + connect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +void TextureEditorFactory::disconnectPropertyManager( TexturePropertyManager *manager ) +{ + disconnect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); +} + +QWidget* TextureEditorFactory::createEditor( TexturePropertyManager *manager, QtProperty *p, QWidget *parent ) +{ + TexturePropertyEditor *editor = new TexturePropertyEditor( parent ); + editor->setValue( manager->value( p ) ); + + connect( editor, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onSetValue( const QString& ) ) ); + connect( editor, SIGNAL( destroyed( QObject* ) ), this, SLOT( onEditorDestroyed( QObject* ) ) ); + + d_ptr->addEditor( p, editor ); + + return editor; +} + +void TextureEditorFactory::onPropertyChanged( QtProperty *p, const QString &value ) +{ + QMap< QtProperty*, QList< TexturePropertyEditor* > >::iterator itr = d_ptr->createdEditors.find( p ); + if( itr == d_ptr->createdEditors.end() ) + return; + + QList< TexturePropertyEditor* > &l = *itr; + QList< TexturePropertyEditor* >::iterator i = l.begin(); + while( i != l.end() ) + { + TexturePropertyEditor *editor = *i; + + editor->blockSignals( true ); + editor->setValue( value ); + editor->blockSignals( false ); + + ++i; + } +} + +void TextureEditorFactory::onSetValue( const QString &value ) +{ + QObject *s = sender(); + TexturePropertyEditor *editor = qobject_cast< TexturePropertyEditor* >( s ); + if( editor == NULL ) + return; + + QMap< TexturePropertyEditor*, QtProperty* >::iterator itr = d_ptr->editorToProperty.find( editor ); + if( itr == d_ptr->editorToProperty.end() ) + return; + + QtProperty *p = *itr; + + TexturePropertyManager *manager = qobject_cast< TexturePropertyManager* >( p->propertyManager() ); + if( manager == NULL ) + return; + + blockSignals( true ); + manager->setValue( p, value ); + blockSignals( false ); +} + +void TextureEditorFactory::onEditorDestroyed( QObject *editor ) +{ + d_ptr->removeEditor( editor ); +} + + + +//////////////////////////////////////////////////////////////////////// Editor ////////////////////////////////////////////////////////////////// + + + +TexturePropertyEditor::TexturePropertyEditor( QWidget *parent ) : +QWidget( parent ) +{ + setupUi(); + setupConnections(); +} + +TexturePropertyEditor::~TexturePropertyEditor() +{ +} + +void TexturePropertyEditor::setValue( const QString &value ) +{ + if( lineEdit->text() == value ) + return; + + disableConnections(); + lineEdit->setText( value ); + setupConnections(); +} + +void TexturePropertyEditor::showEvent( QShowEvent *e ) +{ + QWidget::showEvent( e ); +} + +void TexturePropertyEditor::onToolButtonClicked() +{ + TextureChooser d; + d.load(); + + int result = d.exec(); + if( QDialog::Accepted != result ) + return; + + lineEdit->setText( d.getSelection() ); +} + +void TexturePropertyEditor::onTextChanged( const QString &text ) +{ + Q_EMIT valueChanged( text ); +} + +void TexturePropertyEditor::setupConnections() +{ + connect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + connect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void TexturePropertyEditor::disableConnections() +{ + disconnect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + disconnect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void TexturePropertyEditor::setupUi() +{ + lineEdit = new QLineEdit(); + toolButton = new QToolButton(); + toolButton->setText( "..." ); + + QHBoxLayout *lt = new QHBoxLayout( this ); + lt->setContentsMargins( 0, 0, 0, 0 ); + lt->setSpacing( 0 ); + lt->addWidget( lineEdit ); + lt->addWidget( toolButton ); + + setFocusProxy( lineEdit ); + setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); + +} + + diff --git a/code/studio/src/plugins/gui_editor/texture_property_manager.h b/code/studio/src/plugins/gui_editor/texture_property_manager.h new file mode 100644 index 000000000..9b686ea04 --- /dev/null +++ b/code/studio/src/plugins/gui_editor/texture_property_manager.h @@ -0,0 +1,125 @@ +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TEXTURE_PROPERTY_MANAGER +#define TEXTURE_PROPERTY_MANAGER + +#define QT_QTPROPERTYBROWSER_IMPORT + +#include "3rdparty/qtpropertybrowser/qtpropertybrowser.h" +#include + +/////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + +struct TexturePropertyManagerPrivate; + +class TexturePropertyManager : public QtAbstractPropertyManager +{ + Q_OBJECT + +public: + TexturePropertyManager( QObject *parent = NULL ); + ~TexturePropertyManager(); + + QString value( const QtProperty *p ) const; + +public Q_SLOTS: + void setValue( QtProperty *p, const QString &value ); + +Q_SIGNALS: + void valueChanged( QtProperty *p, const QString &value ); + +protected: + bool hasValue( const QtProperty *p ) const; + QString valueText( const QtProperty *p ) const; + void initializeProperty( QtProperty *p ); + void uninitializeProperty( QtProperty *p ); + +private: + TexturePropertyManagerPrivate *d_ptr; + + Q_DISABLE_COPY( TexturePropertyManager ); +}; + + +////////////////////////////////////////////////////////////////// Factory ///////////////////////////////////////////////////////////////////////// + +struct TextureEditorFactoryPrivate; + +class TextureEditorFactory : public QtAbstractEditorFactory< TexturePropertyManager > +{ + Q_OBJECT + +public: + TextureEditorFactory( QObject *parent = NULL ); + ~TextureEditorFactory(); + +protected: + void connectPropertyManager( TexturePropertyManager *manager ); + void disconnectPropertyManager( TexturePropertyManager *manager ); + + QWidget* createEditor( TexturePropertyManager *manager, QtProperty *p, QWidget *parent ); + +private Q_SLOTS: + void onPropertyChanged( QtProperty *p, const QString &value ); + void onSetValue( const QString &value ); + void onEditorDestroyed( QObject *editor ); + +private: + TextureEditorFactoryPrivate *d_ptr; + + Q_DISABLE_COPY( TextureEditorFactory ); +}; + + +///////////////////////////////////////////////////////////////// Editor /////////////////////////////////////////////////////////////////////////// + +class QLineEdit; +class QToolButton; + +class TexturePropertyEditor : public QWidget +{ + Q_OBJECT +public: + TexturePropertyEditor( QWidget *parent = NULL ); + ~TexturePropertyEditor(); + +public Q_SLOTS: + void setValue( const QString &value ); + +protected: + void showEvent( QShowEvent *e ); + +private Q_SLOTS: + void onToolButtonClicked(); + void onTextChanged( const QString &text ); + +Q_SIGNALS: + void valueChanged( const QString &value ); + +private: + void setupUi(); + void setupConnections(); + void disableConnections(); + + + QLineEdit *lineEdit; + QToolButton *toolButton; +}; + +#endif + diff --git a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml index c39ecbabc..21ef7daff 100644 --- a/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml +++ b/code/studio/src/plugins/gui_editor/widgets/ViewBitmap.xml @@ -35,7 +35,7 @@ texture - string + texture From 2ca6c73d097d0a05b24ec2c0270f71d2494b5ac6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 21:07:12 +0200 Subject: [PATCH 100/220] Texture chooser now supports atlas textures as well. --- code/nel/include/nel/gui/view_renderer.h | 6 ++ code/nel/src/gui/view_renderer.cpp | 40 ++++++++ .../plugins/gui_editor/texture_chooser.cpp | 97 ++++++++++++++++--- .../src/plugins/gui_editor/texture_chooser.h | 13 ++- .../src/plugins/gui_editor/texture_chooser.ui | 8 +- 5 files changed, 146 insertions(+), 18 deletions(-) diff --git a/code/nel/include/nel/gui/view_renderer.h b/code/nel/include/nel/gui/view_renderer.h index 83ac4457e..fe5dad405 100644 --- a/code/nel/include/nel/gui/view_renderer.h +++ b/code/nel/include/nel/gui/view_renderer.h @@ -286,6 +286,12 @@ namespace NLGUI */ void flush (); + /// Retrives a texture + bool getTexture( NLMISC::CBitmap &bm, const std::string &name ); + + /// Retrieve the texture names + void getTextureNames( std::vector< std::string > &textures ); + /** * get a texture file pointer from a string name. O(logN) * \param id : the id of the texture diff --git a/code/nel/src/gui/view_renderer.cpp b/code/nel/src/gui/view_renderer.cpp index b2758c634..6e6675599 100644 --- a/code/nel/src/gui/view_renderer.cpp +++ b/code/nel/src/gui/view_renderer.cpp @@ -1064,6 +1064,46 @@ namespace NLGUI } } + bool CViewRenderer::getTexture( NLMISC::CBitmap &bm, const std::string &name ) + { + TTextureMap::const_iterator itr = _TextureMap.find( name ); + if( itr == _TextureMap.end() ) + return false; + + sint32 id = itr->second; + SImage *si = getSImage( id ); + NLMISC::CBitmap *src = si->GlobalTexturePtr->Texture->generateDatas(); + + if( src->getPixelFormat() != NLMISC::CBitmap::RGBA ) + return false; + + uint x0 = (uint)( si->UVMin.U * si->GlobalTexturePtr->Width ); + uint y0 = (uint)( si->UVMin.V * si->GlobalTexturePtr->Height ); + uint x1 = (uint)( si->UVMax.U * si->GlobalTexturePtr->Width ); + uint y1 = (uint)( si->UVMax.V * si->GlobalTexturePtr->Height ); + + if( x1 == x0 ) + return false; + + if( y1 == y0 ) + return false; + + bm.resize( x1 - x0, y1 - y0 ); + bm.blit( *src, x0, y0, ( x1 - x0 ), ( y1 - y0 ), 0, 0 ); + + return true; + } + + void CViewRenderer::getTextureNames( std::vector< std::string > &textures ) + { + TTextureMap::const_iterator itr = _TextureMap.begin(); + while( itr != _TextureMap.end() ) + { + textures.push_back( itr->first ); + ++itr; + } + } + /* * getTextureIdFromName */ diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index d857d9bdc..1c5e692ee 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -6,40 +6,81 @@ #include #include #include +#include + +#include "nel/gui/view_renderer.h" + +struct TextureChooserPrivate +{ + QListWidget *fileTextures; + QListWidget *atlasTextures; + + TextureChooserPrivate() + { + fileTextures = new QListWidget(); + atlasTextures = new QListWidget(); + } +}; TextureChooser::TextureChooser( QDialog *parent ) : QDialog( parent ) { setupUi( this ); + + d_ptr = new TextureChooserPrivate; + this->tabWidget->clear(); + this->tabWidget->addTab( d_ptr->fileTextures, tr( "File textures" ) ); + this->tabWidget->addTab( d_ptr->atlasTextures, tr( "Atlas texture" ) ); + setupConnections(); } TextureChooser::~TextureChooser() { + delete d_ptr; + d_ptr = NULL; } void TextureChooser::load() { - listWidget->clear(); + // Load the file textures + d_ptr->fileTextures->clear(); std::vector< std::string > textures; //NLMISC::CPath::getFileList( "tga", textures ); - NLMISC::CPath::getFileListByPath( "tga", "interfaces", textures ); + NLMISC::CPath::getFileListByPath( "dds", "interfaces", textures ); + NLMISC::CPath::getFileListByPath( "dds", "gamedev", textures ); + + std::sort( textures.begin(), textures.end() ); std::vector< std::string >::const_iterator itr = textures.begin(); while( itr != textures.end() ) { - listWidget->addItem( itr->c_str() ); + d_ptr->fileTextures->addItem( itr->c_str() ); ++itr; } - listWidget->setCurrentRow( 0 ); + // Now load the atlas textures + d_ptr->atlasTextures->clear(); + textures.clear(); + + NLGUI::CViewRenderer::getInstance()->getTextureNames( textures ); + itr = textures.begin(); + while( itr != textures.end() ) + { + d_ptr->atlasTextures->addItem( itr->c_str() ); + ++itr; + } + + // set the file textures row after the atlas, because they are shown first + d_ptr->atlasTextures->setCurrentRow( 0 ); + d_ptr->fileTextures->setCurrentRow( 0 ); } void TextureChooser::accept() { - QListWidgetItem *item = listWidget->currentItem(); + QListWidgetItem *item = d_ptr->fileTextures->currentItem(); if( item == NULL ) return; @@ -54,12 +95,12 @@ void TextureChooser::reject() QDialog::reject(); } -void TextureChooser::onCurrentRowChanged( int row ) +void TextureChooser::onFileTxtRowChanged( int row ) { if( row < 0 ) return; - QListWidgetItem *item = listWidget->item( row ); + QListWidgetItem *item = d_ptr->fileTextures->item( row ); QString fn = item->text(); std::string rfn = fn.toUtf8().constData(); @@ -81,11 +122,42 @@ void TextureChooser::onCurrentRowChanged( int row ) return; } - uint32 size = bm.getSize() * ( 32 / 8 ); // should be depth, but CBitmap always uses 32 bit to store the image + setPreviewImage( bm ); +} +void TextureChooser::onAtlasTxtRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = d_ptr->atlasTextures->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + + NLMISC::CBitmap bm; + + bool b = NLGUI::CViewRenderer::getInstance()->getTexture( bm, rfn ); + if( !b ) + return; + + setPreviewImage( bm ); +} + + +void TextureChooser::setupConnections() +{ + connect( d_ptr->fileTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onFileTxtRowChanged( int ) ) ); + connect( d_ptr->atlasTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onAtlasTxtRowChanged( int ) ) ); +} + +void TextureChooser::setPreviewImage( NLMISC::CBitmap &bm ) +{ + // should be depth, but CBitmap always uses 32 bit to store the image + uint32 size = bm.getSize() * ( 32 / 8 ); uint8 *data = new uint8[ size ]; bm.getData( data ); - + /// Convert from ABGR to ARGB { int i = 0; @@ -107,13 +179,6 @@ void TextureChooser::onCurrentRowChanged( int row ) delete data; data = NULL; - -} - - -void TextureChooser::setupConnections() -{ - connect( listWidget, SIGNAL( currentRowChanged( int ) ), this, SLOT( onCurrentRowChanged( int ) ) ); } diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index bab1dd1dc..9a615c266 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -3,6 +3,13 @@ #include "ui_texture_chooser.h" +namespace NLMISC +{ + class CBitmap; +} + +struct TextureChooserPrivate; + class TextureChooser : public QDialog, public Ui::TextureChooser { Q_OBJECT @@ -19,12 +26,16 @@ public Q_SLOTS: void reject(); private Q_SLOTS: - void onCurrentRowChanged( int row ); + void onFileTxtRowChanged( int row ); + void onAtlasTxtRowChanged( int row ); private: void setupConnections(); + void setPreviewImage( NLMISC::CBitmap &bm ); QString selection; + + TextureChooserPrivate *d_ptr; }; #endif diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.ui b/code/studio/src/plugins/gui_editor/texture_chooser.ui index 0f635e96f..a0837ee83 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.ui +++ b/code/studio/src/plugins/gui_editor/texture_chooser.ui @@ -18,7 +18,13 @@ - + + + + tab + + + From f694cfdb8e098fb736cb1b3925a9d7fcf4fca63e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 21:13:57 +0200 Subject: [PATCH 101/220] Copyright banner + line endings... I always mess this up somehow.. --- .../plugins/gui_editor/texture_chooser.cpp | 386 +++++++++--------- .../src/plugins/gui_editor/texture_chooser.h | 100 +++-- 2 files changed, 259 insertions(+), 227 deletions(-) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 1c5e692ee..57a0e8d51 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -1,185 +1,201 @@ -#include "texture_chooser.h" -#include "nel/misc/path.h" -#include "nel/misc/bitmap.h" -#include "nel/misc/file.h" -#include -#include -#include -#include -#include - -#include "nel/gui/view_renderer.h" - -struct TextureChooserPrivate -{ - QListWidget *fileTextures; - QListWidget *atlasTextures; - - TextureChooserPrivate() - { - fileTextures = new QListWidget(); - atlasTextures = new QListWidget(); - } -}; - -TextureChooser::TextureChooser( QDialog *parent ) : -QDialog( parent ) -{ - setupUi( this ); - - d_ptr = new TextureChooserPrivate; - this->tabWidget->clear(); - this->tabWidget->addTab( d_ptr->fileTextures, tr( "File textures" ) ); - this->tabWidget->addTab( d_ptr->atlasTextures, tr( "Atlas texture" ) ); - - setupConnections(); -} - -TextureChooser::~TextureChooser() -{ - delete d_ptr; - d_ptr = NULL; -} - - -void TextureChooser::load() -{ - // Load the file textures - d_ptr->fileTextures->clear(); - - std::vector< std::string > textures; - //NLMISC::CPath::getFileList( "tga", textures ); - NLMISC::CPath::getFileListByPath( "dds", "interfaces", textures ); - NLMISC::CPath::getFileListByPath( "dds", "gamedev", textures ); - - std::sort( textures.begin(), textures.end() ); - - std::vector< std::string >::const_iterator itr = textures.begin(); - while( itr != textures.end() ) - { - d_ptr->fileTextures->addItem( itr->c_str() ); - ++itr; - } - - // Now load the atlas textures - d_ptr->atlasTextures->clear(); - textures.clear(); - - NLGUI::CViewRenderer::getInstance()->getTextureNames( textures ); - itr = textures.begin(); - while( itr != textures.end() ) - { - d_ptr->atlasTextures->addItem( itr->c_str() ); - ++itr; - } - - // set the file textures row after the atlas, because they are shown first - d_ptr->atlasTextures->setCurrentRow( 0 ); - d_ptr->fileTextures->setCurrentRow( 0 ); -} - -void TextureChooser::accept() -{ - QListWidgetItem *item = d_ptr->fileTextures->currentItem(); - if( item == NULL ) - return; - - selection = item->text(); - QDialog::accept(); -} - -void TextureChooser::reject() -{ - selection = ""; - - QDialog::reject(); -} - -void TextureChooser::onFileTxtRowChanged( int row ) -{ - if( row < 0 ) - return; - - QListWidgetItem *item = d_ptr->fileTextures->item( row ); - QString fn = item->text(); - - std::string rfn = fn.toUtf8().constData(); - rfn = NLMISC::CPath::lookup( rfn ); - - NLMISC::CIFile f; - bool b = f.open( rfn ); - if( !b ) - { - return; - } - - NLMISC::CBitmap bm; - uint8 depth = bm.load( f ); - f.close(); - b = bm.convertToType( NLMISC::CBitmap::RGBA ); - if( !b ) - { - return; - } - - setPreviewImage( bm ); -} - -void TextureChooser::onAtlasTxtRowChanged( int row ) -{ - if( row < 0 ) - return; - - QListWidgetItem *item = d_ptr->atlasTextures->item( row ); - QString fn = item->text(); - - std::string rfn = fn.toUtf8().constData(); - - NLMISC::CBitmap bm; - - bool b = NLGUI::CViewRenderer::getInstance()->getTexture( bm, rfn ); - if( !b ) - return; - - setPreviewImage( bm ); -} - - -void TextureChooser::setupConnections() -{ - connect( d_ptr->fileTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onFileTxtRowChanged( int ) ) ); - connect( d_ptr->atlasTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onAtlasTxtRowChanged( int ) ) ); -} - -void TextureChooser::setPreviewImage( NLMISC::CBitmap &bm ) -{ - // should be depth, but CBitmap always uses 32 bit to store the image - uint32 size = bm.getSize() * ( 32 / 8 ); - uint8 *data = new uint8[ size ]; - bm.getData( data ); - - /// Convert from ABGR to ARGB - { - int i = 0; - while( i < size ) - { - uint8 t = 0; - - /// ABGR - t = data[ i ]; - data[ i ] = data[ i + 2 ]; - data[ i + 2 ] = t; - - i += 4; - } - } - - QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); - label->setPixmap( QPixmap::fromImage( img ) ); - - delete data; - data = NULL; -} - - - +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "texture_chooser.h" +#include "nel/misc/path.h" +#include "nel/misc/bitmap.h" +#include "nel/misc/file.h" +#include +#include +#include +#include +#include + +#include "nel/gui/view_renderer.h" + +struct TextureChooserPrivate +{ + QListWidget *fileTextures; + QListWidget *atlasTextures; + + TextureChooserPrivate() + { + fileTextures = new QListWidget(); + atlasTextures = new QListWidget(); + } +}; + +TextureChooser::TextureChooser( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + + d_ptr = new TextureChooserPrivate; + this->tabWidget->clear(); + this->tabWidget->addTab( d_ptr->fileTextures, tr( "File textures" ) ); + this->tabWidget->addTab( d_ptr->atlasTextures, tr( "Atlas texture" ) ); + + setupConnections(); +} + +TextureChooser::~TextureChooser() +{ + delete d_ptr; + d_ptr = NULL; +} + + +void TextureChooser::load() +{ + // Load the file textures + d_ptr->fileTextures->clear(); + + std::vector< std::string > textures; + //NLMISC::CPath::getFileList( "tga", textures ); + NLMISC::CPath::getFileListByPath( "dds", "interfaces", textures ); + NLMISC::CPath::getFileListByPath( "dds", "gamedev", textures ); + + std::sort( textures.begin(), textures.end() ); + + std::vector< std::string >::const_iterator itr = textures.begin(); + while( itr != textures.end() ) + { + d_ptr->fileTextures->addItem( itr->c_str() ); + ++itr; + } + + // Now load the atlas textures + d_ptr->atlasTextures->clear(); + textures.clear(); + + NLGUI::CViewRenderer::getInstance()->getTextureNames( textures ); + itr = textures.begin(); + while( itr != textures.end() ) + { + d_ptr->atlasTextures->addItem( itr->c_str() ); + ++itr; + } + + // set the file textures row after the atlas, because they are shown first + d_ptr->atlasTextures->setCurrentRow( 0 ); + d_ptr->fileTextures->setCurrentRow( 0 ); +} + +void TextureChooser::accept() +{ + QListWidgetItem *item = d_ptr->fileTextures->currentItem(); + if( item == NULL ) + return; + + selection = item->text(); + QDialog::accept(); +} + +void TextureChooser::reject() +{ + selection = ""; + + QDialog::reject(); +} + +void TextureChooser::onFileTxtRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = d_ptr->fileTextures->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + rfn = NLMISC::CPath::lookup( rfn ); + + NLMISC::CIFile f; + bool b = f.open( rfn ); + if( !b ) + { + return; + } + + NLMISC::CBitmap bm; + uint8 depth = bm.load( f ); + f.close(); + b = bm.convertToType( NLMISC::CBitmap::RGBA ); + if( !b ) + { + return; + } + + setPreviewImage( bm ); +} + +void TextureChooser::onAtlasTxtRowChanged( int row ) +{ + if( row < 0 ) + return; + + QListWidgetItem *item = d_ptr->atlasTextures->item( row ); + QString fn = item->text(); + + std::string rfn = fn.toUtf8().constData(); + + NLMISC::CBitmap bm; + + bool b = NLGUI::CViewRenderer::getInstance()->getTexture( bm, rfn ); + if( !b ) + return; + + setPreviewImage( bm ); +} + + +void TextureChooser::setupConnections() +{ + connect( d_ptr->fileTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onFileTxtRowChanged( int ) ) ); + connect( d_ptr->atlasTextures, SIGNAL( currentRowChanged( int ) ), this, SLOT( onAtlasTxtRowChanged( int ) ) ); +} + +void TextureChooser::setPreviewImage( NLMISC::CBitmap &bm ) +{ + // should be depth, but CBitmap always uses 32 bit to store the image + uint32 size = bm.getSize() * ( 32 / 8 ); + uint8 *data = new uint8[ size ]; + bm.getData( data ); + + /// Convert from ABGR to ARGB + { + int i = 0; + while( i < size ) + { + uint8 t = 0; + + /// ABGR + t = data[ i ]; + data[ i ] = data[ i + 2 ]; + data[ i + 2 ] = t; + + i += 4; + } + } + + QImage img( data, bm.getWidth(), bm.getHeight(), QImage::Format_ARGB32 ); + label->setPixmap( QPixmap::fromImage( img ) ); + + delete data; + data = NULL; +} + + + diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.h b/code/studio/src/plugins/gui_editor/texture_chooser.h index 9a615c266..160b31481 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.h +++ b/code/studio/src/plugins/gui_editor/texture_chooser.h @@ -1,42 +1,58 @@ -#ifndef TEXTURE_CHOOSER_H -#define TEXTURE_CHOOSER_H - -#include "ui_texture_chooser.h" - -namespace NLMISC -{ - class CBitmap; -} - -struct TextureChooserPrivate; - -class TextureChooser : public QDialog, public Ui::TextureChooser -{ - Q_OBJECT - -public: - TextureChooser( QDialog *parent = NULL ); - ~TextureChooser(); - - void load(); - QString getSelection(){ return selection; } - -public Q_SLOTS: - void accept(); - void reject(); - -private Q_SLOTS: - void onFileTxtRowChanged( int row ); - void onAtlasTxtRowChanged( int row ); - -private: - void setupConnections(); - void setPreviewImage( NLMISC::CBitmap &bm ); - - QString selection; - - TextureChooserPrivate *d_ptr; -}; - -#endif - +// Ryzom Core Studio GUI Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TEXTURE_CHOOSER_H +#define TEXTURE_CHOOSER_H + +#include "ui_texture_chooser.h" + +namespace NLMISC +{ + class CBitmap; +} + +struct TextureChooserPrivate; + +class TextureChooser : public QDialog, public Ui::TextureChooser +{ + Q_OBJECT + +public: + TextureChooser( QDialog *parent = NULL ); + ~TextureChooser(); + + void load(); + QString getSelection(){ return selection; } + +public Q_SLOTS: + void accept(); + void reject(); + +private Q_SLOTS: + void onFileTxtRowChanged( int row ); + void onAtlasTxtRowChanged( int row ); + +private: + void setupConnections(); + void setPreviewImage( NLMISC::CBitmap &bm ); + + QString selection; + + TextureChooserPrivate *d_ptr; +}; + +#endif + From a4ccf0b86c50ec10cc32e1873d90783e072f7e60 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 23:20:50 +0200 Subject: [PATCH 102/220] Workaround related to the unknown statusbar crash. --- .../src/plugins/landscape_editor/landscape_editor_window.cpp | 4 ++++ code/studio/src/plugins/world_editor/world_editor_window.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp b/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp index bbc996b94..aeca41906 100644 --- a/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp +++ b/code/studio/src/plugins/landscape_editor/landscape_editor_window.cpp @@ -104,6 +104,10 @@ LandscapeEditorWindow::~LandscapeEditorWindow() { writeSettings(); delete m_zoneBuilder; + + Core::ICore::instance()->mainWindow()->statusBar()->removeWidget( m_statusInfo ); + delete m_statusInfo; + m_statusInfo = NULL; } QUndoStack *LandscapeEditorWindow::undoStack() const diff --git a/code/studio/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp index b23e62063..afb667358 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_window.cpp @@ -121,6 +121,10 @@ WorldEditorWindow::~WorldEditorWindow() writeSettings(); delete m_zoneBuilderBase; + + Core::ICore::instance()->mainWindow()->statusBar()->removeWidget( m_statusInfo ); + delete m_statusInfo; + m_statusInfo = NULL; } QUndoStack *WorldEditorWindow::undoStack() const From 77b98d796c781bd95941c3cca9c324a1fdf71cb2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:35:05 +0200 Subject: [PATCH 103/220] Implemented const_string_array editor. --- .../src/plugins/world_editor/CMakeLists.txt | 3 + .../const_string_array_editor.cpp | 106 +++++ .../world_editor/const_string_array_editor.h | 50 +++ .../world_editor/const_string_array_editor.ui | 130 +++++++ .../const_string_array_property.cpp | 363 ++++++++++++++++++ .../const_string_array_property.h | 131 +++++++ .../world_editor/property_editor_widget.cpp | 30 +- .../world_editor/property_editor_widget.h | 6 + 8 files changed, 800 insertions(+), 19 deletions(-) create mode 100644 code/studio/src/plugins/world_editor/const_string_array_editor.cpp create mode 100644 code/studio/src/plugins/world_editor/const_string_array_editor.h create mode 100644 code/studio/src/plugins/world_editor/const_string_array_editor.ui create mode 100644 code/studio/src/plugins/world_editor/const_string_array_property.cpp create mode 100644 code/studio/src/plugins/world_editor/const_string_array_property.h diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index 7b76ed810..ac5231aea 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -20,12 +20,15 @@ SET(OVQT_PLUGIN_WORLD_EDITOR_HDR world_editor_plugin.h project_settings_dialog.h property_editor_widget.h world_editor_settings_page.h + const_string_array_property.h + const_string_array_editor.h ) SET(OVQT_PLUGIN_WORLD_EDITOR_UIS world_editor_window.ui project_settings_dialog.ui property_editor_widget.ui world_editor_settings_page.ui + const_string_array_editor.ui ) SET(OVQT_PLUGIN_WORLD_EDITOR_RCS world_editor.qrc) diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.cpp b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp new file mode 100644 index 000000000..05e5e4cf5 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp @@ -0,0 +1,106 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "const_string_array_editor.h" + +ConstStrArrEditDialog::ConstStrArrEditDialog( QDialog *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); +} + +ConstStrArrEditDialog::~ConstStrArrEditDialog() +{ +} + +void ConstStrArrEditDialog::setStrings( const QStringList &strings ) +{ + cb->clear(); + + QStringListIterator itr( strings ); + while( itr.hasNext() ) + { + cb->addItem( itr.next() ); + } + + cb->setCurrentIndex( 0 ); +} + +void ConstStrArrEditDialog::setValue( const QString &value ) +{ + listWidget->clear(); + + if( value.isEmpty() ) + return; + + QStringList l = value.split( ';' ); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + listWidget->addItem( itr.next() ); + } +} + +QString ConstStrArrEditDialog::getValue() const +{ + QString value; + + for( int i = 0; i < listWidget->count(); i++ ) + { + QListWidgetItem *item = listWidget->item( i ); + value += item->text(); + + if( i < ( listWidget->count() - 1 ) ) + value += ';'; + } + + return value; +} + +void ConstStrArrEditDialog::accept() +{ + QDialog::accept(); +} + +void ConstStrArrEditDialog::reject() +{ + QDialog::reject(); +} + +void ConstStrArrEditDialog::onAddClicked() +{ + listWidget->addItem( cb->currentText() ); +} + +void ConstStrArrEditDialog::onRemoveClicked() +{ + QListWidgetItem *item = listWidget->currentItem(); + if( item == NULL ) + return; + + delete item; +} + +void ConstStrArrEditDialog::setupConnections() +{ + connect( addButton, SIGNAL( clicked( bool ) ), this, SLOT( onAddClicked() ) ); + connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveClicked() ) ); +} + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.h b/code/studio/src/plugins/world_editor/const_string_array_editor.h new file mode 100644 index 000000000..a2c458e7c --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.h @@ -0,0 +1,50 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef CONST_STR_ARR_EDIT_DLG +#define CONST_STR_ARR_EDIT_DLG + +#include "ui_const_string_array_editor.h" +#include + +class ConstStrArrEditDialog : public QDialog, public Ui::ConstStrArrEditorDialog +{ + Q_OBJECT +public: + ConstStrArrEditDialog( QDialog *parent = NULL ); + ~ConstStrArrEditDialog(); + + void setStrings( const QStringList &strings ); + void setValue( const QString &value ); + QString getValue() const; + +public Q_SLOTS: + void accept(); + void reject(); + +private Q_SLOTS: + void onAddClicked(); + void onRemoveClicked(); + +private: + void setupConnections(); +}; + + +#endif + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.ui b/code/studio/src/plugins/world_editor/const_string_array_editor.ui new file mode 100644 index 000000000..6aec02352 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.ui @@ -0,0 +1,130 @@ + + + ConstStrArrEditorDialog + + + + 0 + 0 + 392 + 293 + + + + Dialog + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Add + + + + + + + + 0 + 0 + + + + Remove + + + + + + + + + + 6 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + okButton + clicked() + ConstStrArrEditorDialog + accept() + + + 278 + 253 + + + 96 + 254 + + + + + cancelButton + clicked() + ConstStrArrEditorDialog + reject() + + + 369 + 253 + + + 179 + 282 + + + + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_property.cpp b/code/studio/src/plugins/world_editor/const_string_array_property.cpp new file mode 100644 index 000000000..5ef7566d8 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_property.cpp @@ -0,0 +1,363 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "const_string_array_property.h" +#include "const_string_array_editor.h" +#include +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + + +struct ConstStrArrPropMgrPriv +{ + QMap< const QtProperty*, QString > values; +}; + +ConstStrArrPropMgr::ConstStrArrPropMgr( QObject *parent ) : +QtAbstractPropertyManager( parent ) +{ + d_ptr = new ConstStrArrPropMgrPriv(); +} + +ConstStrArrPropMgr::~ConstStrArrPropMgr() +{ + delete d_ptr; + d_ptr = NULL; +} + +QString ConstStrArrPropMgr::value( const QtProperty *p ) const +{ + return valueText( p ); +} + +void ConstStrArrPropMgr::setValue( QtProperty *p, const QString &value ) +{ + if( !d_ptr->values.contains( p ) ) + return; + + if( d_ptr->values[ p ] == value ) + return; + + d_ptr->values[ p ] = value; + + Q_EMIT propertyChanged( p ); + Q_EMIT valueChanged( p, value ); +} + +void ConstStrArrPropMgr::setStrings( QtProperty *p, const QStringList &strings ) +{ + Q_EMIT stringsChanged( p, strings ); +} + +bool ConstStrArrPropMgr::hasValue( const QtProperty *p ) const +{ + return d_ptr->values.contains( p ); +} + +QString ConstStrArrPropMgr::valueText( const QtProperty *p ) const +{ + if( !d_ptr->values.contains( p ) ) + return ""; + + return d_ptr->values[ p ]; +} + +void ConstStrArrPropMgr::initializeProperty( QtProperty *p ) +{ + if( d_ptr->values.contains( p ) ) + return; + + d_ptr->values[ p ] = ""; +} + +void ConstStrArrPropMgr::uninitializeProperty( QtProperty *p ) +{ + d_ptr->values.remove( p ); +} + + + +//////////////////////////////////////////////////////////////////// Factory /////////////////////////////////////////////////////////////////////// + + + +struct ConstStrArrEditorFactoryPriv +{ + QMap< QtProperty*, QList< ConstStrArrEditor* > > createdEditors; + QMap< ConstStrArrEditor*, QtProperty* > editorToProperty; + QMap< QtProperty*, QStringList > strings; + + ~ConstStrArrEditorFactoryPriv() + { + createdEditors.clear(); + + QMap< ConstStrArrEditor*, QtProperty* >::iterator itr = editorToProperty.begin(); + while( itr != editorToProperty.end() ) + { + delete itr.key(); + ++itr; + } + editorToProperty.clear(); + } + + void addEditor( QtProperty *p, ConstStrArrEditor *editor ) + { + QMap< QtProperty*, QList< ConstStrArrEditor* > >::iterator itr = createdEditors.find( p ); + + if( itr != createdEditors.end() ) + { + itr->push_back( editor ); + } + else + { + QList< ConstStrArrEditor* > l; + l.push_back( editor ); + createdEditors.insert( p, l ); + } + + editorToProperty.insert( editor, p ); + } + + void removeEditor( QObject *o ) + { + // Remove from editorToProperty first + QMap< ConstStrArrEditor*, QtProperty* >::iterator itr1 = editorToProperty.begin(); + while( itr1 != editorToProperty.end() ) + { + if( itr1.key() == o ) + break; + + ++itr1; + } + if( itr1 != editorToProperty.end() ) + editorToProperty.erase( itr1 ); + + // Then from createdEditors + QMap< QtProperty*, QList< ConstStrArrEditor* > >::iterator itr2 = createdEditors.begin(); + while( itr2 != createdEditors.end() ) + { + QList< ConstStrArrEditor* > &l = *itr2; + QList< ConstStrArrEditor* >::iterator itr = l.begin(); + while( itr != l.end() ) + { + if( *itr == o ) + { + QList< ConstStrArrEditor* >::iterator d = itr; + ++itr; + l.erase( d ); + continue; + } + + ++itr; + } + + ++itr2; + } + } + +}; + +ConstStrArrEditorFactory::ConstStrArrEditorFactory( QObject *parent ) : +QtAbstractEditorFactory( parent ) +{ + d_ptr = new ConstStrArrEditorFactoryPriv(); +} + +ConstStrArrEditorFactory::~ConstStrArrEditorFactory() +{ + delete d_ptr; + d_ptr = NULL; +} + +void ConstStrArrEditorFactory::connectPropertyManager( ConstStrArrPropMgr *manager ) +{ + connect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); + connect( manager, SIGNAL( stringsChanged( QtProperty*, const QStringList& ) ), this, SLOT( onStringsChanged( QtProperty*, const QStringList & ) ) ); +} + +void ConstStrArrEditorFactory::disconnectPropertyManager( ConstStrArrPropMgr *manager ) +{ + disconnect( manager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), this, SLOT( onPropertyChanged( QtProperty*, const QString& ) ) ); + disconnect( manager, SIGNAL( stringsChanged( const QStringList& ) ), this, SLOT( onStringsChanged( const QStringList & ) ) ); +} + +QWidget* ConstStrArrEditorFactory::createEditor( ConstStrArrPropMgr *manager, QtProperty *p, QWidget *parent ) +{ + ConstStrArrEditor *editor = new ConstStrArrEditor( parent ); + editor->setValue( manager->value( p ) ); + + QMap< QtProperty*, QStringList >::iterator itr = d_ptr->strings.find( p ); + if( itr != d_ptr->strings.end() ) + { + editor->setStrings( *itr ); + } + + connect( editor, SIGNAL( valueChanged( const QString& ) ), this, SLOT( onSetValue( const QString& ) ) ); + connect( editor, SIGNAL( destroyed( QObject* ) ), this, SLOT( onEditorDestroyed( QObject* ) ) ); + + d_ptr->addEditor( p, editor ); + + return editor; +} + +void ConstStrArrEditorFactory::onPropertyChanged( QtProperty *p, const QString &value ) +{ + QMap< QtProperty*, QList< ConstStrArrEditor* > >::iterator itr = d_ptr->createdEditors.find( p ); + if( itr == d_ptr->createdEditors.end() ) + return; + + QList< ConstStrArrEditor* > &l = *itr; + QList< ConstStrArrEditor* >::iterator i = l.begin(); + while( i != l.end() ) + { + ConstStrArrEditor *editor = *i; + + editor->blockSignals( true ); + editor->setValue( value ); + editor->blockSignals( false ); + + ++i; + } +} + +void ConstStrArrEditorFactory::onStringsChanged( QtProperty *p, const QStringList &strings ) +{ + if( p == NULL ) + return; + + d_ptr->strings[ p ] = strings; +} + +void ConstStrArrEditorFactory::onSetValue( const QString &value ) +{ + QObject *s = sender(); + ConstStrArrEditor *editor = qobject_cast< ConstStrArrEditor* >( s ); + if( editor == NULL ) + return; + + QMap< ConstStrArrEditor*, QtProperty* >::iterator itr = d_ptr->editorToProperty.find( editor ); + if( itr == d_ptr->editorToProperty.end() ) + return; + + QtProperty *p = *itr; + + ConstStrArrPropMgr *manager = qobject_cast< ConstStrArrPropMgr* >( p->propertyManager() ); + if( manager == NULL ) + return; + + blockSignals( true ); + manager->setValue( p, value ); + blockSignals( false ); +} + +void ConstStrArrEditorFactory::onEditorDestroyed( QObject *editor ) +{ + d_ptr->removeEditor( editor ); +} + + + +//////////////////////////////////////////////////////////////////////// Editor ////////////////////////////////////////////////////////////////// + +ConstStrArrEditor::ConstStrArrEditor( QWidget *parent ) : +QWidget( parent ) +{ + setupUi(); + setupConnections(); +} + +ConstStrArrEditor::~ConstStrArrEditor() +{ +} + +void ConstStrArrEditor::setStrings( const QStringList &strings ) +{ + this->strings.clear(); + + QStringListIterator itr( strings ); + while( itr.hasNext() ) + { + this->strings.push_back( itr.next() ); + } +} + +void ConstStrArrEditor::setValue( const QString &value ) +{ + if( lineEdit->text() == value ) + return; + + disableConnections(); + lineEdit->setText( value ); + setupConnections(); +} + +void ConstStrArrEditor::showEvent( QShowEvent *e ) +{ + QWidget::showEvent( e ); +} + +void ConstStrArrEditor::onToolButtonClicked() +{ + ConstStrArrEditDialog d; + d.setStrings( strings ); + d.setValue( lineEdit->text() ); + int result = d.exec(); + if( QDialog::Accepted != result ) + return; + lineEdit->setText( d.getValue() ); +} + +void ConstStrArrEditor::onTextChanged( const QString &text ) +{ + Q_EMIT valueChanged( text ); +} + +void ConstStrArrEditor::setupConnections() +{ + connect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + connect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ConstStrArrEditor::disableConnections() +{ + disconnect( toolButton, SIGNAL( clicked( bool ) ), this, SLOT( onToolButtonClicked() ) ); + disconnect( lineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( onTextChanged( const QString& ) ) ); +} + +void ConstStrArrEditor::setupUi() +{ + lineEdit = new QLineEdit(); + toolButton = new QToolButton(); + toolButton->setText( "..." ); + + QHBoxLayout *lt = new QHBoxLayout( this ); + lt->setContentsMargins( 0, 0, 0, 0 ); + lt->setSpacing( 0 ); + lt->addWidget( lineEdit ); + lt->addWidget( toolButton ); + + setFocusProxy( lineEdit ); + setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); + +} + + diff --git a/code/studio/src/plugins/world_editor/const_string_array_property.h b/code/studio/src/plugins/world_editor/const_string_array_property.h new file mode 100644 index 000000000..a079f4802 --- /dev/null +++ b/code/studio/src/plugins/world_editor/const_string_array_property.h @@ -0,0 +1,131 @@ +// Ryzom Core Studio World Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef CONST_STR_ARR_PROP_H +#define CONST_STR_ARR_PROP_H + +#define QT_QTPROPERTYBROWSER_IMPORT + +#include "3rdparty/qtpropertybrowser/qtpropertybrowser.h" +#include +#include + +/////////////////////////////////////////////////////// Manager /////////////////////////////////////////////////////////////////////////// + +struct ConstStrArrPropMgrPriv; + +class ConstStrArrPropMgr : public QtAbstractPropertyManager +{ + Q_OBJECT + +public: + ConstStrArrPropMgr( QObject *parent = NULL ); + ~ConstStrArrPropMgr(); + + QString value( const QtProperty *p ) const; + +public Q_SLOTS: + void setValue( QtProperty *p, const QString &value ); + void setStrings( QtProperty *p, const QStringList &strings ); + +Q_SIGNALS: + void valueChanged( QtProperty *p, const QString &value ); + void stringsChanged( QtProperty *p, const QStringList &strings ); + +protected: + bool hasValue( const QtProperty *p ) const; + QString valueText( const QtProperty *p ) const; + void initializeProperty( QtProperty *p ); + void uninitializeProperty( QtProperty *p ); + +private: + ConstStrArrPropMgrPriv *d_ptr; + + Q_DISABLE_COPY( ConstStrArrPropMgr ); +}; + + +////////////////////////////////////////////////////////////////// Factory ///////////////////////////////////////////////////////////////////////// + +struct ConstStrArrEditorFactoryPriv; + +class ConstStrArrEditorFactory : public QtAbstractEditorFactory< ConstStrArrPropMgr > +{ + Q_OBJECT + +public: + ConstStrArrEditorFactory( QObject *parent = NULL ); + ~ConstStrArrEditorFactory(); + +protected: + void connectPropertyManager( ConstStrArrPropMgr *manager ); + void disconnectPropertyManager( ConstStrArrPropMgr *manager ); + + QWidget* createEditor( ConstStrArrPropMgr *manager, QtProperty *p, QWidget *parent ); + +private Q_SLOTS: + void onPropertyChanged( QtProperty *p, const QString &value ); + void onStringsChanged( QtProperty *p, const QStringList &strings ); + void onSetValue( const QString &value ); + void onEditorDestroyed( QObject *editor ); + +private: + ConstStrArrEditorFactoryPriv *d_ptr; + + Q_DISABLE_COPY( ConstStrArrEditorFactory ); +}; + + +///////////////////////////////////////////////////////////////// Editor /////////////////////////////////////////////////////////////////////////// + +class QLineEdit; +class QToolButton; + +class ConstStrArrEditor : public QWidget +{ + Q_OBJECT +public: + ConstStrArrEditor( QWidget *parent = NULL ); + ~ConstStrArrEditor(); + void setStrings( const QStringList &strings ); + +public Q_SLOTS: + void setValue( const QString &value ); + +protected: + void showEvent( QShowEvent *e ); + +private Q_SLOTS: + void onToolButtonClicked(); + void onTextChanged( const QString &text ); + +Q_SIGNALS: + void valueChanged( const QString &value ); + +private: + void setupUi(); + void setupConnections(); + void disableConnections(); + + + QLineEdit *lineEdit; + QToolButton *toolButton; + QStringList strings; +}; + +#endif + diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 6d3fdaec1..4f28d383d 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -29,6 +29,8 @@ // Qt includes #include +#include "const_string_array_property.h" + namespace WorldEditor { @@ -42,6 +44,9 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) m_enumManager = new QtEnumPropertyManager(this); m_stringArrayManager = new QtTextPropertyManager(this); + m_constStrArrPropMgr = new ConstStrArrPropMgr(this); + m_constStrArrEditorFactory = new ConstStrArrEditorFactory(this); + QtLineEditFactory *lineEditFactory = new QtLineEditFactory(this); QtCheckBoxFactory *boolFactory = new QtCheckBoxFactory(this); QtEnumEditorFactory *enumFactory = new QtEnumEditorFactory(this); @@ -51,6 +56,7 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) m_ui.treePropertyBrowser->setFactoryForManager(m_boolManager, boolFactory); m_ui.treePropertyBrowser->setFactoryForManager(m_enumManager, enumFactory); m_ui.treePropertyBrowser->setFactoryForManager(m_stringArrayManager, textFactory); + m_ui.treePropertyBrowser->setFactoryForManager(m_constStrArrPropMgr, m_constStrArrEditorFactory); m_groupManager = new QtGroupPropertyManager(this); @@ -58,6 +64,7 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) connect(m_boolManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_stringArrayManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + connect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_boolManager, SIGNAL(resetProperty(QtProperty *)), this, SLOT(resetProperty(QtProperty *))); connect(m_stringManager, SIGNAL(resetProperty(QtProperty *)), this, SLOT(resetProperty(QtProperty *))); @@ -326,32 +333,18 @@ QtProperty *PropertyEditorWidget::addConstStringArrayProperty(const NLLIGO::IPro primitive->getPropertyByName(name.c_str(), value); // Create qt property -// QtProperty *prop = m_enumManager->addProperty(parameter.Name.c_str()); - QtProperty *prop = m_stringArrayManager->addProperty(parameter.Name.c_str()); + QtProperty *prop = m_constStrArrPropMgr->addProperty(parameter.Name.c_str()); QStringList listEnums = getComboValues(parameter); if (listEnums.isEmpty()) { -// listEnums << QString(value.c_str()) + tr(" (WRN: Check leveldesign!)"); -// m_enumManager->setEnumNames(prop, listEnums); -// m_enumManager->setValue(prop, 0); prop->setEnabled(false); } else { // Fill qt property - m_enumManager->setEnumNames(prop, listEnums); - - // Find index of current value - //for (int i = 0; i < listEnums.size(); i++) - //{ - // if (value == std::string(listEnums[i].toUtf8().constData())) - // { - // m_enumManager->setValue(prop, i); - // break; - // } - //} + m_constStrArrPropMgr->setStrings(prop, listEnums); const NLLIGO::IProperty *ligoProperty; std::vector vectString; @@ -371,17 +364,16 @@ QtProperty *PropertyEditorWidget::addConstStringArrayProperty(const NLLIGO::IPro if (i != (vectString.size() - 1)) temp += '\n'; } - m_stringArrayManager->setValue(prop, temp.c_str()); + m_constStrArrPropMgr->setValue(prop, temp.c_str()); prop->setToolTip(temp.c_str()); } } else { - m_stringArrayManager->setValue(prop, "StringArray :("); + m_constStrArrPropMgr->setValue(prop, "StringArray :("); } } - m_enumManager->setValue(prop, 0); } return prop; diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index 85935cccd..81a8ad008 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -33,6 +33,9 @@ // Qt includes +class ConstStrArrPropMgr; +class ConstStrArrEditorFactory; + namespace WorldEditor { /** @@ -84,6 +87,9 @@ private: QtGroupPropertyManager *m_groupManager; QtTextPropertyManager *m_stringArrayManager; + ConstStrArrPropMgr *m_constStrArrPropMgr; + ConstStrArrEditorFactory *m_constStrArrEditorFactory; + Ui::PropertyEditorWidget m_ui; }; /* PropertyEditorWidget */ From b9e12caaeffff5e468fbb3141afcc9faf9297ed3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:37:32 +0200 Subject: [PATCH 104/220] Identation --- .../world_editor/property_editor_widget.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 4f28d383d..e3e9f0884 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -346,33 +346,33 @@ QtProperty *PropertyEditorWidget::addConstStringArrayProperty(const NLLIGO::IPro // Fill qt property m_constStrArrPropMgr->setStrings(prop, listEnums); - const NLLIGO::IProperty *ligoProperty; - std::vector vectString; + const NLLIGO::IProperty *ligoProperty; + std::vector vectString; - if (primitive->getPropertyByName (parameter.Name.c_str(), ligoProperty)) - { - const NLLIGO::CPropertyStringArray *const propStringArray = dynamic_cast (ligoProperty); - if (propStringArray) + if (primitive->getPropertyByName (parameter.Name.c_str(), ligoProperty)) { - const std::vector &vectString = propStringArray->StringArray; - if (!vectString.empty()) + const NLLIGO::CPropertyStringArray *const propStringArray = dynamic_cast (ligoProperty); + if (propStringArray) { - std::string temp; - for (size_t i = 0; i < vectString.size(); i++) + const std::vector &vectString = propStringArray->StringArray; + if (!vectString.empty()) { - temp += vectString[i]; - if (i != (vectString.size() - 1)) - temp += '\n'; + std::string temp; + for (size_t i = 0; i < vectString.size(); i++) + { + temp += vectString[i]; + if (i != (vectString.size() - 1)) + temp += '\n'; + } + m_constStrArrPropMgr->setValue(prop, temp.c_str()); + prop->setToolTip(temp.c_str()); } - m_constStrArrPropMgr->setValue(prop, temp.c_str()); - prop->setToolTip(temp.c_str()); + } + else + { + m_constStrArrPropMgr->setValue(prop, "StringArray :("); } } - else - { - m_constStrArrPropMgr->setValue(prop, "StringArray :("); - } - } } From 3dc9d07f59114d0c2a42b4bb6d16cc1f26ddab61 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:41:15 +0200 Subject: [PATCH 105/220] Use \n instead of ; as a separator. --- .../src/plugins/world_editor/const_string_array_editor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/world_editor/const_string_array_editor.cpp b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp index 05e5e4cf5..1f9907646 100644 --- a/code/studio/src/plugins/world_editor/const_string_array_editor.cpp +++ b/code/studio/src/plugins/world_editor/const_string_array_editor.cpp @@ -48,7 +48,7 @@ void ConstStrArrEditDialog::setValue( const QString &value ) if( value.isEmpty() ) return; - QStringList l = value.split( ';' ); + QStringList l = value.split( '\n' ); QStringListIterator itr( l ); while( itr.hasNext() ) @@ -67,7 +67,7 @@ QString ConstStrArrEditDialog::getValue() const value += item->text(); if( i < ( listWidget->count() - 1 ) ) - value += ';'; + value += '\n'; } return value; From ae120af5b55eb462fcbec7b77d3cc2fd1282ec3b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:47:24 +0200 Subject: [PATCH 106/220] Changed property to p, property is a reserved word in VS. --- .../src/plugins/world_editor/property_editor_widget.cpp | 4 ++-- code/studio/src/plugins/world_editor/property_editor_widget.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index e3e9f0884..17be420cb 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -195,9 +195,9 @@ void PropertyEditorWidget::updateSelection(Node *node) blockSignalsOfProperties(false); } -void PropertyEditorWidget::propertyChanged(QtProperty *property) +void PropertyEditorWidget::propertyChanged(QtProperty *p) { - nlinfo(QString("property %1 changed").arg(property->propertyName()).toUtf8().constData()); + nlinfo(QString("property %1 changed").arg(p->propertyName()).toUtf8().constData()); } void PropertyEditorWidget::resetProperty(QtProperty *property) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index 81a8ad008..4152eec0a 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -57,7 +57,7 @@ public Q_SLOTS: /// Update of selections void updateSelection(Node *node); - void propertyChanged(QtProperty *property); + void propertyChanged(QtProperty *p); void resetProperty(QtProperty *property); private: From 3b713d152a7ba34cb83b060695d27b2a1faeac3e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 00:01:17 +0200 Subject: [PATCH 107/220] Store QtProperty, IPrimitive pairs and look the primitive up when the property changes. --- .../world_editor/property_editor_widget.cpp | 50 +++++++++++++++++++ .../world_editor/property_editor_widget.h | 5 ++ 2 files changed, 55 insertions(+) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 17be420cb..0927ce6f7 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -28,12 +28,48 @@ // Qt includes #include +#include #include "const_string_array_property.h" namespace WorldEditor { +struct PropertyEditorWidgetPrivate +{ + QMap< QtProperty*, NLLIGO::IPrimitive* > propToPrim; + + void clearPrimitives() + { + propToPrim.clear(); + } + + void addPrimitive( QtProperty *p, NLLIGO::IPrimitive *prim ) + { + QMap< QtProperty*, NLLIGO::IPrimitive* >::const_iterator itr + = propToPrim.find( p ); + if( itr != propToPrim.end() ) + return; + + propToPrim[ p ] = prim; + } + + NLLIGO::IPrimitive* getPrimitive( QtProperty *p ) + { + NLLIGO::IPrimitive *prim = NULL; + + QMap< QtProperty*, NLLIGO::IPrimitive* >::const_iterator itr + = propToPrim.find( p ); + + if( itr != propToPrim.end() ) + { + prim = itr.value(); + } + + return prim; + } +}; + PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) : QWidget(parent) { @@ -60,6 +96,8 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) m_groupManager = new QtGroupPropertyManager(this); + d_ptr = new PropertyEditorWidgetPrivate(); + connect(m_stringManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_boolManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); connect(m_enumManager, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); @@ -74,10 +112,13 @@ PropertyEditorWidget::PropertyEditorWidget(QWidget *parent) PropertyEditorWidget::~PropertyEditorWidget() { + delete d_ptr; + d_ptr = NULL; } void PropertyEditorWidget::clearProperties() { + d_ptr->clearPrimitives(); m_ui.treePropertyBrowser->clear(); } @@ -170,6 +211,8 @@ void PropertyEditorWidget::updateSelection(Node *node) else prop = addBoolProperty(ligoProperty, parameter, primitive); + d_ptr->addPrimitive( prop, const_cast< NLLIGO::IPrimitive* >( primitive ) ); + // Default value ? if ((ligoProperty == NULL) || (ligoProperty->Default)) prop->setModified(false); @@ -198,6 +241,12 @@ void PropertyEditorWidget::updateSelection(Node *node) void PropertyEditorWidget::propertyChanged(QtProperty *p) { nlinfo(QString("property %1 changed").arg(p->propertyName()).toUtf8().constData()); + + NLLIGO::IPrimitive *prim = d_ptr->getPrimitive( p ); + if( prim != NULL ) + { + + } } void PropertyEditorWidget::resetProperty(QtProperty *property) @@ -422,5 +471,6 @@ void PropertyEditorWidget::blockSignalsOfProperties(bool block) m_boolManager->blockSignals(block); m_enumManager->blockSignals(block); m_stringArrayManager->blockSignals(block); + m_constStrArrPropMgr->blockSignals(block); } } /* namespace WorldEditor */ diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index 4152eec0a..e77b92664 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -38,6 +38,9 @@ class ConstStrArrEditorFactory; namespace WorldEditor { + +struct PropertyEditorWidgetPrivate; + /** @class PropertyEditorWidget @brief PropertyEditorWidget @@ -91,6 +94,8 @@ private: ConstStrArrEditorFactory *m_constStrArrEditorFactory; Ui::PropertyEditorWidget m_ui; + + PropertyEditorWidgetPrivate *d_ptr; }; /* PropertyEditorWidget */ } /* namespace WorldEditor */ From 790ac4524fbfdc6174e4cb154c323c9926a01041 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 00:38:35 +0200 Subject: [PATCH 108/220] Block only the propertychanged signal in the const_string_array property manager. --- .../plugins/world_editor/property_editor_widget.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 0927ce6f7..93e9f31cf 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -471,6 +471,14 @@ void PropertyEditorWidget::blockSignalsOfProperties(bool block) m_boolManager->blockSignals(block); m_enumManager->blockSignals(block); m_stringArrayManager->blockSignals(block); - m_constStrArrPropMgr->blockSignals(block); + + if( block ) + { + disconnect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + } + else + { + connect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + } } } /* namespace WorldEditor */ From 5f941d812dac149169deee932286764a30fb9fb5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 01:54:45 +0200 Subject: [PATCH 109/220] Apply property changes. --- .../world_editor/property_editor_widget.cpp | 137 +++++++++++++++++- .../world_editor/property_editor_widget.h | 9 ++ 2 files changed, 140 insertions(+), 6 deletions(-) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 93e9f31cf..0854dcd15 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -241,12 +241,6 @@ void PropertyEditorWidget::updateSelection(Node *node) void PropertyEditorWidget::propertyChanged(QtProperty *p) { nlinfo(QString("property %1 changed").arg(p->propertyName()).toUtf8().constData()); - - NLLIGO::IPrimitive *prim = d_ptr->getPrimitive( p ); - if( prim != NULL ) - { - - } } void PropertyEditorWidget::resetProperty(QtProperty *property) @@ -254,6 +248,107 @@ void PropertyEditorWidget::resetProperty(QtProperty *property) nlinfo(QString("property %1 reset").arg(property->propertyName()).toUtf8().constData()); } +NLLIGO::IProperty* PropertyEditorWidget::getLigoProperty( QtProperty *p ) +{ + NLLIGO::IPrimitive *prim = d_ptr->getPrimitive( p ); + if( prim == NULL ) + { + return NULL; + } + + NLLIGO::IProperty *prop = NULL; + prim->getPropertyByName( p->propertyName().toUtf8().constData(), prop ); + if( prop == NULL ) + { + return NULL; + } + + return prop; +} + +void PropertyEditorWidget::onBoolValueChanged( QtProperty *p, bool v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyString *pp = dynamic_cast< NLLIGO::CPropertyString* >( prop ); + if( pp == NULL ) + return; + + if( v ) + pp->String = "true"; + else + pp->String = "false"; +} + +void PropertyEditorWidget::onStringValueChanged( QtProperty *p, const QString &v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyString *pp = dynamic_cast< NLLIGO::CPropertyString* >( prop ); + if( pp == NULL ) + return; + + pp->String = v.toUtf8().constData(); +} + +void PropertyEditorWidget::onEnumValueChanged( QtProperty *p, int v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyString *pp = dynamic_cast< NLLIGO::CPropertyString* >( prop ); + if( pp == NULL ) + return; + + pp->String = p->valueText().toUtf8().constData(); +} + +void PropertyEditorWidget::onStrArrValueChanged( QtProperty *p, const QString &v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyStringArray *pp = dynamic_cast< NLLIGO::CPropertyStringArray* >( prop ); + if( pp == NULL ) + return; + + pp->StringArray.clear(); + + QStringList l = v.split( '\n' ); + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + pp->StringArray.push_back( itr.next().toUtf8().constData() ); + } +} + +void PropertyEditorWidget::onConstStrArrValueChanged( QtProperty *p, const QString &v ) +{ + NLLIGO::IProperty *prop = getLigoProperty( p ); + if( prop == NULL ) + return; + + NLLIGO::CPropertyStringArray *pp = dynamic_cast< NLLIGO::CPropertyStringArray* >( prop ); + if( pp == NULL ) + return; + + pp->StringArray.clear(); + + QStringList l = v.split( '\n' ); + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + pp->StringArray.push_back( itr.next().toUtf8().constData() ); + } +} + + QtProperty *PropertyEditorWidget::addBoolProperty(const NLLIGO::IProperty *property, const NLLIGO::CPrimitiveClass::CParameter ¶meter, const NLLIGO::IPrimitive *primitive) @@ -475,10 +570,40 @@ void PropertyEditorWidget::blockSignalsOfProperties(bool block) if( block ) { disconnect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + + disconnect(m_boolManager, SIGNAL( valueChanged( QtProperty*, bool ) ), + this, SLOT( onBoolValueChanged( QtProperty*, bool ) ) ); + + disconnect(m_stringManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStringValueChanged( QtProperty*, const QString& ) ) ); + + disconnect(m_enumManager, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumValueChanged( QtProperty*, int ) ) ); + + disconnect(m_stringArrayManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStrArrValueChanged( QtProperty*, const QString& ) ) ); + + disconnect(m_constStrArrPropMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onConstStrArrValueChanged( QtProperty*, const QString& ) ) ); } else { connect(m_constStrArrPropMgr, SIGNAL(propertyChanged(QtProperty *)), this, SLOT(propertyChanged(QtProperty *))); + + connect(m_boolManager, SIGNAL( valueChanged( QtProperty*, bool ) ), + this, SLOT( onBoolValueChanged( QtProperty*, bool ) ) ); + + connect(m_stringManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStringValueChanged( QtProperty*, const QString& ) ) ); + + connect(m_enumManager, SIGNAL( valueChanged( QtProperty*, int ) ), + this, SLOT( onEnumValueChanged( QtProperty*, int ) ) ); + + connect(m_stringArrayManager, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onStrArrValueChanged( QtProperty*, const QString& ) ) ); + + connect(m_constStrArrPropMgr, SIGNAL( valueChanged( QtProperty*, const QString& ) ), + this, SLOT( onConstStrArrValueChanged( QtProperty*, const QString& ) ) ); } } } /* namespace WorldEditor */ diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.h b/code/studio/src/plugins/world_editor/property_editor_widget.h index e77b92664..dae7ad13e 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.h +++ b/code/studio/src/plugins/world_editor/property_editor_widget.h @@ -63,6 +63,15 @@ public Q_SLOTS: void propertyChanged(QtProperty *p); void resetProperty(QtProperty *property); + NLLIGO::IProperty* getLigoProperty( QtProperty *p ); + + void onBoolValueChanged( QtProperty *p, bool v ); + void onStringValueChanged( QtProperty *p, const QString &v ); + void onEnumValueChanged( QtProperty *p, int v ); + void onStrArrValueChanged( QtProperty *p, const QString &v ); + void onConstStrArrValueChanged( QtProperty *p, const QString &v ); + + private: QtProperty *addBoolProperty(const NLLIGO::IProperty *property, const NLLIGO::CPrimitiveClass::CParameter ¶meter, From cabcff881cf054d62dfeec23eff140063113440b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 13 Jul 2014 21:38:14 +0200 Subject: [PATCH 110/220] Trying to load an invalid world editor file shouldn't crash the application, and an error messagebox should inform the user. --- .../world_editor/world_editor_misc.cpp | 95 +++++++++++-------- .../plugins/world_editor/world_editor_misc.h | 2 + .../world_editor/world_editor_window.cpp | 7 +- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/code/studio/src/plugins/world_editor/world_editor_misc.cpp b/code/studio/src/plugins/world_editor/world_editor_misc.cpp index 7401f49fb..5d6b7f94e 100644 --- a/code/studio/src/plugins/world_editor/world_editor_misc.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_misc.cpp @@ -34,35 +34,11 @@ namespace WorldEditor namespace Utils { -void syntaxError(const char *filename, xmlNodePtr xmlNode, const char *format, ...) +std::string lastError; + +std::string getLastError() { - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - nlerror("(%s), node (%s), line (%s) :\n%s", filename, xmlNode->name, xmlNode->content, buffer); -} - -bool getPropertyString(std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName) -{ - // Call the CIXml version - if (!NLMISC::CIXml::getPropertyString(result, xmlNode, propName)) - { - // Output a formated error - syntaxError(filename, xmlNode, "Missing XML node property (%s)", propName); - return false; - } - return true; + return lastError; } uint32 getUniqueId() @@ -81,6 +57,8 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList { bool result = false; + lastError = ""; + // Load the document NLMISC::CIFile file; if (file.open(fileName)) @@ -110,20 +88,31 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList } if (version == -1) - syntaxError(fileName.c_str(), rootNode, "No version node"); + { + std::string error = "No version node in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; + } else { // Old format, if (version <= 1) { - syntaxError(fileName.c_str(), rootNode, "Old version node"); + std::string error = "Old version node in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } else { // Read it if (version > WORLD_EDITOR_FILE_VERSION) { - syntaxError(fileName.c_str(), node, "Unknown file version"); + std::string error = "Unknown file version in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } else { @@ -153,11 +142,12 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList { // Get the type std::string type; - if (getPropertyString(type, fileName.c_str(), node, "TYPE")) + + if ( NLMISC::CIXml::getPropertyString(type, node, "TYPE")) { // Read the filename std::string filenameChild; - if (getPropertyString(filenameChild, fileName.c_str(), node, "FILENAME")) + if ( NLMISC::CIXml::getPropertyString(filenameChild, node, "FILENAME")) { // Is it a landscape ? if (type == "landscape") @@ -179,11 +169,34 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList } } else + if ( type == "primitive" ) { worldEditList.push_back(WorldEditItem(PrimitiveType, filenameChild)); } + else + if( type.empty() ) + { + std::string error = "Empty type node property in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; + } } + else + { + std::string error = "Missing filename node property in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; + } + } + else + { + std::string error = "Missing type node property in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } } while (node = NLMISC::CIXml::getNextChildNode(node, "DATABASE_ELEMENT")); @@ -197,18 +210,26 @@ bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList } else { - // Error - syntaxError(fileName.c_str(), rootNode, "Unknown file header : %s", rootNode->name); + std::string error = "Unknown file header in file " + fileName; + lastError = error; + nlinfo( "%s", error.c_str() ); + return false; } } } catch (NLMISC::Exception &e) { - nlerror("Error reading file %s : %s", fileName.c_str(), e.what()); + std::string error = "Error reading file " + fileName + " : " + std::string( e.what() ); + lastError = error; + nlinfo( "%s", error.c_str() ); } } else - nlerror("Can't open the file %s for reading.", fileName.c_str()); + { + std::string error = "Can't open the file " + fileName + " for reading."; + lastError = error; + nlinfo( "%s", error.c_str() ); + } return result; } diff --git a/code/studio/src/plugins/world_editor/world_editor_misc.h b/code/studio/src/plugins/world_editor/world_editor_misc.h index d29b2553b..36c7b1a6a 100644 --- a/code/studio/src/plugins/world_editor/world_editor_misc.h +++ b/code/studio/src/plugins/world_editor/world_editor_misc.h @@ -49,6 +49,8 @@ typedef std::vector WorldEditList; // Generate unique identificator uint32 getUniqueId(); +std::string getLastError(); + // Load *.worldedit file and return list primitives and landscapes. bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList); diff --git a/code/studio/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp index afb667358..d4ae355f4 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_window.cpp @@ -174,7 +174,12 @@ void WorldEditorWindow::loadWorldEditFile(const QString &fileName) Utils::WorldEditList worldEditList; if (!Utils::loadWorldEditFile(fileName.toUtf8().constData(), worldEditList)) { - // TODO: add the message box + std::string error = Utils::getLastError(); + + QMessageBox::critical( this, + tr( "Error opening world editor file" ), + tr( error.c_str() ) ); + return; } From 12d33f1024d6f39b999afe927f693e66b50f9c16 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 01:30:30 +0200 Subject: [PATCH 111/220] Save world editor files. --- .../world_editor/world_editor_actions.cpp | 172 ++++++++++++++++++ .../world_editor/world_editor_actions.h | 25 +++ .../world_editor/world_editor_window.cpp | 12 ++ .../world_editor/world_editor_window.h | 3 + 4 files changed, 212 insertions(+) diff --git a/code/studio/src/plugins/world_editor/world_editor_actions.cpp b/code/studio/src/plugins/world_editor/world_editor_actions.cpp index e10e15745..5255e976f 100644 --- a/code/studio/src/plugins/world_editor/world_editor_actions.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_actions.cpp @@ -209,6 +209,178 @@ void CreateWorldCommand::redo() m_model->createWorldEditNode(m_fileName); } + +WorldSaver::WorldSaver( PrimitivesTreeModel *model, LandscapeEditor::ZoneBuilderBase *zoneBuilder, const std::string &dataDir, const std::string &context ) +{ + m_model = model; + m_zoneBuilder = zoneBuilder; + m_dataDir = dataDir; + m_context = context; +} + +bool WorldSaver::save() +{ + QModelIndex pidx = m_model->index( 0, 0 ); + if( !pidx.isValid() ) + { + lastError = "No root node."; + return false; + } + + int rows = m_model->rowCount( pidx ); + bool ok = false; + + for( int i = 0; i < rows; i++ ) + { + QModelIndex idx = m_model->index( i, 0, pidx ); + + Node *node = reinterpret_cast< Node* >( idx.internalPointer() ); + Node::NodeType t = node->type(); + + switch( t ) + { + case Node::LandscapeNodeType: ok = saveLandscapeNode( node ); break; + case Node::RootPrimitiveNodeType: ok = savePrimitiveNode( node ); break; + } + + if( !ok ) + return false; + } + + ok = saveWorldEditFile(); + return ok; +} + +bool WorldSaver::saveLandscapeNode( Node *node ) +{ + LandscapeNode *n = dynamic_cast< LandscapeNode* >( node ); + if( n == NULL ) + { + lastError = "Trying to save a non-landscape node as landscape."; + return false; + } + + LandscapeEditor::ZoneRegionObject *z = m_zoneBuilder->zoneRegion( n->id() ); + if( z == NULL ) + { + lastError = "The specified zoneregion doesn't exist."; + return false; + } + + z->setFileName( n->fileName().toUtf8().constData() ); + bool ok = z->save(); + + if( ok ) + { + std::pair< std::string, std::string > p; + p.first = "landscape"; + p.second = n->fileName().toUtf8().constData(); + + m_data.push_back( p ); + } + else + { + lastError = "Couldn't save landscape file " + std::string( n->fileName().toUtf8().constData() ); + } + + return ok; +} + +bool WorldSaver::savePrimitiveNode( Node *node ) +{ + RootPrimitiveNode *n = dynamic_cast< RootPrimitiveNode* >( node ); + if( n == NULL ) + { + lastError = "Trying to save a non-primitive node as primitive."; + return false; + } + + bool ok = NLLIGO::saveXmlPrimitiveFile( *(n->primitives()), n->fileName().toUtf8().constData() ); + + if( ok ) + { + std::pair< std::string, std::string > p; + p.first = "primitive"; + p.second = n->fileName().toUtf8().constData(); + + m_data.push_back( p ); + } + else + { + lastError = "Couldn't save primitive file " + std::string( n->fileName().toUtf8().constData() ); + } + + return ok; +} + +bool WorldSaver::saveWorldEditFile() +{ + QModelIndex idx = m_model->index( 0, 0 ); + Node *node = reinterpret_cast< Node* >( idx.internalPointer() ); + Node::NodeType t = node->type(); + + WorldEditNode *n = dynamic_cast< WorldEditNode* >( node ); + if( n == NULL ) + { + lastError = "Not a worldedit node."; + return false; + } + + std::string fn = n->data( 0 ).toString().toUtf8().constData(); + bool ok = writeWorldEditFile( fn ); + + return ok; +} + +bool WorldSaver::writeWorldEditFile( const std::string &fn ) +{ + if( fn.empty() ) + return false; + + NLMISC::COFile of; + if( !of.open( fn, false, true, false ) ) + { + lastError = "Couldn't open file " + fn + " for writing."; + return false; + } + + NLMISC::COXml xml; + xml.init( &of ); + + xmlNodePtr rootNode = xmlNewDocNode (xml.getDocument (), NULL, (const xmlChar*)"NEL_WORLD_EDITOR_PROJECT", NULL); + xmlDocSetRootElement (xml.getDocument (), rootNode); + xmlNodePtr node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"VERSION", NULL); + xmlNodePtr text = xmlNewText ((const xmlChar *) NLMISC::toString( WORLD_EDITOR_FILE_VERSION ).c_str ()); + xmlAddChild( node, text ); + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATA_DIRECTORY", NULL); + xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)m_dataDir.c_str ()); + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"CONTEXT", NULL); + xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)m_context.c_str ()); + + std::vector< std::pair< std::string, std::string > >::const_iterator itr = m_data.begin(); + while( itr != m_data.end() ) + { + const std::pair< std::string, std::string > &p = *itr; + + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATABASE_ELEMENT", NULL); + xmlSetProp (node, (const xmlChar*)"FILENAME", (const xmlChar*)p.second.c_str ()); + + if( p.first == "landscape" ) + xmlSetProp (node, (const xmlChar*)"TYPE", (const xmlChar*)("landscape")); + else + xmlSetProp (node, (const xmlChar*)"TYPE", (const xmlChar*)("primitive")); + + ++itr; + } + + xml.flush(); + + of.close(); + + + return true; +} + LoadLandscapeCommand::LoadLandscapeCommand(const QString &fileName, PrimitivesTreeModel *model, LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent) : QUndoCommand(parent), diff --git a/code/studio/src/plugins/world_editor/world_editor_actions.h b/code/studio/src/plugins/world_editor/world_editor_actions.h index 89de14e9a..95ce093e2 100644 --- a/code/studio/src/plugins/world_editor/world_editor_actions.h +++ b/code/studio/src/plugins/world_editor/world_editor_actions.h @@ -72,6 +72,31 @@ private: PrimitivesTreeModel *const m_model; }; + +class WorldSaver +{ +public: + WorldSaver( PrimitivesTreeModel *model, LandscapeEditor::ZoneBuilderBase *zoneBuilder, const std::string &dataDir, const std::string &context ); + bool save(); + + std::string getLastError() const{ return lastError; } + +private: + bool saveLandscapeNode( Node *node ); + bool savePrimitiveNode( Node *node ); + bool saveWorldEditFile(); + bool writeWorldEditFile( const std::string &fn ); + + std::string m_dataDir; + std::string m_context; + PrimitivesTreeModel *m_model; + LandscapeEditor::ZoneBuilderBase *m_zoneBuilder; + + std::vector< std::pair< std::string, std::string > > m_data; + + std::string lastError; +}; + /** @class LoadLandscapeCommand @brief diff --git a/code/studio/src/plugins/world_editor/world_editor_window.cpp b/code/studio/src/plugins/world_editor/world_editor_window.cpp index d4ae355f4..cec3baee1 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.cpp +++ b/code/studio/src/plugins/world_editor/world_editor_window.cpp @@ -194,8 +194,10 @@ void WorldEditorWindow::loadWorldEditFile(const QString &fileName) { case Utils::DataDirectoryType: m_zoneBuilderBase->init(QString(worldEditList[i].second.c_str()), true); + m_dataDir = worldEditList[i].second.c_str(); break; case Utils::ContextType: + m_context = worldEditList[i].second.c_str(); break; case Utils::LandscapeType: m_undoStack->push(new LoadLandscapeCommand(QString(worldEditList[i].second.c_str()), m_primitivesModel, m_zoneBuilderBase)); @@ -221,6 +223,16 @@ void WorldEditorWindow::newWorldEditFile() void WorldEditorWindow::saveWorldEditFile() { + WorldSaver saver( m_primitivesModel, m_zoneBuilderBase, m_dataDir.toUtf8().constData(), m_context.toUtf8().constData() ); + bool ok = saver.save(); + QString error = saver.getLastError().c_str(); + + if( !ok ) + { + QMessageBox::critical( this, + tr( "Failed to save world editor files" ), + tr( "Failed to save world editor files.\nError:\n " ) + error ); + } } void WorldEditorWindow::openProjectSettings() diff --git a/code/studio/src/plugins/world_editor/world_editor_window.h b/code/studio/src/plugins/world_editor/world_editor_window.h index f289e6c2a..60a6a988a 100644 --- a/code/studio/src/plugins/world_editor/world_editor_window.h +++ b/code/studio/src/plugins/world_editor/world_editor_window.h @@ -76,6 +76,9 @@ private: void loadWorldEditFile(const QString &fileName); void checkCurrentWorld(); + QString m_context; + QString m_dataDir; + QString m_lastDir; QLabel *m_statusInfo; From 2a6e5115e11498ef741554ab131e671dc8d8e57c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 18:51:06 +0200 Subject: [PATCH 112/220] When changing a property make sure to set default to false, so it's actually saved! --- .../src/plugins/world_editor/property_editor_widget.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/studio/src/plugins/world_editor/property_editor_widget.cpp b/code/studio/src/plugins/world_editor/property_editor_widget.cpp index 0854dcd15..9c24c8452 100644 --- a/code/studio/src/plugins/world_editor/property_editor_widget.cpp +++ b/code/studio/src/plugins/world_editor/property_editor_widget.cpp @@ -280,6 +280,8 @@ void PropertyEditorWidget::onBoolValueChanged( QtProperty *p, bool v ) pp->String = "true"; else pp->String = "false"; + + pp->Default = false; } void PropertyEditorWidget::onStringValueChanged( QtProperty *p, const QString &v ) @@ -293,6 +295,7 @@ void PropertyEditorWidget::onStringValueChanged( QtProperty *p, const QString &v return; pp->String = v.toUtf8().constData(); + pp->Default = false; } void PropertyEditorWidget::onEnumValueChanged( QtProperty *p, int v ) @@ -306,6 +309,7 @@ void PropertyEditorWidget::onEnumValueChanged( QtProperty *p, int v ) return; pp->String = p->valueText().toUtf8().constData(); + pp->Default = false; } void PropertyEditorWidget::onStrArrValueChanged( QtProperty *p, const QString &v ) @@ -326,6 +330,8 @@ void PropertyEditorWidget::onStrArrValueChanged( QtProperty *p, const QString &v { pp->StringArray.push_back( itr.next().toUtf8().constData() ); } + + pp->Default = false; } void PropertyEditorWidget::onConstStrArrValueChanged( QtProperty *p, const QString &v ) @@ -346,6 +352,8 @@ void PropertyEditorWidget::onConstStrArrValueChanged( QtProperty *p, const QStri { pp->StringArray.push_back( itr.next().toUtf8().constData() ); } + + pp->Default = false; } From b55b0c5e0d55924b3f50bfbcd2cbf40d0f5b8176 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 20:19:53 +0200 Subject: [PATCH 113/220] 'Fixed' the Mission Compiler crash. --- .../mission_compiler/mission_compiler_main_window.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp index e01f5f617..10985aa38 100644 --- a/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp +++ b/code/studio/src/plugins/mission_compiler/mission_compiler_main_window.cpp @@ -90,7 +90,14 @@ MissionCompilerMainWindow::MissionCompilerMainWindow(QWidget *parent) : NLLIGO::Register(); // TODO try/catch exception. Crashes if path invalid. - m_ligoConfig.readPrimitiveClass(NLMISC::CPath::lookup("world_editor_classes.xml").c_str(), false); + try{ + m_ligoConfig.readPrimitiveClass(NLMISC::CPath::lookup("world_editor_classes.xml").c_str(), false); + } + catch( NLMISC::Exception &e ) + { + nlinfo( "Exception occured during Mission Compiler LIGO startup: %s", e.what() ); + } + NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig; } From 5a39d59fb92a525683fda27609a5425026ddf326 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 20:29:57 +0200 Subject: [PATCH 114/220] Fixed another crash. --- .../mission_compiler/mission_compiler_settings_page.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp index ad115cffd..28dc4f9ce 100644 --- a/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp +++ b/code/studio/src/plugins/mission_compiler/mission_compiler_settings_page.cpp @@ -191,7 +191,9 @@ void MissionCompilerSettingsPage::writeSettings() { for(int column = 0; column < m_ui.serversTableWidget->columnCount(); column++) { - items << m_ui.serversTableWidget->item(row, column)->text(); + QTableWidgetItem *item = m_ui.serversTableWidget->item(row, column); + if( item != NULL ) + items << item->text(); } } From 19570b735df8f726daa1f770c413db167518f8cd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 21:41:11 +0200 Subject: [PATCH 115/220] Initialize the undostack to NULL, so we get a proper crash instead of a dangled pointer crash. --- .../plugins/translation_manager/translation_manager_editor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_editor.h b/code/studio/src/plugins/translation_manager/translation_manager_editor.h index fd53ba863..3ded2c3af 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_editor.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_editor.h @@ -32,8 +32,8 @@ class CEditor : public QMdiSubWindow Q_OBJECT public: - CEditor(QMdiArea *parent) : QMdiSubWindow(parent) {} - CEditor() : QMdiSubWindow() {} + CEditor(QMdiArea *parent) : QMdiSubWindow(parent) { current_stack = NULL; } + CEditor() : QMdiSubWindow() { current_stack = NULL; } virtual void open(QString filename) =0; virtual void save() =0; virtual void saveAs(QString filename) =0; From be977a23b740deb9e96f878c4fd833c4072e95ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 21:46:16 +0200 Subject: [PATCH 116/220] Set the undostack so we won't crash... --- .../translation_manager/translation_manager_main_window.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 244a5a92c..44d0963ae 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -280,6 +280,7 @@ void CMainWindow::openWorkFile(QString file) if(isWorksheetEditor(file_path->filePath())) { CEditorWorksheet *new_window = new CEditorWorksheet(_ui.mdiArea); + new_window->setUndoStack( m_undoStack ); new_window->open(file_path->filePath()); new_window->activateWindow(); } From bc50ca150b71f27c12f8a5a222ab9cf8206d7b63 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 16 Jul 2014 02:52:17 +0200 Subject: [PATCH 117/220] I don't really know what to write here. --- .../translation_manager/translation_manager_main_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 44d0963ae..dcade72ef 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -558,7 +558,7 @@ void CMainWindow::readSettings() // core settings settings->beginGroup(Core::Constants::DATA_PATH_SECTION); level_design_path = settings->value(Core::Constants::LEVELDESIGN_PATH).toString(); - primitives_path = QString(Core::Constants::PRIMITIVES_PATH); //TODO + primitives_path = settings->value( Core::Constants::PRIMITIVES_PATH ).toString(); settings->endGroup(); } From 85f1e37155128792503426e9364d12c30ba044d1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 17 Jul 2014 19:08:29 +0200 Subject: [PATCH 118/220] UXT Editor widget --- .../translation_manager/CMakeLists.txt | 1 + .../translation_manager_constants.h | 4 +- .../translation_manager_main_window.cpp | 14 +++ .../translation_manager_main_window.h | 1 + .../translation_manager/uxt_editor.cpp | 96 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 33 +++++++ 6 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/translation_manager/uxt_editor.cpp create mode 100644 code/studio/src/plugins/translation_manager/uxt_editor.h diff --git a/code/studio/src/plugins/translation_manager/CMakeLists.txt b/code/studio/src/plugins/translation_manager/CMakeLists.txt index 6f0f7a1c2..b35c64735 100644 --- a/code/studio/src/plugins/translation_manager/CMakeLists.txt +++ b/code/studio/src/plugins/translation_manager/CMakeLists.txt @@ -17,6 +17,7 @@ SET(OVQT_PLUG_TRANSLATION_MANAGER_HDR translation_manager_plugin.h ftp_selection.h editor_worksheet.h editor_phrase.h + uxt_editor.h ) SET(OVQT_PLUG_TRANSLATION_MANAGER_UIS translation_manager_settings_page.ui diff --git a/code/studio/src/plugins/translation_manager/translation_manager_constants.h b/code/studio/src/plugins/translation_manager/translation_manager_constants.h index d72a2b223..7ff813d40 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_constants.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_constants.h @@ -21,8 +21,9 @@ namespace TranslationManager { namespace Constants { -const int ED_SHEET = 1; +const int ED_SHEET = 1; const int ED_PHRASE = 2; +const int ED_UXT = 3; const char *const WK_BOTNAMES = "bot_names_wk.txt"; const char *const WK_ITEM = "item_words_wk.txt"; @@ -32,6 +33,7 @@ const char *const WK_SPHRASE = "sphrase_words_wk.txt"; const char *const WK_PLACE = "place_words_wk.txt"; const char *const WK_CONTINENT = "place_words_wk.txt"; const char *const WK_STABLE = "place_words_wk.txt"; +const char *const WK_UXT = "wk.uxt"; } } diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index dcade72ef..f3e882739 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -41,6 +41,8 @@ #include #include +#include "uxt_editor.h" + namespace TranslationManager { @@ -84,6 +86,10 @@ void CMainWindow::createMenus() if( m != NULL ) { windowMenu = m->addMenu("Window"); + + QAction *a = m->addAction( "Uxt" ); + connect( a, SIGNAL( triggered() ), this, SLOT( onUxtClicked() ) ); + menu = m; } @@ -544,6 +550,14 @@ void CMainWindow::mergeSingleFile() } } +void CMainWindow::onUxtClicked() +{ + UXTEditor *e = new UXTEditor(); + e->open( work_path + "/" + QString( Constants::WK_UXT ) ); + _ui.mdiArea->addSubWindow( e ); + e->activateWindow(); +} + // Read the settings from QSettings void CMainWindow::readSettings() { diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h index 73bccdd8e..ba6ce8746 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h @@ -90,6 +90,7 @@ private Q_SLOTS: void setActiveSubWindow(QWidget *window); void updateWindowsList(); void mergeSingleFile(); + void onUxtClicked(); private: void openWorkFile(QString file); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp new file mode 100644 index 000000000..e13a6300d --- /dev/null +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -0,0 +1,96 @@ +#include "translation_manager_constants.h" +#include "uxt_editor.h" + +#include +#include +#include + +#include "nel/misc/diff_tool.h" + +namespace TranslationManager +{ + +class UXTEditorPvt +{ +public: + + UXTEditorPvt() + { + t = new QTableWidget(); + } + + QTableWidget *t; +}; + + +UXTEditor::UXTEditor( QMdiArea *parent ) : +CEditor( parent ) +{ + editor_type = Constants::ED_UXT; + setAttribute( Qt::WA_DeleteOnClose ); + + d_ptr = new UXTEditorPvt(); +} + +UXTEditor::~UXTEditor() +{ + delete d_ptr; + d_ptr = NULL; +} + +void UXTEditor::open( QString filename ) +{ + std::vector< STRING_MANAGER::TStringInfo > infos; + STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + + if( infos.size() == 0 ) + return; + + d_ptr->t->clear(); + d_ptr->t->setColumnCount( 2 ); + d_ptr->t->setRowCount( infos.size() ); + + int i = 0; + + std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = infos.begin(); + while( itr != infos.end() ) + { + const STRING_MANAGER::TStringInfo &info = *itr; + + QTableWidgetItem *name = new QTableWidgetItem( info.Identifier.c_str() ); + QTableWidgetItem *text1 = new QTableWidgetItem( info.Text.toUtf8().c_str() ); + + d_ptr->t->setItem( i, 0, name ); + d_ptr->t->setItem( i, 1, text1 ); + + ++itr; + i++; + } + + d_ptr->t->resizeColumnsToContents(); + + setWidget( d_ptr->t ); + setCurrentFile( filename ); +} + +void UXTEditor::save() +{ +} + +void UXTEditor::saveAs( QString filename ) +{ +} + +void UXTEditor::activateWindow() +{ + showMaximized(); +} + + +void UXTEditor::closeEvent( QCloseEvent *e ) +{ + e->accept(); + close(); +} + +} diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h new file mode 100644 index 000000000..231461bc3 --- /dev/null +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -0,0 +1,33 @@ +#ifndef UXT_EDITOR_H +#define UXT_EDITOR_H + +#include "translation_manager_editor.h" + +namespace TranslationManager +{ + +class UXTEditorPvt; + +class UXTEditor : public CEditor +{ + Q_OBJECT +public: + UXTEditor( QMdiArea *parent = NULL ); + ~UXTEditor(); + + void open( QString filename ); + void save(); + void saveAs( QString filename ); + void activateWindow(); + +protected: + void closeEvent( QCloseEvent *e ); + +private: + UXTEditorPvt *d_ptr; +}; + +} + +#endif + From 1df00cc8b39e3d5432469860062380806d88f11d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 17 Jul 2014 19:17:02 +0200 Subject: [PATCH 119/220] Set header texts. --- .../translation_manager/uxt_editor.cpp | 12 ++++ .../plugins/translation_manager/uxt_editor.h | 58 ++++++++++--------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index e13a6300d..3ac7cb066 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -50,6 +50,8 @@ void UXTEditor::open( QString filename ) d_ptr->t->setColumnCount( 2 ); d_ptr->t->setRowCount( infos.size() ); + setHeaderText( "Id", "Text" ); + int i = 0; std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = infos.begin(); @@ -93,4 +95,14 @@ void UXTEditor::closeEvent( QCloseEvent *e ) close(); } +void UXTEditor::setHeaderText( const QString &id, const QString &text ) +{ + QTableWidgetItem *h1 = new QTableWidgetItem( id ); + QTableWidgetItem *h2 = new QTableWidgetItem( text ); + h1->setTextAlignment( Qt::AlignLeft ); + h2->setTextAlignment( Qt::AlignLeft ); + d_ptr->t->setHorizontalHeaderItem( 0, h1 ); + d_ptr->t->setHorizontalHeaderItem( 1, h2 ); +} + } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 231461bc3..3f6d52b3a 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -1,33 +1,35 @@ -#ifndef UXT_EDITOR_H -#define UXT_EDITOR_H - -#include "translation_manager_editor.h" - -namespace TranslationManager -{ - -class UXTEditorPvt; - -class UXTEditor : public CEditor -{ - Q_OBJECT -public: - UXTEditor( QMdiArea *parent = NULL ); +#ifndef UXT_EDITOR_H +#define UXT_EDITOR_H + +#include "translation_manager_editor.h" + +namespace TranslationManager +{ + +class UXTEditorPvt; + +class UXTEditor : public CEditor +{ + Q_OBJECT +public: + UXTEditor( QMdiArea *parent = NULL ); ~UXTEditor(); void open( QString filename ); void save(); void saveAs( QString filename ); - void activateWindow(); - -protected: - void closeEvent( QCloseEvent *e ); - -private: - UXTEditorPvt *d_ptr; -}; - -} - -#endif - + void activateWindow(); + +protected: + void closeEvent( QCloseEvent *e ); + +private: + void setHeaderText( const QString &id, const QString &text ); + + UXTEditorPvt *d_ptr; +}; + +} + +#endif + From 512aa4c86712118eff4d5ad9aabac9059b5994cd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:27:05 +0200 Subject: [PATCH 120/220] Apply table changes to the loaded data, and offer to save when closing the changed table. --- .../translation_manager/uxt_editor.cpp | 52 ++++++++++++++++++- .../plugins/translation_manager/uxt_editor.h | 4 ++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 3ac7cb066..69cd1a9b6 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "nel/misc/diff_tool.h" @@ -17,9 +18,12 @@ public: UXTEditorPvt() { t = new QTableWidget(); + changed = false; } QTableWidget *t; + std::vector< STRING_MANAGER::TStringInfo > infos; + bool changed; }; @@ -30,6 +34,8 @@ CEditor( parent ) setAttribute( Qt::WA_DeleteOnClose ); d_ptr = new UXTEditorPvt(); + + blockTableSignals( false ); } UXTEditor::~UXTEditor() @@ -40,12 +46,16 @@ UXTEditor::~UXTEditor() void UXTEditor::open( QString filename ) { - std::vector< STRING_MANAGER::TStringInfo > infos; + std::vector< STRING_MANAGER::TStringInfo > &infos = d_ptr->infos; + + infos.clear(); STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); - if( infos.size() == 0 ) + if( d_ptr->infos.size() == 0 ) return; + blockTableSignals( true ); + d_ptr->t->clear(); d_ptr->t->setColumnCount( 2 ); d_ptr->t->setRowCount( infos.size() ); @@ -71,6 +81,8 @@ void UXTEditor::open( QString filename ) d_ptr->t->resizeColumnsToContents(); + blockTableSignals( false ); + setWidget( d_ptr->t ); setCurrentFile( filename ); } @@ -91,10 +103,38 @@ void UXTEditor::activateWindow() void UXTEditor::closeEvent( QCloseEvent *e ) { + if( d_ptr->changed ) + { + int reply = QMessageBox::question( this, + tr( "Table changed" ), + tr( "The table has changed. Would you like to save your changes?" ), + QMessageBox::Yes, + QMessageBox::No + ); + + if( reply == QMessageBox::Yes ) + save(); + + } + e->accept(); close(); } +void UXTEditor::onCellChanged( int row, int column ) +{ + QTableWidgetItem *item = d_ptr->t->item( row, column ); + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ row ]; + + if( column == 0 ) + info.Identifier = item->text().toUtf8().constData(); + else + if( column == 1 ) + info.Text = item->text().toUtf8().constData(); + + d_ptr->changed = true; +} + void UXTEditor::setHeaderText( const QString &id, const QString &text ) { QTableWidgetItem *h1 = new QTableWidgetItem( id ); @@ -105,4 +145,12 @@ void UXTEditor::setHeaderText( const QString &id, const QString &text ) d_ptr->t->setHorizontalHeaderItem( 1, h2 ); } +void UXTEditor::blockTableSignals( bool block ) +{ + if( block ) + disconnect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); + else + connect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); +} + } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 3f6d52b3a..5a96377a6 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -23,8 +23,12 @@ public: protected: void closeEvent( QCloseEvent *e ); +private Q_SLOTS: + void onCellChanged( int row, int column ); + private: void setHeaderText( const QString &id, const QString &text ); + void blockTableSignals( bool block = false ); UXTEditorPvt *d_ptr; }; From de87aca09d67f91df773e1274e7f2fd862483f38 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:50:40 +0200 Subject: [PATCH 121/220] Implemented saving. --- .../translation_manager_main_window.cpp | 4 ++- .../translation_manager/uxt_editor.cpp | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index f3e882739..59e8d5ebe 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -553,7 +553,9 @@ void CMainWindow::mergeSingleFile() void CMainWindow::onUxtClicked() { UXTEditor *e = new UXTEditor(); - e->open( work_path + "/" + QString( Constants::WK_UXT ) ); + QString path = work_path + "/" + QString( Constants::WK_UXT ); + e->open( path ); + e->setCurrentFile( path ); _ui.mdiArea->addSubWindow( e ); e->activateWindow(); } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 69cd1a9b6..6147b8de2 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -6,6 +6,9 @@ #include #include +#include +#include + #include "nel/misc/diff_tool.h" namespace TranslationManager @@ -89,10 +92,39 @@ void UXTEditor::open( QString filename ) void UXTEditor::save() { + saveAs( current_file ); } void UXTEditor::saveAs( QString filename ) { + QFile f( filename ); + if( !f.open( QIODevice::WriteOnly ) ) + return; + + QTextStream out( &f ); + + std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); + while( itr != d_ptr->infos.end() ) + { + QString line = ""; + + line += itr->Identifier.c_str(); + line += "\t"; + + line += "["; + line += itr->Text.toUtf8().c_str(); + line += "]"; + + line += "\r\n"; + + out << line; + + ++itr; + } + + f.close(); + + d_ptr->changed = false; } void UXTEditor::activateWindow() From 80d0c7c9c6bee79e76a83979a66d3a94a86d219b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:53:36 +0200 Subject: [PATCH 122/220] Added copyright headers to the new files. --- .../plugins/translation_manager/uxt_editor.cpp | 17 +++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 6147b8de2..a6c4ec500 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Translation Manager Plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "translation_manager_constants.h" #include "uxt_editor.h" diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 5a96377a6..738f88f7d 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Translation Manager Plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef UXT_EDITOR_H #define UXT_EDITOR_H From b86fce833c4d899ff87a4e0a2aec81406c537299 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:08:31 +0200 Subject: [PATCH 123/220] Allow only 1 instance of the uxt editor. --- .../translation_manager_main_window.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index 59e8d5ebe..aafc6f473 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -552,8 +552,13 @@ void CMainWindow::mergeSingleFile() void CMainWindow::onUxtClicked() { - UXTEditor *e = new UXTEditor(); QString path = work_path + "/" + QString( Constants::WK_UXT ); + path.replace( "\\", "/" ); + + if( getEditorByWindowFilePath( path ) != NULL ) + return; + + UXTEditor *e = new UXTEditor(); e->open( path ); e->setCurrentFile( path ); _ui.mdiArea->addSubWindow( e ); From 237ac85e9c90441ec884dc9bb784e3ef40efcabf Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:18:41 +0200 Subject: [PATCH 124/220] Use the QWidget modified property instead of the UXTEditor's own. --- .../studio/src/plugins/translation_manager/uxt_editor.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index a6c4ec500..bf6e787b6 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -38,12 +38,10 @@ public: UXTEditorPvt() { t = new QTableWidget(); - changed = false; } QTableWidget *t; std::vector< STRING_MANAGER::TStringInfo > infos; - bool changed; }; @@ -141,7 +139,7 @@ void UXTEditor::saveAs( QString filename ) f.close(); - d_ptr->changed = false; + setWindowModified( false ); } void UXTEditor::activateWindow() @@ -152,7 +150,7 @@ void UXTEditor::activateWindow() void UXTEditor::closeEvent( QCloseEvent *e ) { - if( d_ptr->changed ) + if( isWindowModified() ) { int reply = QMessageBox::question( this, tr( "Table changed" ), @@ -181,7 +179,7 @@ void UXTEditor::onCellChanged( int row, int column ) if( column == 1 ) info.Text = item->text().toUtf8().constData(); - d_ptr->changed = true; + setWindowModified( true ); } void UXTEditor::setHeaderText( const QString &id, const QString &text ) From ec89725824451b2881b5228fc9effe0e8732930f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:52:23 +0200 Subject: [PATCH 125/220] Implemented row deletion / insertion. --- .../translation_manager/uxt_editor.cpp | 24 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 4 ++++ 2 files changed, 28 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index bf6e787b6..cb4a0a0f3 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -148,6 +148,30 @@ void UXTEditor::activateWindow() } +void UXTEditor::insertRow() +{ + d_ptr->infos.push_back( STRING_MANAGER::TStringInfo() ); + d_ptr->t->setRowCount( d_ptr->t->rowCount() + 1 ); + + setWindowModified( true ); +} + + +void UXTEditor::deleteRow() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + std::vector< STRING_MANAGER::TStringInfo >::iterator itr = d_ptr->infos.begin(); + itr += r; + d_ptr->infos.erase( itr ); + + d_ptr->t->removeRow( r ); + + setWindowModified( true ); +} + void UXTEditor::closeEvent( QCloseEvent *e ) { if( isWindowModified() ) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 738f88f7d..d37be8c72 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -37,6 +37,10 @@ public: void saveAs( QString filename ); void activateWindow(); +public Q_SLOTS: + void insertRow(); + void deleteRow(); + protected: void closeEvent( QCloseEvent *e ); From 39c43b03a8a75d6b8f7f3c8eb13e3af7c96395b6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 19 Jul 2014 17:23:53 +0200 Subject: [PATCH 126/220] Show insert / delete row in context menu. --- .../plugins/translation_manager/uxt_editor.cpp | 16 ++++++++++++++++ .../src/plugins/translation_manager/uxt_editor.h | 1 + 2 files changed, 17 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index cb4a0a0f3..88d866fe2 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include #include #include @@ -192,6 +194,20 @@ void UXTEditor::closeEvent( QCloseEvent *e ) close(); } +void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) +{ + QMenu *menu = new QMenu( this ); + QAction *insertAction = new QAction( "Insert row", menu ); + QAction *deleteAction = new QAction( "Delete row", menu ); + + connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); + connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); + + menu->addAction( insertAction ); + menu->addAction( deleteAction ); + menu->exec( e->globalPos() ); +} + void UXTEditor::onCellChanged( int row, int column ) { QTableWidgetItem *item = d_ptr->t->item( row, column ); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index d37be8c72..7499df44c 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -43,6 +43,7 @@ public Q_SLOTS: protected: void closeEvent( QCloseEvent *e ); + void contextMenuEvent( QContextMenuEvent *e ); private Q_SLOTS: void onCellChanged( int row, int column ); From b0c916276d602e5b301219ca2757e8bde76819cb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 19 Jul 2014 17:26:59 +0200 Subject: [PATCH 127/220] Ask for confirmation before deleting a row. --- .../studio/src/plugins/translation_manager/uxt_editor.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 88d866fe2..4004c05e4 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -165,6 +165,14 @@ void UXTEditor::deleteRow() if( r < 0 ) return; + int answer = QMessageBox::question( this, + tr( "Deleting a row" ), + tr( "Are you sure you want to delete this row?" ), + QMessageBox::Yes, + QMessageBox::Cancel ); + if( QMessageBox::Yes != answer ) + return; + std::vector< STRING_MANAGER::TStringInfo >::iterator itr = d_ptr->infos.begin(); itr += r; d_ptr->infos.erase( itr ); From a51f76d03617ce45e38f2cbd9b2cba0f3c83ccba Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 17:24:04 +0200 Subject: [PATCH 128/220] Work with translated files, instead of work files. --- .../translation_manager_main_window.cpp | 25 ++++++++++++---- .../translation_manager_main_window.h | 3 +- .../translation_manager/uxt_editor.cpp | 30 ++++++++++++++----- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index aafc6f473..b439edce6 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -54,6 +54,7 @@ CMainWindow::CMainWindow(QWidget *parent) _ui.mdiArea->closeAllSubWindows(); windowMapper = new QSignalMapper(this); + m_UXTMapper = new QSignalMapper(this); connect(windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(setActiveSubWindow(QWidget *))); initialize_settings["georges"] = false; @@ -87,8 +88,20 @@ void CMainWindow::createMenus() { windowMenu = m->addMenu("Window"); - QAction *a = m->addAction( "Uxt" ); - connect( a, SIGNAL( triggered() ), this, SLOT( onUxtClicked() ) ); + QMenu *mm = m->addMenu( "UI translation" ); + if( mm != NULL ) + { + QStringListIterator itr( languages ); + while( itr.hasNext() ) + { + QString lang = itr.next(); + QAction *a = mm->addAction( lang ); + connect( a, SIGNAL( triggered() ), m_UXTMapper, SLOT( map() ) ); + m_UXTMapper->setMapping( a, lang ); + } + + connect( m_UXTMapper, SIGNAL( mapped( QString ) ), this, SLOT( onUxtMapped( QString ) ) ); + } menu = m; } @@ -550,14 +563,14 @@ void CMainWindow::mergeSingleFile() } } -void CMainWindow::onUxtClicked() +void CMainWindow::onUxtMapped( QString lang ) { - QString path = work_path + "/" + QString( Constants::WK_UXT ); + QString path = translation_path + "/" + lang + ".uxt"; path.replace( "\\", "/" ); - + if( getEditorByWindowFilePath( path ) != NULL ) return; - + UXTEditor *e = new UXTEditor(); e->open( path ); e->setCurrentFile( path ); diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h index ba6ce8746..34f60ff19 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.h +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.h @@ -71,6 +71,7 @@ private: QAction *saveAsAct; QMenu *windowMenu; QSignalMapper *windowMapper; + QSignalMapper *m_UXTMapper; // config QMap initialize_settings; QList filters; @@ -90,7 +91,7 @@ private Q_SLOTS: void setActiveSubWindow(QWidget *window); void updateWindowsList(); void mergeSingleFile(); - void onUxtClicked(); + void onUxtMapped( QString lang ); private: void openWorkFile(QString file); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 4004c05e4..9f8cc56f4 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -29,6 +29,7 @@ #include #include "nel/misc/diff_tool.h" +#include "nel/misc/i18n.h" namespace TranslationManager { @@ -120,23 +121,36 @@ void UXTEditor::saveAs( QString filename ) QTextStream out( &f ); + int idx = 0; std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); while( itr != d_ptr->infos.end() ) { - QString line = ""; + QString hashLine = "// HASH_VALUE "; + hashLine += QString( NLMISC::CI18N::hashToString( itr->HashValue ).c_str() ).toUpper(); + hashLine += "\r\n"; - line += itr->Identifier.c_str(); - line += "\t"; + QString idxLine = "// INDEX "; + idxLine += QString::number( idx ); + idxLine += "\r\n"; - line += "["; - line += itr->Text.toUtf8().c_str(); - line += "]"; + + QString trLine = ""; + trLine += itr->Identifier.c_str(); + trLine += "\t"; + trLine += "["; + trLine += itr->Text.toUtf8().c_str(); + trLine += "]"; + trLine += "\r\n"; - line += "\r\n"; + QString newLine = "\r\n"; - out << line; + out << hashLine; + out << idxLine; + out << trLine; + out << newLine; ++itr; + idx++; } f.close(); From ad06212de76f49b21ef7c223985de8c4493d2c16 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 19:52:23 +0200 Subject: [PATCH 129/220] Set header text according to the language. --- .../translation_manager/uxt_editor.cpp | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 9f8cc56f4..dc453b57f 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -31,6 +31,27 @@ #include "nel/misc/diff_tool.h" #include "nel/misc/i18n.h" +namespace +{ + +QString getLang( const QString &fn ) +{ + QString lang = fn; + int idx = lang.lastIndexOf( '/' ); + if( idx == -1 ) + return ""; + + lang = lang.mid( idx + 1 ); + idx = lang.lastIndexOf( '.' ); + if( idx == -1 ) + return ""; + + lang = lang.left( idx ); + return lang; +} + +} + namespace TranslationManager { @@ -68,12 +89,30 @@ UXTEditor::~UXTEditor() void UXTEditor::open( QString filename ) { std::vector< STRING_MANAGER::TStringInfo > &infos = d_ptr->infos; + QString lang = getLang( filename ); infos.clear(); STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) - return; + { + // The work file cannot be found, cannot proceed + if( filename.endsWith( "wk.uxt" ) ) + { + return; + } + + int l = filename.lastIndexOf( "/" ); + if( l == -1 ) + return; + filename = filename.left( l ); + filename += "/wk.uxt"; + + // The work file cannot be found, cannot proceed + STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + if( d_ptr->infos.size() == 0 ) + return; + } blockTableSignals( true ); @@ -81,7 +120,7 @@ void UXTEditor::open( QString filename ) d_ptr->t->setColumnCount( 2 ); d_ptr->t->setRowCount( infos.size() ); - setHeaderText( "Id", "Text" ); + setHeaderText( "Id", lang.toUpper() + " Text" ); int i = 0; From 164eac0eba681d5bc923271a05704ae72f330813 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 20:03:16 +0200 Subject: [PATCH 130/220] Save to the right file. --- .../translation_manager_main_window.cpp | 1 - .../src/plugins/translation_manager/uxt_editor.cpp | 12 ++++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp index b439edce6..c5228fae6 100644 --- a/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp +++ b/code/studio/src/plugins/translation_manager/translation_manager_main_window.cpp @@ -573,7 +573,6 @@ void CMainWindow::onUxtMapped( QString lang ) UXTEditor *e = new UXTEditor(); e->open( path ); - e->setCurrentFile( path ); _ui.mdiArea->addSubWindow( e ); e->activateWindow(); } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index dc453b57f..38f8fa76d 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -105,11 +105,12 @@ void UXTEditor::open( QString filename ) int l = filename.lastIndexOf( "/" ); if( l == -1 ) return; - filename = filename.left( l ); - filename += "/wk.uxt"; + + QString fn = filename.left( l ); + fn += "/wk.uxt"; // The work file cannot be found, cannot proceed - STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) return; } @@ -144,7 +145,10 @@ void UXTEditor::open( QString filename ) blockTableSignals( false ); setWidget( d_ptr->t ); - setCurrentFile( filename ); + + current_file = filename; + setWindowTitle( filename + "[*]" ); + setWindowFilePath( filename ); } void UXTEditor::save() From 232e830c3cf0b82e5c55ba845336d7af45b8daec Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 03:24:18 +0200 Subject: [PATCH 131/220] Make sure a correct hash is not used for untranslated strings. --- .../translation_manager/uxt_editor.cpp | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 38f8fa76d..1ea22870d 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -62,10 +62,12 @@ public: UXTEditorPvt() { t = new QTableWidget(); + loadedFromWK = false; } QTableWidget *t; std::vector< STRING_MANAGER::TStringInfo > infos; + bool loadedFromWK; }; @@ -92,7 +94,7 @@ void UXTEditor::open( QString filename ) QString lang = getLang( filename ); infos.clear(); - STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, true ); + STRING_MANAGER::loadStringFile( filename.toUtf8().constData(), infos, false ); if( d_ptr->infos.size() == 0 ) { @@ -113,6 +115,8 @@ void UXTEditor::open( QString filename ) STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) return; + + d_ptr->loadedFromWK = true; } blockTableSignals( true ); @@ -168,8 +172,25 @@ void UXTEditor::saveAs( QString filename ) std::vector< STRING_MANAGER::TStringInfo >::const_iterator itr = d_ptr->infos.begin(); while( itr != d_ptr->infos.end() ) { + uint64 hash = 0; + + // If text2 is not empty we can assume the string was translated, so we store with the correct hash + // If text2 is empty, it wasn't translated so we can just use the old hash. + // Additionally, if the strings were loaded from the wk.uxt file, we use a hash of 0 so we know it was not translated + if( itr->Text2.empty() ) + { + if( d_ptr->loadedFromWK ) + hash = 0; + else + hash = itr->HashValue; + } + else + { + hash = NLMISC::CI18N::makeHash( itr->Text2 ); + } + QString hashLine = "// HASH_VALUE "; - hashLine += QString( NLMISC::CI18N::hashToString( itr->HashValue ).c_str() ).toUpper(); + hashLine += QString( NLMISC::CI18N::hashToString( hash ).c_str() ).toUpper(); hashLine += "\r\n"; QString idxLine = "// INDEX "; @@ -181,7 +202,12 @@ void UXTEditor::saveAs( QString filename ) trLine += itr->Identifier.c_str(); trLine += "\t"; trLine += "["; - trLine += itr->Text.toUtf8().c_str(); + + if( itr->Text2.empty() ) + trLine += itr->Text.toUtf8().c_str(); + else + trLine += itr->Text2.toUtf8().c_str(); + trLine += "]"; trLine += "\r\n"; @@ -282,7 +308,7 @@ void UXTEditor::onCellChanged( int row, int column ) info.Identifier = item->text().toUtf8().constData(); else if( column == 1 ) - info.Text = item->text().toUtf8().constData(); + info.Text2 = item->text().toUtf8().constData(); setWindowModified( true ); } From 7988a71c981959d8453598791cd997327ef1ecde Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 03:51:03 +0200 Subject: [PATCH 132/220] New context menu options: mark / unmark translated. --- .../translation_manager/uxt_editor.cpp | 37 ++++++++++++++++++- .../plugins/translation_manager/uxt_editor.h | 2 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 1ea22870d..fcd6e74cf 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -290,12 +290,18 @@ void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) QMenu *menu = new QMenu( this ); QAction *insertAction = new QAction( "Insert row", menu ); QAction *deleteAction = new QAction( "Delete row", menu ); + QAction *markAction = new QAction( "Mark translated", menu ); + QAction *unmarkAction = new QAction( "Mark not-translated", menu ); connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); - connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); + connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); + connect( markAction, SIGNAL( triggered( bool ) ), this, SLOT( markTranslated() ) ); + connect( unmarkAction, SIGNAL( triggered( bool ) ), this, SLOT( markUntranslated() ) ); menu->addAction( insertAction ); menu->addAction( deleteAction ); + menu->addAction( markAction ); + menu->addAction( unmarkAction ); menu->exec( e->globalPos() ); } @@ -313,6 +319,35 @@ void UXTEditor::onCellChanged( int row, int column ) setWindowModified( true ); } +void UXTEditor::markTranslated() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; + if( !info.Text2.empty() ) + return; + + info.Text2 = info.Text; + + setWindowModified( true ); +} + +void UXTEditor::markUntranslated() +{ + int r = d_ptr->t->currentRow(); + if( r < 0 ) + return; + + STRING_MANAGER::TStringInfo &info = d_ptr->infos[ r ]; + + info.Text2.clear(); + info.HashValue = 0; + + setWindowModified( true ); +} + void UXTEditor::setHeaderText( const QString &id, const QString &text ) { QTableWidgetItem *h1 = new QTableWidgetItem( id ); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 7499df44c..00716ee2f 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -47,6 +47,8 @@ protected: private Q_SLOTS: void onCellChanged( int row, int column ); + void markTranslated(); + void markUntranslated(); private: void setHeaderText( const QString &id, const QString &text ); From 741fee935efd8bf7c009d152b473b8a93a3808db Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 04:11:53 +0200 Subject: [PATCH 133/220] Mark translated item with green, untranslated ones with red. --- .../translation_manager/uxt_editor.cpp | 51 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 2 + 2 files changed, 53 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index fcd6e74cf..d6e7c5fa0 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -55,6 +55,16 @@ QString getLang( const QString &fn ) namespace TranslationManager { +void markItemTranslated( QTableWidgetItem *item ) +{ + item->setBackground( QColor::fromRgb( 126, 247, 134 ) ); +} + +void markItemUntranslated( QTableWidgetItem *item ) +{ + item->setBackground( QColor::fromRgb( 247, 126, 126 ) ); +} + class UXTEditorPvt { public: @@ -139,6 +149,17 @@ void UXTEditor::open( QString filename ) d_ptr->t->setItem( i, 0, name ); d_ptr->t->setItem( i, 1, text1 ); + + if( ( info.HashValue != 0 ) && !d_ptr->loadedFromWK ) + { + markItemTranslated( name ); + markItemTranslated( text1 ); + } + else + { + markItemUntranslated( name ); + markItemUntranslated( text1 ); + } ++itr; i++; @@ -317,6 +338,8 @@ void UXTEditor::onCellChanged( int row, int column ) info.Text2 = item->text().toUtf8().constData(); setWindowModified( true ); + + markRowTranslated( row ); } void UXTEditor::markTranslated() @@ -332,6 +355,8 @@ void UXTEditor::markTranslated() info.Text2 = info.Text; setWindowModified( true ); + + markRowTranslated( r ); } void UXTEditor::markUntranslated() @@ -346,6 +371,8 @@ void UXTEditor::markUntranslated() info.HashValue = 0; setWindowModified( true ); + + markRowUntranslated( r ); } void UXTEditor::setHeaderText( const QString &id, const QString &text ) @@ -366,4 +393,28 @@ void UXTEditor::blockTableSignals( bool block ) connect( d_ptr->t, SIGNAL( cellChanged( int, int ) ), this, SLOT( onCellChanged( int, int ) ) ); } +void UXTEditor::markRowTranslated( int row ) +{ + blockTableSignals( true ); + + QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); + QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); + markItemTranslated( item1 ); + markItemTranslated( item2 ); + + blockTableSignals( false ); +} + +void UXTEditor::markRowUntranslated( int row ) +{ + blockTableSignals( true ); + + QTableWidgetItem *item1 = d_ptr->t->item( row, 0 ); + QTableWidgetItem *item2 = d_ptr->t->item( row, 1 ); + markItemUntranslated( item1 ); + markItemUntranslated( item2 ); + + blockTableSignals( false ); +} + } diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index 00716ee2f..b0f977709 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -53,6 +53,8 @@ private Q_SLOTS: private: void setHeaderText( const QString &id, const QString &text ); void blockTableSignals( bool block = false ); + void markRowTranslated( int row ); + void markRowUntranslated( int row ); UXTEditorPvt *d_ptr; }; From d63c78b50311d6afb7f9608e399c169628edfbee Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 17:46:01 +0200 Subject: [PATCH 134/220] Shouldn't crash when adding a new row. --- .../src/plugins/translation_manager/uxt_editor.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index d6e7c5fa0..6c108b667 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -256,10 +256,22 @@ void UXTEditor::activateWindow() void UXTEditor::insertRow() { + blockTableSignals( true ); + d_ptr->infos.push_back( STRING_MANAGER::TStringInfo() ); d_ptr->t->setRowCount( d_ptr->t->rowCount() + 1 ); + int row = d_ptr->t->rowCount() - 1; + + QTableWidgetItem *item1 = new QTableWidgetItem(); + QTableWidgetItem *item2 = new QTableWidgetItem(); + d_ptr->t->setItem( row, 0, item1 ); + d_ptr->t->setItem( row, 1, item2 ); + + markRowUntranslated( row ); setWindowModified( true ); + + blockTableSignals( false ); } From 7c0cd64ae77f8a0329a1224c218c0c847072e6f2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 23:08:05 +0200 Subject: [PATCH 135/220] Added save and save as items to the context menu. --- .../translation_manager/uxt_editor.cpp | 32 +++++++++++++++++++ .../plugins/translation_manager/uxt_editor.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 6c108b667..b9548e0b5 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -325,16 +326,22 @@ void UXTEditor::contextMenuEvent( QContextMenuEvent *e ) QAction *deleteAction = new QAction( "Delete row", menu ); QAction *markAction = new QAction( "Mark translated", menu ); QAction *unmarkAction = new QAction( "Mark not-translated", menu ); + QAction *saveAction = new QAction( "Save", menu ); + QAction *saveAsAction = new QAction( "Save as..", menu ); connect( insertAction, SIGNAL( triggered( bool ) ), this, SLOT( insertRow() ) ); connect( deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteRow() ) ); connect( markAction, SIGNAL( triggered( bool ) ), this, SLOT( markTranslated() ) ); connect( unmarkAction, SIGNAL( triggered( bool ) ), this, SLOT( markUntranslated() ) ); + connect( saveAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveClicked() ) ); + connect( saveAsAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAsClicked() ) ); menu->addAction( insertAction ); menu->addAction( deleteAction ); menu->addAction( markAction ); menu->addAction( unmarkAction ); + menu->addAction( saveAction ); + menu->addAction( saveAsAction ); menu->exec( e->globalPos() ); } @@ -387,6 +394,31 @@ void UXTEditor::markUntranslated() markRowUntranslated( r ); } +void UXTEditor::onSaveClicked() +{ + save(); +} + +void UXTEditor::onSaveAsClicked() +{ + QString path = current_file; + int idx = path.lastIndexOf( '/' ); + if( idx < 0 ) + path = ""; + else + path = path.left( idx + 1 ); + + QString file = QFileDialog::getSaveFileName( this, + tr( "Save Uxt as.." ), + path, + tr( "Uxt files ( *.uxt)" ) ); + + if( file.isEmpty() ) + return; + + saveAs( file ); +} + void UXTEditor::setHeaderText( const QString &id, const QString &text ) { QTableWidgetItem *h1 = new QTableWidgetItem( id ); diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.h b/code/studio/src/plugins/translation_manager/uxt_editor.h index b0f977709..b749e65e3 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.h +++ b/code/studio/src/plugins/translation_manager/uxt_editor.h @@ -49,6 +49,8 @@ private Q_SLOTS: void onCellChanged( int row, int column ); void markTranslated(); void markUntranslated(); + void onSaveClicked(); + void onSaveAsClicked(); private: void setHeaderText( const QString &id, const QString &text ); From bfb04d7dda35e481ec1741c1afc44f4baefe24fd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 23:25:35 +0200 Subject: [PATCH 136/220] Error message when files can't be opened. --- .../studio/src/plugins/translation_manager/uxt_editor.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index b9548e0b5..99b0b200c 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -112,6 +112,9 @@ void UXTEditor::open( QString filename ) // The work file cannot be found, cannot proceed if( filename.endsWith( "wk.uxt" ) ) { + QMessageBox::critical( this, + tr( "Error opening file.." ), + tr( "There was an error opening wk.uxt" ) ); return; } @@ -125,7 +128,12 @@ void UXTEditor::open( QString filename ) // The work file cannot be found, cannot proceed STRING_MANAGER::loadStringFile( fn.toUtf8().constData(), infos, true ); if( d_ptr->infos.size() == 0 ) + { + QMessageBox::critical( this, + tr( "Error opening Uxt file" ), + tr( "Neither the specified file nor wk.uxt could be opened." ) ); return; + } d_ptr->loadedFromWK = true; } From 395fafd2fee17136f7d2c58000d600f08216ae9d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 14:44:31 +0200 Subject: [PATCH 137/220] Update qrc location. --- .../studio/src/plugins/tile_editor/tile_editor_main_window.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 66a086179..cfa6c4fa1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -309,7 +309,7 @@ - + :/newPrefix/reset.png:/newPrefix/reset.png @@ -789,7 +789,7 @@ - + From c369f49b8afaf2375cc1a0b6d8936ebfd91475f1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 15:35:14 +0200 Subject: [PATCH 138/220] Don't allow 2 tilesets to have the same name. --- .../tile_editor/tile_editor_main_window.cpp | 14 ++++++-------- .../studio/src/plugins/tile_editor/tile_item.h | 2 +- .../src/plugins/tile_editor/tile_model.cpp | 18 ++++++++++++++++++ .../src/plugins/tile_editor/tile_model.h | 2 ++ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index d1199ebc9..a4643f7a0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -226,15 +226,13 @@ void TileEditorMainWindow::onTileSetAdd() QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) { - //if (ui.tileSetListWidget->findItems(text, Qt::MatchExactly).count() > 0) - //{ - // QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); - //} - //else - //{ - - //QModelIndex index = m_ui->tileSetLV->selectionModel()->currentIndex(); TileModel *model = static_cast(m_ui->tileSetLV->model()); + + if( model->hasTileSet( text ) ) + { + QMessageBox::information( this, tr("Error Adding Tile Set"), tr("This name already exists") ); + return; + } //if(index.isValid()) //{ diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index f89b20ab7..75108c77e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -67,7 +67,7 @@ public: QVariant data(int column, int role) const; int columnCount() const; - const QString &getTileSetName(); + const QString &getTileSetName(){ return m_tileSetName; } private: QString m_tileSetName; }; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index c167dbd44..7c444606f 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -219,6 +219,24 @@ uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) return 0; } +bool TileModel::hasTileSet( const QString &name ) +{ + for( int i = 0; i < rowCount(); i++ ) + { + QModelIndex idx = index( i, 0 ); + if( !idx.isValid() ) + { + continue; + } + + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + if( n->getTileSetName() == name ) + return true; + } + + return false; +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index bd7d808fb..68d8cfeef 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -87,6 +87,8 @@ public: static TTileZoomFactor CurrentZoomFactor; + bool hasTileSet( const QString &name ); + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); From 068a10ea6dd4b08176a8f208ea9feb5c16f792a1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 15:38:26 +0200 Subject: [PATCH 139/220] Don't try to delete the same items more than once! --- code/studio/src/plugins/tile_editor/tile_item.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 9d9418561..ef80cc302 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -35,6 +35,7 @@ Node::Node(const QVector &data, Node *parent) Node::~Node() { qDeleteAll(m_childItems); + m_childItems.clear(); } void Node::appendChild(Node *item) @@ -164,6 +165,7 @@ TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tile TileSetNode::~TileSetNode() { qDeleteAll(m_childItems); + m_childItems.clear(); } QVariant TileSetNode::data(int column, int role) const @@ -191,6 +193,7 @@ TileTypeNode::TileTypeNode(TileModel::TNodeTileType type, Node *parent) : m_node TileTypeNode::~TileTypeNode() { qDeleteAll(m_childItems); + m_childItems.clear(); } QVariant TileTypeNode::data(int column, int role) const From acf3f656b2438488b3318550df8e1eb8ea4919ef Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Jul 2014 18:35:26 +0200 Subject: [PATCH 140/220] Implemented tileset removal. --- .../tile_editor/tile_editor_main_window.cpp | 13 +++++++++++++ .../plugins/tile_editor/tile_editor_main_window.h | 1 + .../tile_editor/tile_editor_main_window.ui | 2 +- .../studio/src/plugins/tile_editor/tile_model.cpp | 15 +++++++++++++++ code/studio/src/plugins/tile_editor/tile_model.h | 2 ++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a4643f7a0..6656ba793 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -88,6 +88,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); + connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -261,6 +262,18 @@ void TileEditorMainWindow::onTileSetAdd() } } +void TileEditorMainWindow::onTileSetDelete() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + bool ok = model->removeRow( idx.row() ); + + //m_ui->tileSetLV->reset(); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 0effbe087..a4f2fe623 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -48,6 +48,7 @@ public Q_SLOTS: void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); void onTileSetAdd(); + void onTileSetDelete(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index cfa6c4fa1..ef2061e38 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -505,7 +505,7 @@ - + ... diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 7c444606f..a5527fb56 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -140,6 +140,21 @@ void TileModel::appendRow(Node *item) rootItem->appendRow(item); } +bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) +{ + int c = rootItem->childCount(); + if( row + count > c ) + return false; + + beginRemoveRows( QModelIndex(), row, row + count - 1 ); + + bool ok = rootItem->removeChildren( row, count ); + + endRemoveRows(); + + return ok; +} + TileSetNode *TileModel::createTileSetNode(QString tileSetName) { // Create the new tile set. diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 68d8cfeef..cdf85acc3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -80,6 +80,8 @@ public: void appendRow(const QList &items); void appendRow(Node *item); + bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ); + TileSetNode *createTileSetNode(QString tileSetName); static const char *getTileTypeName(TNodeTileType type); From 764b80b751aa31e5da91e6531805905542407a71 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Jul 2014 21:53:09 +0200 Subject: [PATCH 141/220] Implemented tileset rename. --- .../tile_editor/tile_editor_main_window.cpp | 35 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + .../tile_editor/tile_editor_main_window.ui | 2 +- .../src/plugins/tile_editor/tile_item.h | 2 ++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 6656ba793..8ab499bf8 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -89,6 +89,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); + connect(m_ui->tileSetEditTB, SIGNAL(clicked()), this, SLOT(onTileSetEdit())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -274,6 +275,40 @@ void TileEditorMainWindow::onTileSetDelete() //m_ui->tileSetLV->reset(); } +void TileEditorMainWindow::onTileSetEdit() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + QString name = node->getTileSetName(); + + bool ok = false; + + QString newName = QInputDialog::getText( this, + tr( "Edit tileset" ), + tr( "Enter tileset name" ), + QLineEdit::Normal, + name, + &ok ); + + if( !ok ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + if( model->hasTileSet( newName ) ) + { + QMessageBox::information( this, + tr("Tileset already exists"), + tr("A tileset with that name already exists!") ); + return; + } + + node->setTileSetName( newName ); + m_ui->tileSetLV->reset(); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index a4f2fe623..8719f799a 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -49,6 +49,7 @@ public Q_SLOTS: void onActionDeleteImage(bool triggered); void onTileSetAdd(); void onTileSetDelete(); + void onTileSetEdit(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index ef2061e38..a88c11d0e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -516,7 +516,7 @@ - + ... diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 75108c77e..69fc89d71 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -68,6 +68,8 @@ public: int columnCount() const; const QString &getTileSetName(){ return m_tileSetName; } + void setTileSetName( const QString &name ){ m_tileSetName = name; } + private: QString m_tileSetName; }; From 347a883d7b2d4b77b7d3f090eab0e708139e9dd9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 02:28:19 +0200 Subject: [PATCH 142/220] Implemented tileset move up and move down. --- .../tile_editor/tile_editor_main_window.cpp | 62 +++++++++++++------ .../tile_editor/tile_editor_main_window.h | 2 + .../tile_editor/tile_editor_main_window.ui | 4 +- .../src/plugins/tile_editor/tile_item.cpp | 7 +++ .../src/plugins/tile_editor/tile_item.h | 2 + .../src/plugins/tile_editor/tile_model.cpp | 5 ++ .../src/plugins/tile_editor/tile_model.h | 2 + 7 files changed, 63 insertions(+), 21 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 8ab499bf8..88090de47 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -87,9 +87,13 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Set up the tile set list view. m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); + connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); connect(m_ui->tileSetEditTB, SIGNAL(clicked()), this, SLOT(onTileSetEdit())); + connect(m_ui->tileSetUpTB, SIGNAL(clicked()), this, SLOT(onTileSetUp())); + connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); + connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -236,23 +240,6 @@ void TileEditorMainWindow::onTileSetAdd() return; } - //if(index.isValid()) - //{ - // if(!model->insertRow(index.row()+1, index.parent())) - // return; - - // //updateActions() - - // for(int column=0; columncolumnCount(index.parent()); column++) - // { - // QModelIndex child = model->index(index.row()+1, column, index.parent()); - // model->setData(child, QVariant(text), Qt::EditRole); - // } - //} - //else - //{ - - // Create and append the new tile set to the model. TileSetNode *tileSet = model->createTileSetNode(text); @@ -271,8 +258,6 @@ void TileEditorMainWindow::onTileSetDelete() TileModel *model = static_cast(m_ui->tileSetLV->model()); bool ok = model->removeRow( idx.row() ); - - //m_ui->tileSetLV->reset(); } void TileEditorMainWindow::onTileSetEdit() @@ -309,6 +294,45 @@ void TileEditorMainWindow::onTileSetEdit() m_ui->tileSetLV->reset(); } +void TileEditorMainWindow::onTileSetUp() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + if( idx.row() == 0 ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + if( model->rowCount() < 2 ) + return; + + int r = idx.row(); + model->swapRows( r, r - 1 ); + + m_ui->tileSetLV->reset(); + m_ui->tileSetLV->setCurrentIndex( model->index( r - 1, 0 ) ); +} + +void TileEditorMainWindow::onTileSetDown() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileModel *model = static_cast(m_ui->tileSetLV->model()); + if( model->rowCount() < idx.row() ) + return; + if( model->rowCount() < 2 ) + return; + + int r = idx.row(); + model->swapRows( r, r + 1 ); + + m_ui->tileSetLV->reset(); + m_ui->tileSetLV->setCurrentIndex( model->index( r + 1, 0 ) ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 8719f799a..c830666a0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -50,6 +50,8 @@ public Q_SLOTS: void onTileSetAdd(); void onTileSetDelete(); void onTileSetEdit(); + void onTileSetUp(); + void onTileSetDown(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index a88c11d0e..f90ac69fb 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -442,7 +442,7 @@ - + ... @@ -453,7 +453,7 @@ - + ... diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index ef80cc302..230776fbd 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -155,6 +155,13 @@ void Node::appendRow(Node *item) m_childItems.append(item); } +void Node::swapRows( int a, int b ) +{ + Node *temp = m_childItems[ a ]; + m_childItems[ a ] = m_childItems[ b ]; + m_childItems[ b ] = temp; +} + /////////////////////////////////////////////////// TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 69fc89d71..56adfa926 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -53,6 +53,8 @@ public: void appendRow(const QList &items); void appendRow(Node *item); + void swapRows( int a, int b ); + protected: QList m_childItems; QVector m_itemData; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index a5527fb56..4b6d2113d 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -155,6 +155,11 @@ bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) return ok; } +void TileModel::swapRows( int a, int b ) +{ + rootItem->swapRows( a, b ); +} + TileSetNode *TileModel::createTileSetNode(QString tileSetName) { // Create the new tile set. diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index cdf85acc3..239c423cb 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -82,6 +82,8 @@ public: bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ); + void swapRows( int a, int b ); + TileSetNode *createTileSetNode(QString tileSetName); static const char *getTileTypeName(TNodeTileType type); From f67e5b4e5b5ef3877f80f90b1282c6b99e133fda Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:09:58 +0200 Subject: [PATCH 143/220] Renamed land related widgets. --- .../src/plugins/tile_editor/tile_editor_main_window.ui | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index f90ac69fb..07fbf08aa 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -352,7 +352,7 @@ - + @@ -370,7 +370,7 @@ - + ... @@ -381,7 +381,7 @@ - + ... @@ -392,7 +392,7 @@ - + ... From 7c1f53994dab56f84a82048b9f654af33d126329 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:18:01 +0200 Subject: [PATCH 144/220] Implemented land adding. --- .../tile_editor/tile_editor_main_window.cpp | 26 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 4 +++ 2 files changed, 30 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 88090de47..1a7dc164b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -94,6 +94,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->tileSetUpTB, SIGNAL(clicked()), this, SLOT(onTileSetUp())); connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); + connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); + connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); @@ -333,6 +335,30 @@ void TileEditorMainWindow::onTileSetDown() m_ui->tileSetLV->setCurrentIndex( model->index( r + 1, 0 ) ); } +void TileEditorMainWindow::onLandAdd() +{ + QString name = QInputDialog::getText( this, + tr("Adding new land"), + tr("Please specify the new land's name") ); + + if( name.isEmpty() ) + return; + + for( int i = 0; i < m_ui->landLW->count(); i++ ) + { + QListWidgetItem *item = m_ui->landLW->item( i ); + if( item->text() == name ) + { + QMessageBox::information( this, + tr( "Error adding new land" ), + tr( "A land with that name already exists." ) ); + return; + } + } + + m_ui->landLW->addItem( name ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index c830666a0..6d1aa82c7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -47,11 +47,15 @@ public Q_SLOTS: void onActionDeleteTile(bool triggered); void onActionReplaceImage(bool triggered); void onActionDeleteImage(bool triggered); + void onTileSetAdd(); void onTileSetDelete(); void onTileSetEdit(); void onTileSetUp(); void onTileSetDown(); + + void onLandAdd(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); From c81e70b9b20014e2a801e324c736f01aea15cd84 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:20:44 +0200 Subject: [PATCH 145/220] Implemented land removal. --- .../plugins/tile_editor/tile_editor_main_window.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 11 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 1a7dc164b..26f92b6ae 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -95,6 +95,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); + connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), @@ -359,6 +360,15 @@ void TileEditorMainWindow::onLandAdd() m_ui->landLW->addItem( name ); } +void TileEditorMainWindow::onLandRemove() +{ + QListWidgetItem *item = m_ui->landLW->currentItem(); + if( item == NULL ) + return; + + delete item; +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 6d1aa82c7..cc7312b7d 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -55,6 +55,7 @@ public Q_SLOTS: void onTileSetDown(); void onLandAdd(); + void onLandRemove(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); From c1d6ada9c6f652ef6df11de82cb6d5a8b51ae33e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:25:28 +0200 Subject: [PATCH 146/220] Implemented land name changing. --- .../tile_editor/tile_editor_main_window.cpp | 22 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 23 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 26f92b6ae..11f5d79b0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -96,6 +96,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); + connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), @@ -369,6 +370,27 @@ void TileEditorMainWindow::onLandRemove() delete item; } +void TileEditorMainWindow::onLandEdit() +{ + QListWidgetItem *item = m_ui->landLW->currentItem(); + if( item == NULL ) + return; + + QString name = item->text(); + + QString newName = QInputDialog::getText( this, + tr( "Editing land" ), + tr( "Please specify the new name of the selected land" ), + QLineEdit::Normal, + name ); + + if( newName.isEmpty() ) + return; + if( newName == name ) + return; + item->setText( newName ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index cc7312b7d..31e65df27 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -56,6 +56,7 @@ public Q_SLOTS: void onLandAdd(); void onLandRemove(); + void onLandEdit(); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); From 25dba4695d17646be16b0b47f5539a555601d6b8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:31:07 +0200 Subject: [PATCH 147/220] Each land has it's own TilesetModel now. When changing the land the model also changes. --- .../tile_editor/tile_editor_main_window.cpp | 88 ++++++++++++++++--- .../tile_editor/tile_editor_main_window.h | 6 +- .../src/plugins/tile_editor/tile_model.h | 3 +- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 11f5d79b0..2f3127c8e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -79,13 +79,10 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) core->menuManager()->menuBar()->addMenu(m_tileEditorMenu); // Set up the list views. - QStringList headers; - headers << "Tile Set"; - m_model = new TileModel(headers, this); m_tileItemDelegate = new TileItemDelegate(); // Set up the tile set list view. - m_ui->tileSetLV->setModel(m_model); + //m_ui->tileSetLV->setModel(m_model); //m_ui->tileSetLV->setRootIndex(m_model->index(0,0)); connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); @@ -97,6 +94,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); + connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); connect(m_ui->tileSetLV->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), @@ -104,7 +102,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); - m_ui->listView128->setModel(m_model); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); m_ui->listView128->addAction(m_ui->actionReplaceImage); @@ -112,7 +109,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // 256x256 List View //m_ui->listView256->setItemDelegate(m_tileItemDelegate); - m_ui->listView256->setModel(m_model); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); m_ui->listView256->addAction(m_ui->actionReplaceImage); @@ -120,13 +116,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Transition List View //m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); - m_ui->listViewTransition->setModel(m_model); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View //m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); - m_ui->listViewDisplacement->setModel(m_model); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -137,9 +131,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); - connect(m_ui->actionTileDisplayFilename, SIGNAL(toggled(bool)), m_model, SLOT(selectFilenameDisplay(bool))); - connect(m_ui->actionTileDisplayIndex, SIGNAL(toggled(bool)), m_model, SLOT(selectIndexDisplay(bool))); - //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); // Connect the zoom buttons. @@ -164,6 +155,9 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_zoomMenu; delete m_zoomActionGroup; delete m_zoomSignalMapper; + + qDeleteAll( m_tileModels ); + m_tileModels.clear(); } void TileEditorMainWindow::onZoomFactor(int level) @@ -232,6 +226,14 @@ void TileEditorMainWindow::onActionDeleteImage(bool triggered) void TileEditorMainWindow::onTileSetAdd() { + if( m_ui->landLW->count() == 0 ) + { + QMessageBox::information( this, + tr( "Error adding tile set" ), + tr( "You need to add a land before adding a tileset!" ) ); + return; + } + bool ok; QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) @@ -260,6 +262,14 @@ void TileEditorMainWindow::onTileSetDelete() if( !idx.isValid() ) return; + int reply = QMessageBox::question( this, + tr( "Removing tile set" ), + tr( "Are you sure you want to remove this tile set?" ), + QMessageBox::Yes | QMessageBox::Cancel ); + + if( reply != QMessageBox::Yes ) + return; + TileModel *model = static_cast(m_ui->tileSetLV->model()); bool ok = model->removeRow( idx.row() ); } @@ -359,6 +369,13 @@ void TileEditorMainWindow::onLandAdd() } m_ui->landLW->addItem( name ); + + TileModel *m = createTileModel(); + + m_tileModels.push_back( m ); + + if( m_tileModels.count() == 1 ) + m_ui->landLW->setCurrentRow( 0 ); } void TileEditorMainWindow::onLandRemove() @@ -367,6 +384,21 @@ void TileEditorMainWindow::onLandRemove() if( item == NULL ) return; + int idx = m_ui->landLW->currentRow(); + + int reply = QMessageBox::question( this, + tr( "Removing land" ), + tr( "Are you sure you want to remove this land?" ), + QMessageBox::Yes | QMessageBox::Cancel ); + + if( reply != QMessageBox::Yes ) + return; + + QList< TileModel* >::iterator itr = m_tileModels.begin() + idx; + delete m_tileModels[ idx ]; + m_tileModels[ idx ] = NULL; + m_tileModels.erase( itr ); + delete item; } @@ -391,6 +423,28 @@ void TileEditorMainWindow::onLandEdit() item->setText( newName ); } +void TileEditorMainWindow::onLandRowChanged( int row ) +{ + if( row == -1 ) + { + m_ui->tileSetLV->setModel( NULL ); + m_ui->listView128->setModel( NULL ); + m_ui->listView256->setModel( NULL ); + m_ui->listViewTransition->setModel( NULL ); + m_ui->listViewDisplacement->setModel( NULL ); + } + else + { + m_ui->tileSetLV->setModel( m_tileModels[ row ] ); + m_ui->listView128->setModel( m_tileModels[ row ] ); + m_ui->listView256->setModel( m_tileModels[ row ] ); + m_ui->listViewTransition->setModel( m_tileModels[ row ] ); + m_ui->listViewDisplacement->setModel( m_tileModels[ row ] ); + } + + m_ui->tileSetLV->reset(); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; @@ -398,6 +452,18 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); } +TileModel* TileEditorMainWindow::createTileModel() +{ + QStringList headers; + headers << "Tile Set"; + TileModel *m = new TileModel( headers ); + + connect( m_ui->actionTileDisplayFilename, SIGNAL( toggled( bool )), m, SLOT( selectFilenameDisplay( bool ) ) ); + connect( m_ui->actionTileDisplayIndex, SIGNAL( toggled( bool )), m, SLOT( selectIndexDisplay( bool ) ) ); + + return m; +} + void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex) { TileModel *model = static_cast(m_ui->tileSetLV->model()); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 31e65df27..58f546ea9 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -57,6 +57,7 @@ public Q_SLOTS: void onLandAdd(); void onLandRemove(); void onLandEdit(); + void onLandRowChanged( int row ); void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); @@ -64,6 +65,8 @@ public Q_SLOTS: private: void onActionAddTile(int tabId); + TileModel* createTileModel(); + Ui::TileEditorMainWindow *m_ui; QUndoStack *m_undoStack; QMenu *m_rotationMenu; @@ -75,8 +78,9 @@ private: QActionGroup *m_zoomActionGroup; QSignalMapper *m_zoomSignalMapper; - TileModel *m_model; TileItemDelegate *m_tileItemDelegate; + + QList< TileModel* > m_tileModels; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 239c423cb..e2be8da57 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -64,8 +64,7 @@ public: static const int TILE_128_BASE_SIZE = 128; static const int TILE_256_BASE_SIZE = 256; - - TileModel(const QStringList &headers, QObject *parent); + TileModel(const QStringList &headers, QObject *parent = NULL); ~TileModel(); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; From 8034eac2e0d7df44c0c359a9e3da319fb5198e64 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:39:34 +0200 Subject: [PATCH 148/220] Connect the selection model so the widgets are updated. --- .../plugins/tile_editor/tile_editor_main_window.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 2f3127c8e..dbd9d6407 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -96,10 +96,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); - connect(m_ui->tileSetLV->selectionModel(), - SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), - this, SLOT(changeActiveTileSet(const QModelIndex &, const QModelIndex &))); - // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->addAction(m_ui->actionAddTile); @@ -427,6 +423,9 @@ void TileEditorMainWindow::onLandRowChanged( int row ) { if( row == -1 ) { + disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + m_ui->tileSetLV->setModel( NULL ); m_ui->listView128->setModel( NULL ); m_ui->listView256->setModel( NULL ); @@ -435,11 +434,17 @@ void TileEditorMainWindow::onLandRowChanged( int row ) } else { + //disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + // this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + m_ui->tileSetLV->setModel( m_tileModels[ row ] ); m_ui->listView128->setModel( m_tileModels[ row ] ); m_ui->listView256->setModel( m_tileModels[ row ] ); m_ui->listViewTransition->setModel( m_tileModels[ row ] ); m_ui->listViewDisplacement->setModel( m_tileModels[ row ] ); + + connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); } m_ui->tileSetLV->reset(); From 7b13b09e018da2035a3e1e26b4c4822347fdf8a7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:44:00 +0200 Subject: [PATCH 149/220] When selecting another land, select the first tile set, if it exists. --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index dbd9d6407..5e3127d51 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -445,6 +445,12 @@ void TileEditorMainWindow::onLandRowChanged( int row ) connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + + if( m_ui->tileSetLV->model()->rowCount() != 0 ) + { + QModelIndex idx = m_ui->tileSetLV->model()->index( 0, 0 ); + m_ui->tileSetLV->setCurrentIndex( idx ); + } } m_ui->tileSetLV->reset(); From a14a16f9358b8a93ba93f9be1d4d3afef4a6a06f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 23:31:37 +0200 Subject: [PATCH 150/220] Implemented choosing / resetting vegetset for tile sets. --- .../tile_editor/tile_editor_main_window.cpp | 68 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 3 + .../tile_editor/tile_editor_main_window.ui | 4 +- .../src/plugins/tile_editor/tile_item.h | 4 ++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 5e3127d51..40b3b8dfc 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -96,6 +96,9 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); + connect(m_ui->chooseVegetPushButton, SIGNAL(clicked()), this, SLOT(onChooseVegetation())); + connect(m_ui->resetVegetPushButton, SIGNAL(clicked()), this, SLOT(onResetVegetation())); + // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->addAction(m_ui->actionAddTile); @@ -421,6 +424,8 @@ void TileEditorMainWindow::onLandEdit() void TileEditorMainWindow::onLandRowChanged( int row ) { + m_ui->chooseVegetPushButton->setText( "..." ); + if( row == -1 ) { disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), @@ -456,6 +461,47 @@ void TileEditorMainWindow::onLandRowChanged( int row ) m_ui->tileSetLV->reset(); } +void TileEditorMainWindow::onChooseVegetation() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr("Choosing a vegetation set"), + tr("You need to select a tileset before choosing a vegetation set!") ); + return; + } + + QString vegetSet = QFileDialog::getOpenFileName( this, + tr( "Choose vegetation set" ), + "", + tr( "Nel vegetset files (*.vegetset)" ) ); + + if( vegetSet.isEmpty() ) + return; + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + node->setVegetSet( vegetSet ); + + m_ui->chooseVegetPushButton->setText( vegetSet ); +} + +void TileEditorMainWindow::onResetVegetation() +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr("Resetting a vegetation set"), + tr("You need to select a tileset before resetting a vegetation set!") ); + return; + } + m_ui->chooseVegetPushButton->setText( "..." ); + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + node->setVegetSet( "" ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; @@ -493,6 +539,28 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->listViewDisplacement->setRootIndex(tileDispIdx); m_ui->listViewDisplacement->setCurrentIndex(m_ui->listViewDisplacement->model()->index(0, 0, m_ui->listViewDisplacement->rootIndex())); + TileSetNode *oldNode = NULL; + TileSetNode *newNode = NULL; + + if( oldIndex.isValid() ) + oldNode = reinterpret_cast< TileSetNode* >( oldIndex.internalPointer() ); + if( newIndex.isValid() ) + newNode = reinterpret_cast< TileSetNode* >( newIndex.internalPointer() ); + + if( newNode != NULL ) + { + QString vegetSet = newNode->vegetSet(); + + if( !vegetSet.isEmpty() ) + m_ui->chooseVegetPushButton->setText( vegetSet ); + else + m_ui->chooseVegetPushButton->setText( "..." ); + } + else + { + m_ui->chooseVegetPushButton->setText( "..." ); + } + //nlinfo("number of rows in displacement: %d", tileDispIdx.model()->rowCount(tileDispIdx)); //m_ui->listView128->reset(); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 58f546ea9..de7f1d0d0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -59,6 +59,9 @@ public Q_SLOTS: void onLandEdit(); void onLandRowChanged( int row ); + void onResetVegetation(); + void onChooseVegetation(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 07fbf08aa..387d0f23e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -18,7 +18,7 @@ - 2 + 4 @@ -306,7 +306,7 @@ - + Reset diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 56adfa926..e99effc62 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -72,8 +72,12 @@ public: const QString &getTileSetName(){ return m_tileSetName; } void setTileSetName( const QString &name ){ m_tileSetName = name; } + void setVegetSet( const QString &s ){ m_vegetSet = s; } + QString vegetSet() const{ return m_vegetSet; } + private: QString m_tileSetName; + QString m_vegetSet; }; class TileTypeNode : public Node From 41f8104f19de02e5b81df9e62707de58b0160f82 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 23:41:42 +0200 Subject: [PATCH 151/220] Implemented tilebank texture path setting. --- .../tile_editor/tile_editor_main_window.cpp | 23 +++++++++++++++ .../tile_editor/tile_editor_main_window.h | 4 +++ .../tile_editor/tile_editor_main_window.ui | 29 +++++++------------ 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 40b3b8dfc..7b255ce2d 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -99,6 +99,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->chooseVegetPushButton, SIGNAL(clicked()), this, SLOT(onChooseVegetation())); connect(m_ui->resetVegetPushButton, SIGNAL(clicked()), this, SLOT(onResetVegetation())); + connect(m_ui->tileBankTexturePathPB, SIGNAL(clicked()), this, SLOT(onChooseTexturePath())); + // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); m_ui->listView128->addAction(m_ui->actionAddTile); @@ -502,6 +504,27 @@ void TileEditorMainWindow::onResetVegetation() node->setVegetSet( "" ); } +void TileEditorMainWindow::onChooseTexturePath() +{ + QString path = QFileDialog::getExistingDirectory( this, + tr("Choose tilebank absolute texture path "), + "" ); + + if( path.isEmpty() ) + return; + + int reply = QMessageBox::question( this, + tr("tilebank texture path"), + tr("Are you sure you want to make '%1' the tilebank absolute texture path?").arg( path ), + QMessageBox::Yes | QMessageBox::Cancel ); + + if( reply != QMessageBox::Yes ) + return; + + m_texturePath = path; + m_ui->tileBankTexturePathPB->setText( path ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QFileDialog::Options options; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index de7f1d0d0..a66d6d993 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -62,6 +62,8 @@ public Q_SLOTS: void onResetVegetation(); void onChooseVegetation(); + void onChooseTexturePath(); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); @@ -84,6 +86,8 @@ private: TileItemDelegate *m_tileItemDelegate; QList< TileModel* > m_tileModels; + + QString m_texturePath; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 387d0f23e..4297b4848 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -541,24 +541,6 @@ - - - - - - ... - - - - - - - ... - - - - - @@ -569,6 +551,17 @@ + + + + + + ... + + + + + From a1b87377768742b695e66a737e47bb368f105565 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 00:29:37 +0200 Subject: [PATCH 152/220] Implemented Tile addition. --- .../tile_editor/tile_editor_main_window.cpp | 54 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 12 ++++- .../src/plugins/tile_editor/tile_model.cpp | 5 ++ .../src/plugins/tile_editor/tile_model.h | 1 + 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 7b255ce2d..1ad0e8a45 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -527,9 +527,63 @@ void TileEditorMainWindow::onChooseTexturePath() void TileEditorMainWindow::onActionAddTile(int tabId) { + int land = m_ui->landLW->currentRow(); + if( land == -1 ) + { + QMessageBox::information( this, + tr( "Adding new tile" ), + tr( "You need to have a land and a tileset selected before you can add tiles!" ) ); + return; + } + + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Adding new tiles" ), + tr( "You need to have a tileset selected before you can add tiles!" ) ); + return; + } + + int tileSet = idx.row(); + + TileModel *model = static_cast< TileModel* >( m_tileModels[ land ] ); + idx = model->index( tileSet, 0 ); + if( !idx.isValid() ) + return; + + TileSetNode *tsn = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + + int tabIdx = m_ui->tileViewTabWidget->currentIndex(); + Node *n = tsn->child( tabIdx ); + QFileDialog::Options options; QString selectedFilter; QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); + + int c = n->childCount(); + + QStringListIterator itr( fileNames ); + while( itr.hasNext() ) + { + Node *newNode = TileModel::createItemNode( c, TileModel::TileDiffuse, itr.next() ); + n->appendRow( newNode ); + c++; + } + + QModelIndex rootIdx = model->index( tabIdx, 0, m_ui->tileSetLV->currentIndex()); + + QListView *lv = NULL; + + switch( tabIdx ) + { + case TAB_128: lv = m_ui->listView128; break; + case TAB_256: lv = m_ui->listView256; break; + } + + lv->reset(); + lv->setRootIndex( rootIdx ); + lv->setCurrentIndex( lv->model()->index( 0, 0, rootIdx ) ); } TileModel* TileEditorMainWindow::createTileModel() diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index a66d6d993..9dff9fc3e 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -42,7 +42,7 @@ public: QUndoStack *getUndoStack() { return m_undoStack; } -public Q_SLOTS: +private Q_SLOTS: void onActionAddTile(bool triggered); void onActionDeleteTile(bool triggered); void onActionReplaceImage(bool triggered); @@ -69,7 +69,6 @@ public Q_SLOTS: private: void onActionAddTile(int tabId); - TileModel* createTileModel(); Ui::TileEditorMainWindow *m_ui; @@ -88,6 +87,15 @@ private: QList< TileModel* > m_tileModels; QString m_texturePath; + + enum Tabs + { + TAB_128 = 0, + TAB_256 = 1, + TAB_TRANSITION = 2, + TAB_DISPLACEMENT = 3, + TAB_DETAILS = 4 + }; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 4b6d2113d..d7ead6ac3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -203,6 +203,11 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) return tileSet; } +Node *TileModel::createItemNode( int id, TTileChannel channel, const QString &fileName ) +{ + return new TileItemNode( id, channel, fileName ); +} + const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) { switch(type) diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index e2be8da57..56d7b792b 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -84,6 +84,7 @@ public: void swapRows( int a, int b ); TileSetNode *createTileSetNode(QString tileSetName); + static Node *createItemNode( int id, TTileChannel channel, const QString &fileName ); static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); From 4d0002a6f4cd1d702d93d277c5f748bae9f55871 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 00:32:42 +0200 Subject: [PATCH 153/220] I must be blind... --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 1ad0e8a45..a0397fbda 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -554,8 +554,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) TileSetNode *tsn = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - int tabIdx = m_ui->tileViewTabWidget->currentIndex(); - Node *n = tsn->child( tabIdx ); + Node *n = tsn->child( tabId ); QFileDialog::Options options; QString selectedFilter; @@ -571,11 +570,11 @@ void TileEditorMainWindow::onActionAddTile(int tabId) c++; } - QModelIndex rootIdx = model->index( tabIdx, 0, m_ui->tileSetLV->currentIndex()); + QModelIndex rootIdx = model->index( tabId, 0, m_ui->tileSetLV->currentIndex()); QListView *lv = NULL; - switch( tabIdx ) + switch( tabId ) { case TAB_128: lv = m_ui->listView128; break; case TAB_256: lv = m_ui->listView256; break; From fc4856f28c0e4fbbee7c88aca700b641dbd92cd0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 01:57:50 +0200 Subject: [PATCH 154/220] Implemented tile deletion. --- .../tile_editor/tile_editor_main_window.cpp | 27 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + .../src/plugins/tile_editor/tile_item.h | 2 +- .../src/plugins/tile_editor/tile_model.cpp | 16 ++++++++--- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a0397fbda..25406e389 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -215,6 +215,7 @@ void TileEditorMainWindow::onActionAddTile(bool triggered) void TileEditorMainWindow::onActionDeleteTile(bool triggered) { + onActionDeleteTile(m_ui->tileViewTabWidget->currentIndex()); } void TileEditorMainWindow::onActionReplaceImage(bool triggered) @@ -585,6 +586,32 @@ void TileEditorMainWindow::onActionAddTile(int tabId) lv->setCurrentIndex( lv->model()->index( 0, 0, rootIdx ) ); } +void TileEditorMainWindow::onActionDeleteTile( int tabId ) +{ + QListView *lv = NULL; + switch( tabId ) + { + case TAB_128: lv = m_ui->listView128; break; + case TAB_256: lv = m_ui->listView256; break; + } + + QModelIndex idx = lv->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Deleting a tile" ), + tr( "You need to select a tile to delete is!" ) ); + return; + } + + int row = idx.row(); + + QModelIndex parent = idx.parent(); + lv->model()->removeRow( row, parent ); + + //lv->reset(); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 9dff9fc3e..f839e7c32 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -69,6 +69,7 @@ private Q_SLOTS: private: void onActionAddTile(int tabId); + void onActionDeleteTile(int tabId); TileModel* createTileModel(); Ui::TileEditorMainWindow *m_ui; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index e99effc62..5331ef081 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -43,7 +43,7 @@ public: virtual QVariant data(int column, int role) const; bool insertChildren(int position, int count, int columns); - bool removeChildren(int position, int count); + virtual bool removeChildren(int position, int count); bool insertColumns(int position, int columns); int row() const; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d7ead6ac3..d68650b8f 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -142,13 +142,23 @@ void TileModel::appendRow(Node *item) bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) { - int c = rootItem->childCount(); + Node *parentNode = NULL; + + if( !parent.isValid() ) + parentNode = rootItem; + else + parentNode = getItem( parent ); + + if( parentNode == NULL ) + return false; + + int c = parentNode->childCount(); if( row + count > c ) return false; - beginRemoveRows( QModelIndex(), row, row + count - 1 ); + beginRemoveRows( parent, row, row + count - 1 ); - bool ok = rootItem->removeChildren( row, count ); + bool ok = parentNode->removeChildren( row, count ); endRemoveRows(); From fe044b85927bbf2e83962db8a96398bade63ba6d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:05:21 +0200 Subject: [PATCH 155/220] Reindex tile item nodes after deleting a node. --- .../src/plugins/tile_editor/tile_item.cpp | 26 +++++++++++++++++++ .../src/plugins/tile_editor/tile_item.h | 6 +++++ 2 files changed, 32 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 230776fbd..e228a6745 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -224,7 +224,33 @@ TileModel::TNodeTileType TileTypeNode::getTileType() return m_nodeTileType; } +bool TileTypeNode::removeChildren( int position, int count ) +{ + bool ok = Node::removeChildren( position, count ); + if( !ok ) + return false; + reindex(); + + return true; +} + +void TileTypeNode::reindex() +{ + int i = 0; + + QListIterator< Node* > itr( m_childItems ); + while( itr.hasNext() ) + { + TileItemNode *n = dynamic_cast< TileItemNode* >( itr.next() ); + if( n == NULL ) + continue; + + n->setId( i ); + + i++; + } +} /////////////////////////////////////////////////// diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 5331ef081..f232acb4b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -90,7 +90,11 @@ public: int columnCount() const; TileModel::TNodeTileType getTileType(); + + bool removeChildren( int position, int count ); + private: + void reindex(); TileModel::TNodeTileType m_nodeTileType; }; @@ -102,6 +106,8 @@ public: QVariant data(int column, int role) const; int columnCount() const; void setTileFilename(TileModel::TTileChannel channel, QString filename); + void setId( int id ){ m_tileId = id; } + int id() const{ return m_tileId; } private: int m_tileId; QMap m_tileFilename; From 39bde4b2575350acc117b2033946f05a6fb55fac Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:11:02 +0200 Subject: [PATCH 156/220] A little refactoring. --- .../tile_editor/tile_editor_main_window.cpp | 33 +++++++++++-------- .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 25406e389..4884ea42b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -573,13 +573,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QModelIndex rootIdx = model->index( tabId, 0, m_ui->tileSetLV->currentIndex()); - QListView *lv = NULL; - - switch( tabId ) - { - case TAB_128: lv = m_ui->listView128; break; - case TAB_256: lv = m_ui->listView256; break; - } + QListView *lv = getListViewByTab( tabId ); lv->reset(); lv->setRootIndex( rootIdx ); @@ -588,12 +582,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) void TileEditorMainWindow::onActionDeleteTile( int tabId ) { - QListView *lv = NULL; - switch( tabId ) - { - case TAB_128: lv = m_ui->listView128; break; - case TAB_256: lv = m_ui->listView256; break; - } + QListView *lv = getListViewByTab( tabId ); QModelIndex idx = lv->currentIndex(); if( !idx.isValid() ) @@ -671,3 +660,21 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons //m_ui->listViewTransition->reset(); //m_ui->listViewDisplacement->reset(); } + + +QListView* TileEditorMainWindow::getListViewByTab( int tab ) const +{ + QListView *lv = NULL; + + switch( tab ) + { + case TAB_128: lv = m_ui->listView128; break; + case TAB_256: lv = m_ui->listView256; break; + case TAB_TRANSITION: lv = m_ui->listViewTransition; break; + case TAB_DISPLACEMENT: lv = m_ui->listViewDisplacement; break; + } + + return lv; +} + + diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index f839e7c32..2eae0b89f 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -71,6 +71,7 @@ private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); TileModel* createTileModel(); + QListView* getListViewByTab( int tab ) const; Ui::TileEditorMainWindow *m_ui; QUndoStack *m_undoStack; From 2f6faf05c1f9ec00362ad33e5fc850e74415dcc8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:19:13 +0200 Subject: [PATCH 157/220] Implemented tile image deletion. --- .../tile_editor/tile_editor_main_window.cpp | 20 ++++++++++++++++++- .../tile_editor/tile_editor_main_window.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 4884ea42b..a941de6d7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -130,7 +130,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionAddTile, SIGNAL(triggered(bool)), this, SLOT(onActionAddTile(bool))); connect(m_ui->actionDeleteTile, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteTile(bool))); connect(m_ui->actionReplaceImage, SIGNAL(triggered(bool)), this, SLOT(onActionReplaceImage(bool))); - connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActioneleteImage(bool))); + connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteImage(bool))); //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); @@ -224,6 +224,7 @@ void TileEditorMainWindow::onActionReplaceImage(bool triggered) void TileEditorMainWindow::onActionDeleteImage(bool triggered) { + onActionDeleteImage(m_ui->tileViewTabWidget->currentIndex()); } void TileEditorMainWindow::onTileSetAdd() @@ -601,6 +602,23 @@ void TileEditorMainWindow::onActionDeleteTile( int tabId ) //lv->reset(); } +void TileEditorMainWindow::onActionDeleteImage( int tabId ) +{ + QListView *lv = getListViewByTab( tabId ); + + QModelIndex idx = lv->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Deleting tile image" ), + tr( "No tile selected!" ) ); + return; + } + + TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); + n->setTileFilename( TileModel::TileDiffuse, "" ); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 2eae0b89f..117315c25 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -70,6 +70,9 @@ private Q_SLOTS: private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); + void onActionDeleteImage(int tabId); + + TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; From aef9f58242101a9d7da181b767d123c9494ec973 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:24:32 +0200 Subject: [PATCH 158/220] Implemented tile image replace. --- .../tile_editor/tile_editor_main_window.cpp | 25 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 26 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a941de6d7..e272faeee 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -220,6 +220,7 @@ void TileEditorMainWindow::onActionDeleteTile(bool triggered) void TileEditorMainWindow::onActionReplaceImage(bool triggered) { + onActionReplaceImage(m_ui->tileViewTabWidget->currentIndex()); } void TileEditorMainWindow::onActionDeleteImage(bool triggered) @@ -619,6 +620,30 @@ void TileEditorMainWindow::onActionDeleteImage( int tabId ) n->setTileFilename( TileModel::TileDiffuse, "" ); } +void TileEditorMainWindow::onActionReplaceImage( int tabId ) +{ + QListView *lv = getListViewByTab( tabId ); + + QModelIndex idx = lv->currentIndex(); + if( !idx.isValid() ) + { + QMessageBox::information( this, + tr( "Replacing tile image" ), + tr( "No tile selected!" ) ); + return; + } + + QString fileName = QFileDialog::getOpenFileName( this, + tr( "Select tile image" ), + "", + tr( "PNG files (*.png)" ) ); + if( fileName.isEmpty() ) + return; + + TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); + n->setTileFilename( TileModel::TileDiffuse, fileName ); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 117315c25..14cb7cf75 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -71,6 +71,7 @@ private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); void onActionDeleteImage(int tabId); + void onActionReplaceImage(int tabId); TileModel* createTileModel(); From 2f9b4f1b5eb66944d0f12efbad71ceb2750a840e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 27 Jul 2014 18:23:25 +0200 Subject: [PATCH 159/220] 128x128 tab should be shown by default. --- code/studio/src/plugins/tile_editor/tile_editor_main_window.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 4297b4848..2e936aa8b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -18,7 +18,7 @@ - 4 + 0 From d3698a5c1aed82c90403ce77d9a17b485d40ae75 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 27 Jul 2014 20:38:08 +0200 Subject: [PATCH 160/220] Implemented the GUI part of saving... --- .../tile_editor/tile_editor_main_window.cpp | 49 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 6 +++ .../plugins/tile_editor/tile_editor_plugin.h | 10 ++++ .../plugins/tile_editor/tilebank_saver.cpp | 37 ++++++++++++++ .../src/plugins/tile_editor/tilebank_saver.h | 38 ++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 code/studio/src/plugins/tile_editor/tilebank_saver.cpp create mode 100644 code/studio/src/plugins/tile_editor/tilebank_saver.h diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index e272faeee..75d2c31f4 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -32,6 +32,8 @@ #include "tile_item.h" #include "tile_item_delegate.h" +#include "tilebank_saver.h" + TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::TileEditorMainWindow) @@ -142,6 +144,14 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionZoom200, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); m_zoomSignalMapper->setMapping(m_ui->actionZoom200, 2); connect(m_zoomSignalMapper, SIGNAL(mapped(int)), this, SLOT(onZoomFactor(int))); + + QAction *saveAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE ); + saveAction->setEnabled( true ); + QAction *saveAsAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE_AS ); + saveAsAction->setEnabled( true ); + + connect( m_ui->actionSaveTileBank, SIGNAL( triggered() ), this, SLOT( save() ) ); + connect( m_ui->actionSaveTileBankAs, SIGNAL( triggered() ), this, SLOT( saveAs() ) ); } TileEditorMainWindow::~TileEditorMainWindow() @@ -161,6 +171,45 @@ TileEditorMainWindow::~TileEditorMainWindow() m_tileModels.clear(); } +void TileEditorMainWindow::save() +{ + saveAs(); +} + +void TileEditorMainWindow::saveAs() +{ + if( m_fileName.isEmpty() ) + { + m_fileName = QFileDialog::getSaveFileName( this, + tr( "Save TileBank as..." ), + "", + tr( "TileBank files (*.tilebank)" ) ); + + if( m_fileName.isEmpty() ) + return; + + } + + QList< QString > landNames; + + int c = m_ui->landLW->count(); + for( int i = 0; i < c; i++ ) + { + QListWidgetItem *item = m_ui->landLW->item( i ); + landNames.push_back( item->text() ); + } + + TileBankSaver saver; + bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModels, landNames ); + + if( !ok ) + { + QMessageBox::critical( this, + tr( "Saving tilebank" ), + tr( "Failed to save tilebank :(" ) ); + } +} + void TileEditorMainWindow::onZoomFactor(int level) { int tile128Scaled=TileModel::TILE_128_BASE_SIZE; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 14cb7cf75..c1fb662b0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -42,6 +42,10 @@ public: QUndoStack *getUndoStack() { return m_undoStack; } +public Q_SLOTS: + void save(); + void saveAs(); + private Q_SLOTS: void onActionAddTile(bool triggered); void onActionDeleteTile(bool triggered); @@ -102,6 +106,8 @@ private: TAB_DISPLACEMENT = 3, TAB_DETAILS = 4 }; + + QString m_fileName; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h index cb7be7fc1..024e6a6e2 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h @@ -95,6 +95,16 @@ public: { } + void save() + { + m_tileEditorMainWindow->save(); + } + + void saveAs() + { + m_tileEditorMainWindow->saveAs(); + } + virtual QWidget *widget() { return m_tileEditorMainWindow; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp new file mode 100644 index 000000000..d149648ff --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -0,0 +1,37 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "tilebank_saver.h" +#include "tile_model.h" + +#include "nel/3d/tile_bank.h" + +TileBankSaver::TileBankSaver() +{ +} + +TileBankSaver::~TileBankSaver() +{ +} + +bool TileBankSaver::save( const char *fileName, const QList< TileModel* > &models, const QList< QString > &lands ) +{ + NL3D::CTileBank bank; + + return false; +} + diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h new file mode 100644 index 000000000..80fb119d8 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -0,0 +1,38 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef TILEBANK_SAVER_H +#define TILEBANK_SAVER_H + +#include +#include + +class TileModel; + +class TileBankSaver +{ +public: + TileBankSaver(); + ~TileBankSaver(); + + bool save( const char *filename, const QList< TileModel* > &models, const QList< QString > &lands ); + +private: +}; + +#endif + From fed92a47d36e7f5749d71c23d02b0bb27f8a7390 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 28 Jul 2014 17:05:51 +0200 Subject: [PATCH 161/220] As it turns out, tilesets can be assigned to multiple lands... --- .../src/plugins/tile_editor/CMakeLists.txt | 6 +- .../plugins/tile_editor/land_edit_dialog.cpp | 77 +++++++++ .../plugins/tile_editor/land_edit_dialog.h | 32 ++++ .../plugins/tile_editor/land_edit_dialog.ui | 99 +++++++++++ .../tile_editor/tile_editor_main_window.cpp | 157 +++++++++--------- .../tile_editor/tile_editor_main_window.h | 12 +- .../plugins/tile_editor/tilebank_saver.cpp | 2 +- .../src/plugins/tile_editor/tilebank_saver.h | 2 +- 8 files changed, 299 insertions(+), 88 deletions(-) create mode 100644 code/studio/src/plugins/tile_editor/land_edit_dialog.cpp create mode 100644 code/studio/src/plugins/tile_editor/land_edit_dialog.h create mode 100644 code/studio/src/plugins/tile_editor/land_edit_dialog.ui diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index d546beba1..396522235 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -11,10 +11,12 @@ SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin. SET(OVQT_TILE_EDITOR_PLUGIN_HDR tile_model.h tile_editor_main_window.h - tile_editor_plugin.h) + tile_editor_plugin.h + land_edit_dialog.h) SET(OVQT_TILE_EDITOR_PLUGIN_UIS - tile_editor_main_window.ui) + tile_editor_main_window.ui + land_edit_dialog.ui) SET(OVQT_PLUG_TILE_EDITOR_RCS tile_editor.qrc) diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp new file mode 100644 index 000000000..f7f5c5ce6 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -0,0 +1,77 @@ +#include "land_edit_dialog.h" + +LandEditDialog::LandEditDialog( QWidget *parent ) : +QDialog( parent ) +{ + setupUi( this ); + setupConnections(); +} + +LandEditDialog::~LandEditDialog() +{ +} + +void LandEditDialog::getSelectedTileSets( QStringList &l ) const +{ + int c = tilesetLV->count(); + for( int i = 0; i < c; i++ ) + { + l.push_back( tilesetLV->item( i )->text() ); + } +} + +void LandEditDialog::setTileSets( const QStringList &l ) +{ + tilesetCB->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + tilesetCB->addItem( itr.next() ); + } +} + +void LandEditDialog::setupConnections() +{ + connect( okButton, SIGNAL( clicked( bool ) ), this, SLOT( onOkClicked() ) ); + connect( cancelButton, SIGNAL( clicked( bool ) ), this, SLOT( onCancelClicked() ) ); + connect( addButton, SIGNAL( clicked( bool ) ), this, SLOT( onAddClicked() ) ); + connect( removeButton, SIGNAL( clicked( bool ) ), this, SLOT( onRemoveClicked() ) ); +} + +void LandEditDialog::onOkClicked() +{ + accept(); +} + +void LandEditDialog::onCancelClicked() +{ + reject(); +} + +void LandEditDialog::onAddClicked() +{ + if( tilesetCB->currentIndex() < 0 ) + return; + + QString text = tilesetCB->currentText(); + + int c = tilesetLV->count(); + for( int i = 0; i < c; i++ ) + { + if( text == tilesetLV->item( i )->text() ) + return; + } + + tilesetLV->addItem( text ); +} + +void LandEditDialog::onRemoveClicked() +{ + if( tilesetLV->currentItem() == NULL ) + return; + + QListWidgetItem *item = tilesetLV->currentItem(); + delete item; +} + diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.h b/code/studio/src/plugins/tile_editor/land_edit_dialog.h new file mode 100644 index 000000000..9b86a2d06 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -0,0 +1,32 @@ +#ifndef LAND_EDIT_DLG_H +#define LAND_EDIT_DLG_H + + +#include "ui_land_edit_dialog.h" +#include + +class LandEditDialog : public QDialog, public Ui::LandEditDialog +{ + Q_OBJECT +public: + LandEditDialog( QWidget *parent = NULL ); + ~LandEditDialog(); + + void getSelectedTileSets( QStringList &l ) const; + void setTileSets( const QStringList &l ); + +private: + void setupConnections(); + + +private Q_SLOTS: + void onOkClicked(); + void onCancelClicked(); + void onAddClicked(); + void onRemoveClicked(); + +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.ui b/code/studio/src/plugins/tile_editor/land_edit_dialog.ui new file mode 100644 index 000000000..7eb707528 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.ui @@ -0,0 +1,99 @@ + + + LandEditDialog + + + Qt::WindowModal + + + + 0 + 0 + 402 + 311 + + + + Editing land + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Add + + + + + + + + 0 + 0 + + + + Remove + + + + + + + + 0 + 0 + + + + OK + + + + + + + + 0 + 0 + + + + Cancel + + + + + + + + + + diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 75d2c31f4..0a30da403 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -34,6 +34,8 @@ #include "tilebank_saver.h" +#include "land_edit_dialog.h" + TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::TileEditorMainWindow) @@ -96,15 +98,18 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); connect(m_ui->landEditTB, SIGNAL(clicked()), this, SLOT(onLandEdit())); - connect(m_ui->landLW, SIGNAL(currentRowChanged(int)), this, SLOT(onLandRowChanged(int))); connect(m_ui->chooseVegetPushButton, SIGNAL(clicked()), this, SLOT(onChooseVegetation())); connect(m_ui->resetVegetPushButton, SIGNAL(clicked()), this, SLOT(onResetVegetation())); connect(m_ui->tileBankTexturePathPB, SIGNAL(clicked()), this, SLOT(onChooseTexturePath())); + m_tileModel = createTileModel(); + m_ui->tileSetLV->setModel( m_tileModel ); + // 128x128 List View //m_ui->listView128->setItemDelegate(m_tileItemDelegate); + m_ui->listView128->setModel( m_tileModel ); m_ui->listView128->addAction(m_ui->actionAddTile); m_ui->listView128->addAction(m_ui->actionDeleteTile); m_ui->listView128->addAction(m_ui->actionReplaceImage); @@ -112,6 +117,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // 256x256 List View //m_ui->listView256->setItemDelegate(m_tileItemDelegate); + m_ui->listView256->setModel( m_tileModel ); m_ui->listView256->addAction(m_ui->actionAddTile); m_ui->listView256->addAction(m_ui->actionDeleteTile); m_ui->listView256->addAction(m_ui->actionReplaceImage); @@ -119,11 +125,13 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) // Transition List View //m_ui->listViewTransition->setItemDelegate(m_tileItemDelegate); + m_ui->listViewTransition->setModel( m_tileModel ); m_ui->listViewTransition->addAction(m_ui->actionReplaceImage); m_ui->listViewTransition->addAction(m_ui->actionDeleteImage); // Displacement List View //m_ui->listViewDisplacement->setItemDelegate(m_tileItemDelegate); + m_ui->listViewDisplacement->setModel( m_tileModel ); m_ui->listViewDisplacement->addAction(m_ui->actionReplaceImage); m_ui->listViewDisplacement->addAction(m_ui->actionDeleteImage); @@ -135,6 +143,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->actionDeleteImage, SIGNAL(triggered(bool)), this, SLOT(onActionDeleteImage(bool))); //connect(m_ui->tileViewTabWidget, SIGNAL(currentChanged(int)), m_tileItemDelegate, SLOT(currentTab(int))); + connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), + this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); // Connect the zoom buttons. connect(m_ui->actionZoom50, SIGNAL(triggered()), m_zoomSignalMapper, SLOT(map())); @@ -167,8 +177,8 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_zoomActionGroup; delete m_zoomSignalMapper; - qDeleteAll( m_tileModels ); - m_tileModels.clear(); + delete m_tileModel; + m_tileModel = NULL; } void TileEditorMainWindow::save() @@ -200,7 +210,7 @@ void TileEditorMainWindow::saveAs() } TileBankSaver saver; - bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModels, landNames ); + bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, landNames ); if( !ok ) { @@ -279,14 +289,6 @@ void TileEditorMainWindow::onActionDeleteImage(bool triggered) void TileEditorMainWindow::onTileSetAdd() { - if( m_ui->landLW->count() == 0 ) - { - QMessageBox::information( this, - tr( "Error adding tile set" ), - tr( "You need to add a land before adding a tileset!" ) ); - return; - } - bool ok; QString text = QInputDialog::getText(this, tr("Add Tile Set"), tr("Enter Tile Set name:"), QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) @@ -323,8 +325,12 @@ void TileEditorMainWindow::onTileSetDelete() if( reply != QMessageBox::Yes ) return; + QString set = reinterpret_cast< TileSetNode* >( idx.internalPointer() )->getTileSetName(); + TileModel *model = static_cast(m_ui->tileSetLV->model()); bool ok = model->removeRow( idx.row() ); + + onTileSetRemoved( set ); } void TileEditorMainWindow::onTileSetEdit() @@ -357,8 +363,11 @@ void TileEditorMainWindow::onTileSetEdit() return; } + QString oldName = node->getTileSetName(); node->setTileSetName( newName ); m_ui->tileSetLV->reset(); + + onTileSetRenamed( oldName, newName ); } void TileEditorMainWindow::onTileSetUp() @@ -422,13 +431,10 @@ void TileEditorMainWindow::onLandAdd() } m_ui->landLW->addItem( name ); - - TileModel *m = createTileModel(); - - m_tileModels.push_back( m ); - - if( m_tileModels.count() == 1 ) - m_ui->landLW->setCurrentRow( 0 ); + + Land l; + l.name = name; + m_lands.push_back( l ); } void TileEditorMainWindow::onLandRemove() @@ -447,12 +453,10 @@ void TileEditorMainWindow::onLandRemove() if( reply != QMessageBox::Yes ) return; - QList< TileModel* >::iterator itr = m_tileModels.begin() + idx; - delete m_tileModels[ idx ]; - m_tileModels[ idx ] = NULL; - m_tileModels.erase( itr ); - delete item; + + QList< Land >::iterator itr = m_lands.begin() + idx; + m_lands.erase( itr ); } void TileEditorMainWindow::onLandEdit() @@ -461,58 +465,33 @@ void TileEditorMainWindow::onLandEdit() if( item == NULL ) return; - QString name = item->text(); - - QString newName = QInputDialog::getText( this, - tr( "Editing land" ), - tr( "Please specify the new name of the selected land" ), - QLineEdit::Normal, - name ); - - if( newName.isEmpty() ) - return; - if( newName == name ) - return; - item->setText( newName ); -} - -void TileEditorMainWindow::onLandRowChanged( int row ) -{ - m_ui->chooseVegetPushButton->setText( "..." ); - - if( row == -1 ) + QStringList ts; + int c = m_tileModel->rowCount(); + for( int i = 0; i < c; i++ ) { - disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), - this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + QModelIndex idx = m_tileModel->index( i, 0 ); + if( !idx.isValid() ) + continue; - m_ui->tileSetLV->setModel( NULL ); - m_ui->listView128->setModel( NULL ); - m_ui->listView256->setModel( NULL ); - m_ui->listViewTransition->setModel( NULL ); - m_ui->listViewDisplacement->setModel( NULL ); + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + ts.push_back( n->getTileSetName() ); } - else - { - //disconnect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), - // this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + + int r = m_ui->landLW->currentRow(); + Land &l = m_lands[ r ]; - m_ui->tileSetLV->setModel( m_tileModels[ row ] ); - m_ui->listView128->setModel( m_tileModels[ row ] ); - m_ui->listView256->setModel( m_tileModels[ row ] ); - m_ui->listViewTransition->setModel( m_tileModels[ row ] ); - m_ui->listViewDisplacement->setModel( m_tileModels[ row ] ); + LandEditDialog d; + d.setTileSets( ts ); + int result = d.exec(); - connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), - this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + if( result != QDialog::Accepted ) + return; - if( m_ui->tileSetLV->model()->rowCount() != 0 ) - { - QModelIndex idx = m_ui->tileSetLV->model()->index( 0, 0 ); - m_ui->tileSetLV->setCurrentIndex( idx ); - } - } - - m_ui->tileSetLV->reset(); + // Update the tileset of the land + ts.clear(); + d.getSelectedTileSets( ts ); + l.tilesets.clear(); + l.tilesets = ts; } void TileEditorMainWindow::onChooseVegetation() @@ -579,15 +558,6 @@ void TileEditorMainWindow::onChooseTexturePath() void TileEditorMainWindow::onActionAddTile(int tabId) { - int land = m_ui->landLW->currentRow(); - if( land == -1 ) - { - QMessageBox::information( this, - tr( "Adding new tile" ), - tr( "You need to have a land and a tileset selected before you can add tiles!" ) ); - return; - } - QModelIndex idx = m_ui->tileSetLV->currentIndex(); if( !idx.isValid() ) { @@ -599,8 +569,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) int tileSet = idx.row(); - TileModel *model = static_cast< TileModel* >( m_tileModels[ land ] ); - idx = model->index( tileSet, 0 ); + idx = m_tileModel->index( tileSet, 0 ); if( !idx.isValid() ) return; @@ -622,7 +591,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) c++; } - QModelIndex rootIdx = model->index( tabId, 0, m_ui->tileSetLV->currentIndex()); + QModelIndex rootIdx = m_tileModel->index( tabId, 0, m_ui->tileSetLV->currentIndex()); QListView *lv = getListViewByTab( tabId ); @@ -693,6 +662,30 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) n->setTileFilename( TileModel::TileDiffuse, fileName ); } +void TileEditorMainWindow::onTileSetRemoved( const QString &set ) +{ + int c = m_lands.count(); + for( int i = 0; i < c; i++ ) + { + Land &land = m_lands[ i ]; + land.tilesets.removeAll( set ); + } +} + +void TileEditorMainWindow::onTileSetRenamed( const QString &oldname, const QString &newname ) +{ + int c = m_lands.count(); + for( int i = 0; i < c; i++ ) + { + Land &land = m_lands[ i ]; + int idx = land.tilesets.indexOf( oldname ); + if( idx < 0 ) + continue; + + land.tilesets[ idx ] = newname; + } +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index c1fb662b0..5f015ad6a 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -61,7 +61,6 @@ private Q_SLOTS: void onLandAdd(); void onLandRemove(); void onLandEdit(); - void onLandRowChanged( int row ); void onResetVegetation(); void onChooseVegetation(); @@ -77,6 +76,8 @@ private: void onActionDeleteImage(int tabId); void onActionReplaceImage(int tabId); + void onTileSetRemoved( const QString &set ); + void onTileSetRenamed( const QString &oldname, const QString &newname ); TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; @@ -94,7 +95,7 @@ private: TileItemDelegate *m_tileItemDelegate; - QList< TileModel* > m_tileModels; + TileModel *m_tileModel; QString m_texturePath; @@ -107,7 +108,14 @@ private: TAB_DETAILS = 4 }; + struct Land + { + QString name; + QStringList tilesets; + }; + QString m_fileName; + QList< Land > m_lands; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index d149648ff..db281d161 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -28,7 +28,7 @@ TileBankSaver::~TileBankSaver() { } -bool TileBankSaver::save( const char *fileName, const QList< TileModel* > &models, const QList< QString > &lands ) +bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< QString > &lands ) { NL3D::CTileBank bank; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index 80fb119d8..f86bfab60 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -29,7 +29,7 @@ public: TileBankSaver(); ~TileBankSaver(); - bool save( const char *filename, const QList< TileModel* > &models, const QList< QString > &lands ); + bool save( const char *filename, const TileModel* model, const QList< QString > &lands ); private: }; From a513af355d53654e51c90f6cf10d7c140398dca0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 01:29:17 +0200 Subject: [PATCH 162/220] Implemented saving of the currently stored tilebank data. --- code/studio/src/plugins/tile_editor/land.h | 14 ++ .../tile_editor/tile_editor_main_window.cpp | 2 +- .../tile_editor/tile_editor_main_window.h | 8 +- .../src/plugins/tile_editor/tile_item.cpp | 10 + .../src/plugins/tile_editor/tile_item.h | 1 + .../plugins/tile_editor/tilebank_saver.cpp | 204 +++++++++++++++++- .../src/plugins/tile_editor/tilebank_saver.h | 6 +- 7 files changed, 234 insertions(+), 11 deletions(-) create mode 100644 code/studio/src/plugins/tile_editor/land.h diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h new file mode 100644 index 000000000..37b0d83c6 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/land.h @@ -0,0 +1,14 @@ +#ifndef LAND_H +#define LAND_H + +#include + +struct Land +{ + QString name; + QStringList tilesets; +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 0a30da403..91d81ea50 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -210,7 +210,7 @@ void TileEditorMainWindow::saveAs() } TileBankSaver saver; - bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, landNames ); + bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, m_lands ); if( !ok ) { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 5f015ad6a..a491fc5f2 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -25,6 +25,8 @@ #include #include +#include "land.h" + namespace Ui { class TileEditorMainWindow; } @@ -108,12 +110,6 @@ private: TAB_DETAILS = 4 }; - struct Land - { - QString name; - QStringList tilesets; - }; - QString m_fileName; QList< Land > m_lands; }; diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index e228a6745..b6bb30ea2 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -272,6 +272,16 @@ void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file m_tileFilename[channel] = filename; } +QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) +{ + QMap< TileModel::TTileChannel, QString >::const_iterator itr + = m_tileFilename.find( channel ); + if( itr == m_tileFilename.end() ) + return ""; + + return itr.value(); +} + QVariant TileItemNode::data(int column, int role) const { // find some way to know which file/bitmap to display diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index f232acb4b..b66a2b6f3 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -106,6 +106,7 @@ public: QVariant data(int column, int role) const; int columnCount() const; void setTileFilename(TileModel::TTileChannel channel, QString filename); + QString getTileFilename(TileModel::TTileChannel channel); void setId( int id ){ m_tileId = id; } int id() const{ return m_tileId; } private: diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index db281d161..6bf13fdfe 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -17,21 +17,219 @@ #include "tilebank_saver.h" #include "tile_model.h" +#include "tile_item.h" #include "nel/3d/tile_bank.h" +#include "nel/misc/file.h" + +class TileBankSaverPvt +{ +public: + NL3D::CTileBank bank; + + static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + { + NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; + + switch( channel ) + { + case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileModel::TileAdditive: b = NL3D::CTile::additive; break; + case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + } + + return b; + } + + NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileModel::TNodeTileType type ) + { + int idx = -1; + int bidx = -1; + + switch( type ) + { + case TileModel::Tile128: + { + set->addTile128( idx, bank ); + bidx = set->getTile128( idx ); + break; + } + + case TileModel::Tile256: + { + set->addTile256( idx, bank ); + bidx = set->getTile256( idx ); + break; + } + } + + if( idx == -1 ) + return NULL; + + return bank.getTile( bidx ); + } + + void addTilesToSet( NL3D::CTileSet *set, TileTypeNode *node ) + { + TileModel::TNodeTileType type = node->getTileType(); + + for( int i = 0; i < node->childCount(); i++ ) + { + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + { + QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); + + NL3D::CTile *tile = addTileToSet( set, type ); + tile->setFileName( channelToTBitmap( TileModel::TTileChannel( j ) ) , fn.toUtf8().constData() ); + } + } + } + + void addTilesToSet( NL3D::CTileSet *set, TileSetNode *node ) + { + for( int i = TileModel::Tile128; i <= TileModel::Tile256; i++ ) + { + TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( i ) ); + + addTilesToSet( set, tn ); + } + } + + void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) + { + NL3D::CTileSetTransition *tr = set->getTransition( idx ); + int tid = tr->getTile(); + NL3D::CTile *tile = bank.getTile( tid ); + + if( tile == NULL ) + return; + + for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + { + QString fn = node->getTileFilename( TileModel::TTileChannel( i ) ); + tile->setFileName( channelToTBitmap( TileModel::TTileChannel( i ) ), fn.toUtf8().constData() ); + } + } + + void setupTransitionTiles( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < node->childCount(); i++ ) + { + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + setupTransitionTile( set, tin, i ); + } + } + + void setupTransitionTiles( NL3D::CTileSet *set, TileSetNode *node ) + { + TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 2 ) ); + setupTransitionTiles( set, tn ); + } + + void setupDisplacementTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) + { + set->setDisplacement( NL3D::CTileSet::TDisplacement( idx ), + node->getTileFilename( TileModel::TileDiffuse ).toUtf8().constData(), + bank ); + } + + void setupDisplacementTiles( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < node->childCount(); i++ ) + { + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + setupDisplacementTile( set, tin, i ); + } + } + + void setupDisplacementTiles( NL3D::CTileSet *set, TileSetNode *node ) + { + TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 3 ) ); + setupDisplacementTiles( set, tn ); + } + + void addLands( const QList< Land > &lands ) + { + QListIterator< Land > itr( lands ); + while( itr.hasNext() ) + { + bank.addLand( itr.next().name.toUtf8().constData() ); + } + } + + + void addTileSets( const TileModel* model, const QList< Land > &lands ) + { + // Add the tilesets + for( int i = 0; i < model->rowCount(); i++ ) + { + QModelIndex idx = model->index( i, 0 ); + if( !idx.isValid() ) + continue; + + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + QString set = n->getTileSetName(); + bank.addTileSet( set.toUtf8().constData() ); + } + + // Set the data to tilesets + for( int i = 0; i < bank.getTileSetCount(); i++ ) + { + NL3D::CTileSet *set = bank.getTileSet( i ); + + QModelIndex idx = model->index( i, 0 ); + if( !idx.isValid() ) + continue; + + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + + addTilesToSet( set, n ); + setupTransitionTiles( set, n ); + setupDisplacementTiles( set, n ); + } + + // Add tilesets to lands + for( int i = 0; i < bank.getLandCount(); i++ ) + { + NL3D::CTileLand *land = bank.getLand( i ); + const Land &l = lands[ i ]; + + for( int j = 0; j < l.tilesets.count(); j++ ) + { + land->addTileSet( l.tilesets[ j ].toUtf8().constData() ); + } + } + } +}; TileBankSaver::TileBankSaver() { + p = new TileBankSaverPvt(); } TileBankSaver::~TileBankSaver() { + delete p; + p = NULL; } -bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< QString > &lands ) +bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< Land > &lands ) { - NL3D::CTileBank bank; + p->addLands( lands ); + p->addTileSets( model, lands ); - return false; + // Save to file + NLMISC::COFile f; + bool b = f.open( fileName, false, false, false ); + if( !b ) + return false; + + p->bank.serial( f ); + + f.flush(); + f.close(); + + return true; } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index f86bfab60..2a2806fe1 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -20,18 +20,22 @@ #include #include +#include "land.h" class TileModel; +class TileBankSaverPvt; + class TileBankSaver { public: TileBankSaver(); ~TileBankSaver(); - bool save( const char *filename, const TileModel* model, const QList< QString > &lands ); + bool save( const char *filename, const TileModel* model, const QList< Land > &lands ); private: + TileBankSaverPvt *p; }; #endif From 240844c1cd6c18703a119fb431bcf0627aceccbb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 01:50:01 +0200 Subject: [PATCH 163/220] Connected the oriented combobox and now saving it's value to the tilebank. --- .../tile_editor/tile_editor_main_window.cpp | 16 ++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 2 ++ .../studio/src/plugins/tile_editor/tile_item.cpp | 1 + code/studio/src/plugins/tile_editor/tile_item.h | 4 ++++ .../src/plugins/tile_editor/tilebank_saver.cpp | 2 ++ 5 files changed, 25 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 91d81ea50..a8219f6eb 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -162,6 +162,8 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect( m_ui->actionSaveTileBank, SIGNAL( triggered() ), this, SLOT( save() ) ); connect( m_ui->actionSaveTileBankAs, SIGNAL( triggered() ), this, SLOT( saveAs() ) ); + + connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); } TileEditorMainWindow::~TileEditorMainWindow() @@ -556,6 +558,20 @@ void TileEditorMainWindow::onChooseTexturePath() m_ui->tileBankTexturePathPB->setText( path ); } +void TileEditorMainWindow::onOrientedStateChanged( int state ) +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + + if( state == Qt::Checked ) + node->setOriented( true ); + else + node->setOriented( false ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QModelIndex idx = m_ui->tileSetLV->currentIndex(); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index a491fc5f2..2d1a9e154 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -69,6 +69,8 @@ private Q_SLOTS: void onChooseTexturePath(); + void onOrientedStateChanged( int state ); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index b6bb30ea2..78c3afae2 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -167,6 +167,7 @@ void Node::swapRows( int a, int b ) TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) { m_parentItem = parent; + m_oriented = false; } TileSetNode::~TileSetNode() diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index b66a2b6f3..9538afa3b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -75,9 +75,13 @@ public: void setVegetSet( const QString &s ){ m_vegetSet = s; } QString vegetSet() const{ return m_vegetSet; } + bool isOriented() const{ return m_oriented; } + void setOriented( bool b ){ m_oriented = b; } + private: QString m_tileSetName; QString m_vegetSet; + bool m_oriented; }; class TileTypeNode : public Node diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 6bf13fdfe..c41673243 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -187,6 +187,8 @@ public: addTilesToSet( set, n ); setupTransitionTiles( set, n ); setupDisplacementTiles( set, n ); + + set->setOriented( n->isOriented() ); } // Add tilesets to lands From 5b2aa71b909810c982c8c3cacf8602e6a1c7d90b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 07:43:02 +0200 Subject: [PATCH 164/220] Add the already selected tilesets to the land when editing. --- .../src/plugins/tile_editor/land_edit_dialog.cpp | 11 +++++++++++ .../studio/src/plugins/tile_editor/land_edit_dialog.h | 2 ++ .../plugins/tile_editor/tile_editor_main_window.cpp | 1 + 3 files changed, 14 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp index f7f5c5ce6..87c66aa9c 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -20,6 +20,17 @@ void LandEditDialog::getSelectedTileSets( QStringList &l ) const } } +void LandEditDialog::setSelectedTileSets( QStringList &l ) +{ + tilesetLV->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + tilesetLV->addItem( itr.next() ); + } +} + void LandEditDialog::setTileSets( const QStringList &l ) { tilesetCB->clear(); diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.h b/code/studio/src/plugins/tile_editor/land_edit_dialog.h index 9b86a2d06..1ada1c23e 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.h +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -13,6 +13,8 @@ public: ~LandEditDialog(); void getSelectedTileSets( QStringList &l ) const; + void setSelectedTileSets( QStringList &l ); + void setTileSets( const QStringList &l ); private: diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a8219f6eb..1e43fa003 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -483,6 +483,7 @@ void TileEditorMainWindow::onLandEdit() Land &l = m_lands[ r ]; LandEditDialog d; + d.setSelectedTileSets( l.tilesets ); d.setTileSets( ts ); int result = d.exec(); From e82ffc9b14a0bdbc5ea414c324a54a534920580f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 10:54:08 +0200 Subject: [PATCH 165/220] TileBank loading. --- code/nel/include/nel/3d/tile_bank.h | 3 + .../tile_editor/tile_editor_main_window.cpp | 45 ++++- .../tile_editor/tile_editor_main_window.h | 2 + .../plugins/tile_editor/tile_editor_plugin.h | 1 + .../src/plugins/tile_editor/tile_item.cpp | 8 + .../src/plugins/tile_editor/tile_item.h | 2 + .../src/plugins/tile_editor/tile_model.cpp | 15 ++ .../src/plugins/tile_editor/tile_model.h | 2 + .../plugins/tile_editor/tilebank_loader.cpp | 168 ++++++++++++++++++ .../src/plugins/tile_editor/tilebank_loader.h | 23 +++ 10 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 code/studio/src/plugins/tile_editor/tilebank_loader.cpp create mode 100644 code/studio/src/plugins/tile_editor/tilebank_loader.h diff --git a/code/nel/include/nel/3d/tile_bank.h b/code/nel/include/nel/3d/tile_bank.h index 9253c5f45..f391554d3 100644 --- a/code/nel/include/nel/3d/tile_bank.h +++ b/code/nel/include/nel/3d/tile_bank.h @@ -161,6 +161,9 @@ public: { return _Name; }; + + std::set getTileSets() const{ return _TileSet; } + void setName (const std::string& name); void addTileSet (const std::string& name); void removeTileSet (const std::string& name); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 1e43fa003..427494ab4 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -33,6 +33,7 @@ #include "tile_item_delegate.h" #include "tilebank_saver.h" +#include "tilebank_loader.h" #include "land_edit_dialog.h" @@ -159,9 +160,12 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) saveAction->setEnabled( true ); QAction *saveAsAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE_AS ); saveAsAction->setEnabled( true ); + QAction *openAction = Core::ICore::instance()->menuManager()->action( Core::Constants::OPEN ); + openAction->setEnabled( true ); connect( m_ui->actionSaveTileBank, SIGNAL( triggered() ), this, SLOT( save() ) ); connect( m_ui->actionSaveTileBankAs, SIGNAL( triggered() ), this, SLOT( saveAs() ) ); + connect( m_ui->actionOpenTileBank, SIGNAL( triggered() ), this, SLOT( open() ) ); connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); } @@ -222,6 +226,30 @@ void TileEditorMainWindow::saveAs() } } +void TileEditorMainWindow::open() +{ + QString fn = QFileDialog::getOpenFileName( this, + tr( "Loading tilebank" ), + "", + tr( "tilebank files (*.tilebank)" ) ); + + if( fn.isEmpty() ) + return; + + TileBankLoader loader; + bool b = loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); + + if( !b ) + { + QMessageBox::critical( this, + tr( "Loading tilebank" ), + tr( "Failed to load tilebank %1" ).arg( fn ) ); + } + + // Put the loaded data into the GUI + onTileBankLoaded(); +} + void TileEditorMainWindow::onZoomFactor(int level) { int tile128Scaled=TileModel::TILE_128_BASE_SIZE; @@ -307,7 +335,6 @@ void TileEditorMainWindow::onTileSetAdd() TileSetNode *tileSet = model->createTileSetNode(text); // Retrieve how many rows there currently are and set the current index using that. - m_ui->tileSetLV->reset(); uint32 rows = model->rowCount(); m_ui->tileSetLV->setCurrentIndex(model->index(rows-1, 0)); } @@ -703,6 +730,20 @@ void TileEditorMainWindow::onTileSetRenamed( const QString &oldname, const QStri } } +void TileEditorMainWindow::onTileBankLoaded() +{ + m_ui->landLW->clear(); + QListIterator< Land > itr( m_lands ); + while( itr.hasNext() ) + { + m_ui->landLW->addItem( itr.next().name ); + } + + m_ui->listView128->reset(); + m_ui->listView256->reset(); + m_ui->listViewTransition->reset(); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; @@ -749,6 +790,8 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->chooseVegetPushButton->setText( vegetSet ); else m_ui->chooseVegetPushButton->setText( "..." ); + + m_ui->orientedCheckBox->setChecked( newNode->isOriented() ); } else { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 2d1a9e154..022348ab5 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -47,6 +47,7 @@ public: public Q_SLOTS: void save(); void saveAs(); + void open(); private Q_SLOTS: void onActionAddTile(bool triggered); @@ -82,6 +83,7 @@ private: void onTileSetRemoved( const QString &set ); void onTileSetRenamed( const QString &oldname, const QString &newname ); + void onTileBankLoaded(); TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h index 024e6a6e2..70fb38e77 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.h @@ -93,6 +93,7 @@ public: virtual void open() { + m_tileEditorMainWindow->open(); } void save() diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 78c3afae2..76bf7c67e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -40,6 +40,7 @@ Node::~Node() void Node::appendChild(Node *item) { + item->setParent( this ); m_childItems.append(item); } @@ -162,6 +163,13 @@ void Node::swapRows( int a, int b ) m_childItems[ b ] = temp; } +void Node::clear() +{ + qDeleteAll( m_childItems ); + m_childItems.clear(); + m_itemData.clear(); +} + /////////////////////////////////////////////////// TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 9538afa3b..3fad517c3 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -55,6 +55,8 @@ public: void swapRows( int a, int b ); + void clear(); + protected: QList m_childItems; QVector m_itemData; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d68650b8f..99cc557e3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -137,7 +137,13 @@ void TileModel::appendRow(const QList &items) void TileModel::appendRow(Node *item) { + int c = rootItem->childCount(); + + beginInsertRows( QModelIndex(), c, c ); + rootItem->appendRow(item); + + endInsertRows(); } bool TileModel::removeRows( int row, int count, const QModelIndex &parent ) @@ -272,6 +278,15 @@ bool TileModel::hasTileSet( const QString &name ) return false; } +void TileModel::clear() +{ + int c = rootItem->childCount(); + if( c == 0 ) + return; + + removeRows( 0, c ); +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 56d7b792b..f18e60fd3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -93,6 +93,8 @@ public: bool hasTileSet( const QString &name ); + void clear(); + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp new file mode 100644 index 000000000..6b56dcebe --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -0,0 +1,168 @@ +#include "tilebank_loader.h" + +#include "tile_model.h" +#include "tile_item.h" + +#include "nel/3d/tile_bank.h" +#include "nel/misc/file.h" + +class TileBankLoaderPvt +{ +public: + NL3D::CTileBank bank; + + static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + { + NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; + + switch( channel ) + { + case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileModel::TileAdditive: b = NL3D::CTile::additive; break; + case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + } + + return b; + } + + void loadLands( QList< Land > &lands ) + { + lands.clear(); + + Land l; + + int c = bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = bank.getLand( i ); + l.name = land->getName().c_str(); + + + std::set< std::string > sets = land->getTileSets(); + std::set< std::string >::const_iterator itr = sets.begin(); + while( itr != sets.end() ) + { + l.tilesets.push_back( itr->c_str() ); + ++itr; + } + + lands.push_back( l ); + } + } + + void loadTiles128( NL3D::CTileSet *set, TileTypeNode *node ) + { + int c = set->getNumTile128(); + for( int i = 0; i < c; i++ ) + { + int idx = set->getTile128( i ); + NL3D::CTile *tile = bank.getTile( idx ); + + TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + + for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + { + tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + } + + node->appendChild( tin ); + } + } + + void loadTiles256( NL3D::CTileSet *set, TileTypeNode *node ) + { + int c = set->getNumTile256(); + for( int i = 0; i < c; i++ ) + { + int idx = set->getTile256( i ); + NL3D::CTile *tile = bank.getTile( idx ); + + TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + + for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + { + tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + } + + node->appendChild( tin ); + } + } + + void loadTilesTransition( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < NL3D::CTileSet::count; i++ ) + { + const NL3D::CTileSetTransition *tr = set->getTransition( i ); + int idx = tr->getTile(); + NL3D::CTile *tile = bank.getTile( idx ); + + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + + for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + { + tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + } + } + } + + void loadTilesDisplacement( NL3D::CTileSet *set, TileTypeNode *node ) + { + for( int i = 0; i < NL3D::CTileSet::CountDisplace; i++ ) + { + uint did = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( i ) ); + const char *fn = bank.getDisplacementMap( did ); + + TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + tin->setTileFilename( TileModel::TileDiffuse, fn ); + } + } + + void loadTileSet( NL3D::CTileSet *set, TileSetNode *node ) + { + loadTiles128( set, static_cast< TileTypeNode* >( node->child( 0 ) ) ); + loadTiles256( set, static_cast< TileTypeNode* >( node->child( 1 ) ) ); + loadTilesTransition( set, static_cast< TileTypeNode* >( node->child( 2 ) ) ); + loadTilesDisplacement( set, static_cast< TileTypeNode* >( node->child( 3 ) ) ); + + node->setOriented( set->getOriented() ); + } + + void loadTileSets( TileModel *model ) + { + model->clear(); + + int c = bank.getTileSetCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileSet *set = bank.getTileSet( i ); + TileSetNode *node = model->createTileSetNode( set->getName().c_str() ); + loadTileSet( set, node ); + } + } +}; + + +TileBankLoader::TileBankLoader() +{ + p = new TileBankLoaderPvt; +} + +TileBankLoader::~TileBankLoader() +{ + delete p; + p = NULL; +} + +bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > &lands ) +{ + NLMISC::CIFile file; + if( !file.open( filename, false ) ) + return false; + + p->bank.serial( file ); + + p->loadLands( lands ); + p->loadTileSets( model ); + + return false; +} diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h new file mode 100644 index 000000000..b213cb309 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -0,0 +1,23 @@ +#ifndef TILEBANK_LOADER_H +#define TILEBANK_LOADER_H + +#include "land.h" + +class TileModel; +class TileBankLoaderPvt; + +class TileBankLoader +{ +public: + TileBankLoader(); + ~TileBankLoader(); + + bool load( const char *filename, TileModel *model, QList< Land > &lands ); + +private: + TileBankLoaderPvt *p; +}; + + +#endif + From 447caab681bdaaba9f6f407715406f0d1b43009d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 10:58:37 +0200 Subject: [PATCH 166/220] Save and load the veget set filename. --- code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 2 ++ code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 6b56dcebe..2c1d15c06 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -125,6 +125,8 @@ public: loadTilesDisplacement( set, static_cast< TileTypeNode* >( node->child( 3 ) ) ); node->setOriented( set->getOriented() ); + + node->setVegetSet( set->getTileVegetableDescFileName().c_str() ); } void loadTileSets( TileModel *model ) diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index c41673243..f650fb0d8 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -189,6 +189,8 @@ public: setupDisplacementTiles( set, n ); set->setOriented( n->isOriented() ); + + set->setTileVegetableDescFileName( n->vegetSet().toUtf8().constData() ); } // Add tilesets to lands From 99683c6569febdf7e0131632e4fce99c1722ca18 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:10:15 +0200 Subject: [PATCH 167/220] Save and load the tilebank texture path. --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 7 +++++++ code/studio/src/plugins/tile_editor/tile_model.h | 5 +++++ code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 2 ++ code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 2 ++ 4 files changed, 16 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 427494ab4..df1194e4b 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -584,6 +584,7 @@ void TileEditorMainWindow::onChooseTexturePath() m_texturePath = path; m_ui->tileBankTexturePathPB->setText( path ); + m_tileModel->setTexturePath( path ); } void TileEditorMainWindow::onOrientedStateChanged( int state ) @@ -742,6 +743,12 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->listView128->reset(); m_ui->listView256->reset(); m_ui->listViewTransition->reset(); + + QString path = m_tileModel->texturePath(); + if( path.isEmpty() ) + m_ui->tileBankTexturePathPB->setText( "..." ); + else + m_ui->tileBankTexturePathPB->setText( path ); } TileModel* TileEditorMainWindow::createTileModel() diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index f18e60fd3..f2efdb8d4 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -95,6 +95,9 @@ public: void clear(); + void setTexturePath( const QString &path ){ m_texturePath = path; } + QString texturePath() const{ return m_texturePath; } + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); @@ -109,6 +112,8 @@ private: //QList m_tiles; //int m_activeEditChannel; Node *rootItem; + + QString m_texturePath; }; #endif // TILE_MODEL_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 2c1d15c06..f51413026 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -166,5 +166,7 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > p->loadLands( lands ); p->loadTileSets( model ); + model->setTexturePath( p->bank.getAbsPath().c_str() ); + return false; } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index f650fb0d8..faec90bc4 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -223,6 +223,8 @@ bool TileBankSaver::save( const char *fileName, const TileModel* model, const QL p->addLands( lands ); p->addTileSets( model, lands ); + p->bank.setAbsPath( model->texturePath().toUtf8().constData() ); + // Save to file NLMISC::COFile f; bool b = f.open( fileName, false, false, false ); From 4a69a4f8b2d4accfaba7832a4445d028e346cc96 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:14:41 +0200 Subject: [PATCH 168/220] Set teh current selection to row 0 --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 7 +++++++ code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 1 + 2 files changed, 8 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index df1194e4b..5a77f54e7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -749,6 +749,13 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->tileBankTexturePathPB->setText( "..." ); else m_ui->tileBankTexturePathPB->setText( path ); + + QModelIndex idx = m_tileModel->index( 0, 0 ); + if( idx.isValid() ) + m_ui->tileSetLV->setCurrentIndex( idx ); + + if( m_ui->landLW->count() > 0 ) + m_ui->landLW->setCurrentRow( 0 ); } TileModel* TileEditorMainWindow::createTileModel() diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index f51413026..7be0ebeb7 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -168,5 +168,6 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > model->setTexturePath( p->bank.getAbsPath().c_str() ); + return false; } From 8e3ec659d57c9f83e52c069cd39d033b00656ec0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:15:14 +0200 Subject: [PATCH 169/220] Close the loaded file and return true... --- code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 7be0ebeb7..eb1e9a589 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -168,6 +168,7 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > model->setTexturePath( p->bank.getAbsPath().c_str() ); + file.close(); - return false; + return true; } From 47a5f95b71ffa6db376f9415a63eaed89357091c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:20:29 +0200 Subject: [PATCH 170/220] Copyright headers... --- code/studio/src/plugins/tile_editor/land.h | 39 +++++++++++++------ .../plugins/tile_editor/land_edit_dialog.cpp | 17 ++++++++ .../plugins/tile_editor/land_edit_dialog.h | 17 ++++++++ .../plugins/tile_editor/tilebank_loader.cpp | 17 ++++++++ .../src/plugins/tile_editor/tilebank_loader.h | 16 ++++++++ 5 files changed, 95 insertions(+), 11 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h index 37b0d83c6..8538d7b08 100644 --- a/code/studio/src/plugins/tile_editor/land.h +++ b/code/studio/src/plugins/tile_editor/land.h @@ -1,14 +1,31 @@ -#ifndef LAND_H -#define LAND_H - -#include - +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef LAND_H +#define LAND_H + +#include + struct Land { QString name; - QStringList tilesets; -}; - - -#endif - + QStringList tilesets; +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp index 87c66aa9c..40fbf3024 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "land_edit_dialog.h" LandEditDialog::LandEditDialog( QWidget *parent ) : diff --git a/code/studio/src/plugins/tile_editor/land_edit_dialog.h b/code/studio/src/plugins/tile_editor/land_edit_dialog.h index 1ada1c23e..ac3762b46 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.h +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef LAND_EDIT_DLG_H #define LAND_EDIT_DLG_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index eb1e9a589..b8ab201e8 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "tilebank_loader.h" #include "tile_model.h" diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h index b213cb309..1f3498d6e 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.h +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -1,3 +1,19 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + #ifndef TILEBANK_LOADER_H #define TILEBANK_LOADER_H From 0750ca7a4d91c25dfafd60f50d20299add61b169 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 14:28:17 +0200 Subject: [PATCH 171/220] Show the image that belongs to the channel that is selected. --- .../tile_editor/tile_editor_main_window.cpp | 53 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 8 +++ .../tile_editor/tile_editor_main_window.ui | 14 ++--- .../src/plugins/tile_editor/tile_item.cpp | 4 +- .../src/plugins/tile_editor/tile_item.h | 5 ++ 5 files changed, 76 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 5a77f54e7..66a73cfd1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -168,6 +168,17 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect( m_ui->actionOpenTileBank, SIGNAL( triggered() ), this, SLOT( open() ) ); connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); + + connect( m_ui->diffuse128BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); + connect( m_ui->diffuse256BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); + connect( m_ui->diffuseTrBT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); + connect( m_ui->additive128BT, SIGNAL( toggled( bool ) ), this, SLOT( onAdditiveToggled( bool ) ) ); + connect( m_ui->additive256BT, SIGNAL( toggled( bool ) ), this, SLOT( onAdditiveToggled( bool ) ) ); + connect( m_ui->additiveTrBT, SIGNAL( toggled( bool ) ), this, SLOT( onAdditiveToggled( bool ) ) ); + connect( m_ui->alphaTrBT, SIGNAL( toggled( bool ) ), this, SLOT( onAlphaToggled( bool ) ) ); + + connect( m_ui->tileViewTabWidget, SIGNAL( currentChanged( int ) ), this, SLOT( onTabChanged( int ) ) ); + } TileEditorMainWindow::~TileEditorMainWindow() @@ -601,6 +612,43 @@ void TileEditorMainWindow::onOrientedStateChanged( int state ) node->setOriented( false ); } +void TileEditorMainWindow::onDiffuseToggled( bool b ) +{ + if( !b ) + return; + + TileItemNode::setDisplayChannel( TileModel::TileDiffuse ); + updateTab(); +} + +void TileEditorMainWindow::onAdditiveToggled( bool b ) +{ + if( !b ) + return; + + TileItemNode::setDisplayChannel( TileModel::TileAdditive ); + updateTab(); +} + +void TileEditorMainWindow::onAlphaToggled( bool b ) +{ + if( !b ) + return; + + TileItemNode::setDisplayChannel( TileModel::TileAlpha ); + updateTab(); +} + +void TileEditorMainWindow::onTabChanged( int tab ) +{ + if( tab == -1 ) + return; + + m_ui->diffuse128BT->setChecked( true ); + m_ui->diffuse256BT->setChecked( true ); + m_ui->diffuseTrBT->setChecked( true ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QModelIndex idx = m_ui->tileSetLV->currentIndex(); @@ -758,6 +806,11 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->landLW->setCurrentRow( 0 ); } +void TileEditorMainWindow::updateTab() +{ + m_ui->tileViewTabWidget->currentWidget()->repaint(); +} + TileModel* TileEditorMainWindow::createTileModel() { QStringList headers; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 022348ab5..2c4286377 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -72,6 +72,12 @@ private Q_SLOTS: void onOrientedStateChanged( int state ); + void onDiffuseToggled( bool b ); + void onAdditiveToggled( bool b ); + void onAlphaToggled( bool b ); + + void onTabChanged( int tab ); + void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); @@ -85,6 +91,8 @@ private: void onTileSetRenamed( const QString &oldname, const QString &newname ); void onTileBankLoaded(); + void updateTab(); + TileModel* createTileModel(); QListView* getListViewByTab( int tab ) const; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 2e936aa8b..f45951aba 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -57,7 +57,7 @@ - + Diffuse @@ -67,7 +67,7 @@ - + Additive @@ -115,7 +115,7 @@ - + Diffuse @@ -128,7 +128,7 @@ - + Additive @@ -185,7 +185,7 @@ - + Diffuse @@ -195,14 +195,14 @@ - + Additive - + Alpha diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 76bf7c67e..7ae177220 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -264,6 +264,8 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// +TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; + TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) { m_tileFilename[channel] = filename; @@ -294,7 +296,7 @@ QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) QVariant TileItemNode::data(int column, int role) const { // find some way to know which file/bitmap to display - QString tileFilename = m_tileFilename[TileModel::TileDiffuse]; + QString tileFilename = m_tileFilename[s_displayChannel]; if(role == TileModel::TilePixmapRole || role == Qt::DecorationRole) { diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 3fad517c3..4e00c12c3 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -115,10 +115,15 @@ public: QString getTileFilename(TileModel::TTileChannel channel); void setId( int id ){ m_tileId = id; } int id() const{ return m_tileId; } + + static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } + private: int m_tileId; QMap m_tileFilename; QMap m_tileWidget; + + static TileModel::TTileChannel s_displayChannel; }; #endif // TILE_ITEM_H From fadd8fbf8993b309bea7a40aa5fbf55f72b1c577 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 14:39:19 +0200 Subject: [PATCH 172/220] Replace and delete image should be applied to the correct channel now. --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 4 ++-- code/studio/src/plugins/tile_editor/tile_item.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 66a73cfd1..a2b2525ca 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -728,7 +728,7 @@ void TileEditorMainWindow::onActionDeleteImage( int tabId ) } TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileModel::TileDiffuse, "" ); + n->setTileFilename( TileItemNode::displayChannel(), "" ); } void TileEditorMainWindow::onActionReplaceImage( int tabId ) @@ -752,7 +752,7 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) return; TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileModel::TileDiffuse, fileName ); + n->setTileFilename( TileItemNode::displayChannel(), fileName ); } void TileEditorMainWindow::onTileSetRemoved( const QString &set ) diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 4e00c12c3..5c5f8017c 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -117,6 +117,7 @@ public: int id() const{ return m_tileId; } static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } + static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } private: int m_tileId; From 677d13c7ab029f2e2de730f6ad95180d7d391b92 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:29:50 +0200 Subject: [PATCH 173/220] 128 and 256 tiles don't have alpha, so no need to load/save them. --- code/studio/src/plugins/tile_editor/tilebank_loader.cpp | 4 ++-- code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index b8ab201e8..238a41a52 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -77,7 +77,7 @@ public: TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); } @@ -96,7 +96,7 @@ public: TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index faec90bc4..bca62533d 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -76,7 +76,7 @@ public: for( int i = 0; i < node->childCount(); i++ ) { TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) { QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); From 8ea69d4b817283d07ab0b374f483ef05d56869b8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:40:02 +0200 Subject: [PATCH 174/220] Should only add 1 tile here... --- code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index bca62533d..fc686c3ad 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -76,11 +76,11 @@ public: for( int i = 0; i < node->childCount(); i++ ) { TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); + NL3D::CTile *tile = addTileToSet( set, type ); + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) { QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); - - NL3D::CTile *tile = addTileToSet( set, type ); tile->setFileName( channelToTBitmap( TileModel::TTileChannel( j ) ) , fn.toUtf8().constData() ); } } From 6386c5aac44a7d5a266c0395c3b314d9ef963c4b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:44:02 +0200 Subject: [PATCH 175/220] Should store the filename after opening.. --- code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a2b2525ca..cc4e5e6b0 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -259,6 +259,8 @@ void TileEditorMainWindow::open() // Put the loaded data into the GUI onTileBankLoaded(); + + m_fileName = fn; } void TileEditorMainWindow::onZoomFactor(int level) From ab2e54a3c8b2c5db16f33c71f6046597471b4395 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:55:09 +0200 Subject: [PATCH 176/220] When hitting 'save as' ask for a filename even if one is set. --- .../tile_editor/tile_editor_main_window.cpp | 21 ++++++++++++------- .../tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index cc4e5e6b0..ee6221229 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -200,23 +200,28 @@ TileEditorMainWindow::~TileEditorMainWindow() void TileEditorMainWindow::save() { - saveAs(); + if( m_fileName.isEmpty() ) + saveAs(); + else + saveAs( m_fileName ); } void TileEditorMainWindow::saveAs() { - if( m_fileName.isEmpty() ) - { - m_fileName = QFileDialog::getSaveFileName( this, + QString fn = QFileDialog::getSaveFileName( this, tr( "Save TileBank as..." ), "", tr( "TileBank files (*.tilebank)" ) ); - if( m_fileName.isEmpty() ) - return; + if( fn.isEmpty() ) + return; - } + saveAs( fn ); +} + +void TileEditorMainWindow::saveAs( const QString &fn ) +{ QList< QString > landNames; int c = m_ui->landLW->count(); @@ -227,7 +232,7 @@ void TileEditorMainWindow::saveAs() } TileBankSaver saver; - bool ok = saver.save( m_fileName.toUtf8().constData(), m_tileModel, m_lands ); + bool ok = saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); if( !ok ) { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 2c4286377..d98ec9651 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -47,6 +47,7 @@ public: public Q_SLOTS: void save(); void saveAs(); + void saveAs( const QString &fn ); void open(); private Q_SLOTS: From 2ddd7e10351162c02d169b90a57a05e0276aa05c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 31 Jul 2014 23:23:52 +0200 Subject: [PATCH 177/220] Line endings... --- code/studio/src/plugins/tile_editor/land.h | 28 +++---- .../src/plugins/tile_editor/tile_item.cpp | 10 +-- .../plugins/tile_editor/tile_item_delegate.h | 82 +++++++++---------- .../src/plugins/tile_editor/tile_model.cpp | 82 +++++++++---------- 4 files changed, 101 insertions(+), 101 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h index 8538d7b08..93d244d9d 100644 --- a/code/studio/src/plugins/tile_editor/land.h +++ b/code/studio/src/plugins/tile_editor/land.h @@ -1,17 +1,17 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 7ae177220..d2fa3793f 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -307,11 +307,11 @@ QVariant TileItemNode::data(int column, int role) const // Retrieve the target tile size. uint32 tileSize = TileModel::getTileTypeSize(parent->getTileType()); - if(tileFilename.isEmpty() || tileFilename == "empty") - tileFilename = ":/placeHolder/images/empty_image.png"; - - QPixmap pixmap;// = new QPixmap(); - if(!pixmap.load(tileFilename)) + if(tileFilename.isEmpty() || tileFilename == "empty") + tileFilename = ":/placeHolder/images/empty_image.png"; + + QPixmap pixmap;// = new QPixmap(); + if(!pixmap.load(tileFilename)) nlinfo("failed to load %s", tileFilename.toAscii().data()); if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) diff --git a/code/studio/src/plugins/tile_editor/tile_item_delegate.h b/code/studio/src/plugins/tile_editor/tile_item_delegate.h index 90c831fb8..015f32021 100644 --- a/code/studio/src/plugins/tile_editor/tile_item_delegate.h +++ b/code/studio/src/plugins/tile_editor/tile_item_delegate.h @@ -12,44 +12,44 @@ // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -#ifndef TILE_ITEM_DELEGATE_H -#define TILE_ITEM_DELEGATE_H - -#include -#include -#include - -#include - -class TileItemDelegate : public QStyledItemDelegate - { - public: - - enum TZoomFactor - { - ZoomSmall = 0, - ZoomNormal = 1, - ZoomLarge = 2 - }; - - static const int PIXMAP_MARGIN = 5; - - TileItemDelegate(); - virtual ~TileItemDelegate(); - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const; - - TZoomFactor getZoomFactor(); - void setZoomFactor(TZoomFactor zoomFactor); - -public Q_SLOTS: - void currentTab(int index); - - private: - TZoomFactor m_zoomFactor; - int m_imageHint; - }; - -#endif // TILE_ITEM_DELEGATE_H +// along with this program. If not, see . +#ifndef TILE_ITEM_DELEGATE_H +#define TILE_ITEM_DELEGATE_H + +#include +#include +#include + +#include + +class TileItemDelegate : public QStyledItemDelegate + { + public: + + enum TZoomFactor + { + ZoomSmall = 0, + ZoomNormal = 1, + ZoomLarge = 2 + }; + + static const int PIXMAP_MARGIN = 5; + + TileItemDelegate(); + virtual ~TileItemDelegate(); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index ) const; + + TZoomFactor getZoomFactor(); + void setZoomFactor(TZoomFactor zoomFactor); + +public Q_SLOTS: + void currentTab(int index); + + private: + TZoomFactor m_zoomFactor; + int m_imageHint; + }; + +#endif // TILE_ITEM_DELEGATE_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 99cc557e3..037be65cd 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -24,22 +24,22 @@ // Initialize the static members TileModel::TTileZoomFactor TileModel::CurrentZoomFactor; -TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) -{ - QVector rootData; - Q_FOREACH(QString header, headers) - rootData << header; - - rootItem = new Node(rootData); - - TileModel::CurrentZoomFactor = TileModel::TileZoom100; - m_indexDisplay = true; - m_fileDisplay = true; -} - -TileModel::~TileModel() -{ - delete rootItem; +TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractItemModel(parent) +{ + QVector rootData; + Q_FOREACH(QString header, headers) + rootData << header; + + rootItem = new Node(rootData); + + TileModel::CurrentZoomFactor = TileModel::TileZoom100; + m_indexDisplay = true; + m_fileDisplay = true; +} + +TileModel::~TileModel() +{ + delete rootItem; } Node *TileModel::getItem(const QModelIndex &index) const @@ -92,33 +92,33 @@ int TileModel::columnCount(const QModelIndex &parent) const return parentItem->columnCount(); } -QVariant TileModel::data(const QModelIndex &index, int role) const -{ - if(!index.isValid()) - return QVariant(); - - Node *item = static_cast(index.internalPointer()); - - // Translate the display role to the settings-specific role. - - if(role == Qt::DisplayRole) - { - if(m_indexDisplay && m_fileDisplay) - role = TileFilenameIndexRole; - else if(m_fileDisplay) - role = TileFilenameRole; - else if(m_indexDisplay) - role = TileIndexRole; - } - return item->data(index.column(), role); +QVariant TileModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + Node *item = static_cast(index.internalPointer()); + + // Translate the display role to the settings-specific role. + + if(role == Qt::DisplayRole) + { + if(m_indexDisplay && m_fileDisplay) + role = TileFilenameIndexRole; + else if(m_fileDisplay) + role = TileFilenameRole; + else if(m_indexDisplay) + role = TileIndexRole; + } + return item->data(index.column(), role); } -Qt::ItemFlags TileModel::flags(const QModelIndex &index) const -{ - if(!index.isValid()) - return Qt::ItemIsEnabled; - - return Qt::ItemIsEnabled|Qt::ItemIsSelectable; +Qt::ItemFlags TileModel::flags(const QModelIndex &index) const +{ + if(!index.isValid()) + return Qt::ItemIsEnabled; + + return Qt::ItemIsEnabled|Qt::ItemIsSelectable; } QVariant TileModel::headerData(int section, Qt::Orientation orientation, int role) const From 66c8b95e2d1e87476bd6f5c3d15577ddad9c7cd8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 1 Aug 2014 02:34:57 +0200 Subject: [PATCH 178/220] Don't reload the pixmaps every time they are displayed... -.- --- .../src/plugins/tile_editor/tile_item.cpp | 64 +++++++++++++++---- .../src/plugins/tile_editor/tile_item.h | 6 +- .../src/plugins/tile_editor/tile_model.h | 1 + 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index d2fa3793f..b9064996e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -264,23 +264,71 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// + +class TileItemNodePvt +{ +public: + + bool loadImage( TileModel::TTileChannel channel, const QString &fn ) + { + QPixmap temp; + bool b = temp.load( fn ); + + if( !b ) + return false; + + pixmaps[ channel ] = temp; + + return true; + } + + void clearImage( TileModel::TTileChannel channel ) + { + pixmaps[ channel ] = QPixmap(); + } + + const QPixmap& pixMap( TileModel::TTileChannel channel ) const{ + return pixmaps[ channel ]; + } + +private: + QPixmap pixmaps[ TileModel::TileChannelCount ]; + +}; + TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) { - m_tileFilename[channel] = filename; m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); + + pvt = new TileItemNodePvt(); + + setTileFilename( channel, filename ); } TileItemNode::~TileItemNode() { + delete pvt; + pvt = NULL; + qDeleteAll(m_childItems); } -void TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) +bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) { + QString fn = filename; + + if( filename.isEmpty() || ( filename == "empty" ) ) + fn = ":/placeHolder/images/empty_image.png"; + + bool b = pvt->loadImage( channel, fn ); + if( !b ) + return false; + m_tileFilename[channel] = filename; + return true; } QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) @@ -295,8 +343,7 @@ QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) QVariant TileItemNode::data(int column, int role) const { - // find some way to know which file/bitmap to display - QString tileFilename = m_tileFilename[s_displayChannel]; + QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; if(role == TileModel::TilePixmapRole || role == Qt::DecorationRole) { @@ -307,18 +354,13 @@ QVariant TileItemNode::data(int column, int role) const // Retrieve the target tile size. uint32 tileSize = TileModel::getTileTypeSize(parent->getTileType()); - if(tileFilename.isEmpty() || tileFilename == "empty") - tileFilename = ":/placeHolder/images/empty_image.png"; - - QPixmap pixmap;// = new QPixmap(); - if(!pixmap.load(tileFilename)) - nlinfo("failed to load %s", tileFilename.toAscii().data()); - if(TileModel::CurrentZoomFactor == TileModel::TileZoom200) tileSize *= 2; else if(TileModel::CurrentZoomFactor == TileModel::TileZoom50) tileSize /= 2; + QPixmap pixmap = pvt->pixMap( TileItemNode::s_displayChannel ); + pixmap.scaled(tileSize, tileSize); return pixmap; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 5c5f8017c..611059ffa 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -104,6 +104,8 @@ private: TileModel::TNodeTileType m_nodeTileType; }; +class TileItemNodePvt; + class TileItemNode : public Node { public: @@ -111,7 +113,7 @@ public: virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; - void setTileFilename(TileModel::TTileChannel channel, QString filename); + bool setTileFilename(TileModel::TTileChannel channel, QString filename); QString getTileFilename(TileModel::TTileChannel channel); void setId( int id ){ m_tileId = id; } int id() const{ return m_tileId; } @@ -125,6 +127,8 @@ private: QMap m_tileWidget; static TileModel::TTileChannel s_displayChannel; + + TileItemNodePvt *pvt; }; #endif // TILE_ITEM_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index f2efdb8d4..e855f8871 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -34,6 +34,7 @@ public: TileDiffuse = 0, TileAdditive = 1, TileAlpha = 2, + TileChannelCount = 3 }; enum TNodeTileType From b34db5e7da18f4176cef6fe4b3f31cfb75c0a20e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 1 Aug 2014 02:38:04 +0200 Subject: [PATCH 179/220] Apply the current zoom factor! --- code/studio/src/plugins/tile_editor/tile_item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index b9064996e..20c9492af 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -361,7 +361,7 @@ QVariant TileItemNode::data(int column, int role) const QPixmap pixmap = pvt->pixMap( TileItemNode::s_displayChannel ); - pixmap.scaled(tileSize, tileSize); + pixmap = pixmap.scaled(tileSize, tileSize); return pixmap; } From 3823a9a01b11d81e494b2701fade1ccff4dcf709 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 04:15:12 +0200 Subject: [PATCH 180/220] Added checks. Yes it's horrible and needs to be refactored. --- .../tile_editor/tile_editor_main_window.cpp | 27 +- .../src/plugins/tile_editor/tile_item.cpp | 266 +++++++++++++++++- .../src/plugins/tile_editor/tile_item.h | 13 +- .../src/plugins/tile_editor/tile_model.cpp | 8 +- .../src/plugins/tile_editor/tile_model.h | 6 +- .../plugins/tile_editor/tilebank_loader.cpp | 4 +- 6 files changed, 305 insertions(+), 19 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index ee6221229..7c9ec8f52 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -656,6 +656,14 @@ void TileEditorMainWindow::onTabChanged( int tab ) m_ui->diffuseTrBT->setChecked( true ); } +TileModel::TNodeTileType tabToType( int tabId ) +{ + if( tabId >= TileModel::TileNodeTypeCount ) + return TileModel::TileNodeTypeCount; + + return TileModel::TNodeTileType( tabId ); +} + void TileEditorMainWindow::onActionAddTile(int tabId) { QModelIndex idx = m_ui->tileSetLV->currentIndex(); @@ -683,10 +691,27 @@ void TileEditorMainWindow::onActionAddTile(int tabId) int c = n->childCount(); + TileModel::TNodeTileType type = tabToType( tabId ); + QStringListIterator itr( fileNames ); while( itr.hasNext() ) { - Node *newNode = TileModel::createItemNode( c, TileModel::TileDiffuse, itr.next() ); + TileItemNode *newNode = TileModel::createItemNode( type, c, TileModel::TileDiffuse, itr.next() ); + if( newNode->hasError() ) + { + QString error = newNode->getLastError(); + error += "\nContinue?"; + + int reply = QMessageBox::question( this, + tr( "Error adding tile" ), + error, + QMessageBox::Yes, QMessageBox::No ); + if( reply != QMessageBox::Yes ) + break; + else + continue; + } + n->appendRow( newNode ); c++; } diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 20c9492af..d60fb4bbb 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -22,6 +22,8 @@ #include +#include + Node::Node() : m_parentItem(0) { } @@ -264,18 +266,230 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// +NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) +{ + NL3D::CTile::TBitmap bm; + + switch( channel ) + { + case TileModel::TileDiffuse: bm = NL3D::CTile::diffuse; break; + case TileModel::TileAdditive: bm = NL3D::CTile::additive; break; + case TileModel::TileAlpha: bm = NL3D::CTile::alpha; break; + } + + return bm; +} class TileItemNodePvt { public: + + TileItemNodePvt() + { + for( int i = 0; i < TileModel::TileChannelCount; i++ ) + m_borderFirst[ i ] = false; + + m_id = -1; + } + + bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) + { + QImage img = pixmap.toImage(); + if( img.format() != QImage::Format_ARGB32 ) + img = img.convertToFormat( QImage::Format_ARGB32 ); + + if( img.format() != QImage::Format_ARGB32 ) + return false; + + int c = img.width() * img.height(); + + const unsigned char *data = img.bits(); + const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); + + NLMISC::CBGRA bgra; + pixels.clear(); + + int i = 0; + while( i < c ) + { + bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; + bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; + bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; + bgra.B = ( idata[ i ] & 0x000000FF ); + pixels.push_back( bgra ); + + i++; + } + + return true; + } + + int getWidthForType( TileModel::TNodeTileType type, TileModel::TTileChannel channel ) + { + int width = -1; + + switch( type ) + { + case TileModel::Tile128: width = 128; break; + case TileModel::Tile256: width = 256; break; + case TileModel::TileTransition: + { + if( channel != TileModel::TileAlpha ) + width = 128; + break; + } + + case TileModel::TileDisplacement: width = 32; break; + } + + return width; + } + + NL3D::CTileSet::TError checkTile( TileModel::TTileChannel channel ) + { + if( m_type == TileModel::TileDisplacement ) + return NL3D::CTileSet::ok; + + if( channel == TileModel::TileAdditive ) + return NL3D::CTileSet::ok; + + int pixel; + int component; + int index; + + NL3D::CTileSet set; + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + + NL3D::CTileSet::TError error = NL3D::CTileSet::ok; + + switch( m_type ) + { + case TileModel::Tile128: + error = set.checkTile128( bm, m_border[ channel ], pixel, component ); + break; + case TileModel::Tile256: + error = set.checkTile256( bm, m_border[ channel ], pixel, component ); + break; + case TileModel::TileTransition: + if( channel != TileModel::TileAlpha ) + error = set.checkTile128( bm, m_border[ channel ], pixel, component ); + else + error = set.checkTileTransition( NL3D::CTileSet::TTransition( m_id ), bm, m_border[ channel ], index, pixel, component ); + break; + } + + if( error == NL3D::CTileSet::ok ) + return NL3D::CTileSet::ok; + if( error == NL3D::CTileSet::addFirstA128128 ) + return NL3D::CTileSet::addFirstA128128; + +/* + enum TError { ok=0, topInterfaceProblem, bottomInterfaceProblem, leftInterfaceProblem, + rightInterfaceProblem, addFirstA128128, topBottomNotTheSame, rightLeftNotTheSame, + sizeInvalide, errorCount }; +*/ + static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; + + if( error != NL3D::CTileSet::ok ) + { + m_lastError = "ERROR: "; + m_lastError += NL3D::CTileSet::getErrorMessage( error ); + m_lastError += "\n"; + + switch( m_type ) + { + case TileModel::Tile128: + case TileModel::Tile256: + m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); + break; + + case TileModel::TileTransition: + if( channel != TileModel::TileAlpha ) + { + m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); + } + else + { + if ((error==NL3D::CTileSet::topInterfaceProblem)||(error==NL3D::CTileSet::bottomInterfaceProblem)|| + (error==NL3D::CTileSet::leftInterfaceProblem)||(error==NL3D::CTileSet::rightInterfaceProblem)|| + (error==NL3D::CTileSet::topBottomNotTheSame)||(error==NL3D::CTileSet::rightLeftNotTheSame) + ||(error==NL3D::CTileSet::topInterfaceProblem)) + { + if( index != -1 ) + { + m_lastError += QString( "tile: %1 pixel: %2 component: %3" ).arg( index ).arg( pixel ).arg( comp[ component ] ); + } + else + { + m_lastError += QString( "incompatible with a 128 tile, pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); + } + } + + } + break; + } + } + + return error; + } + + bool checkPixmap( TileModel::TTileChannel channel, QPixmap &pixmap ) + { + int w = pixmap.width(); + int h = pixmap.height(); + + if( w != h ) + { + m_lastError = QObject::tr( "Not a square texture." ); + return false; + } + + int width = getWidthForType( m_type, channel ); + + if( width != -1 ) + { + if( width != w ) + { + m_lastError = QObject::tr( "Not the proper size." ); + return false; + } + } + + std::vector< NLMISC::CBGRA > pixels; + + pixmapToCBGRA( pixmap, pixels ); + + m_border[ channel ].set( w, h, pixels ); + + NL3D::CTileSet::TError error = checkTile( channel ); + if( error == NL3D::CTileSet::addFirstA128128 ) + { + m_borderFirst[ channel ] = true; + return true; + } + + if( error != NL3D::CTileSet::ok ) + return false; + + return true; + } - bool loadImage( TileModel::TTileChannel channel, const QString &fn ) + bool loadImage( TileModel::TTileChannel channel, const QString &fn, bool empty = false ) { QPixmap temp; bool b = temp.load( fn ); if( !b ) + { + m_lastError = QObject::tr( "Cannot open file %1" ).arg( fn ); return false; + } + + if( !empty ) + { + if( !checkPixmap( channel, temp ) ) + return false; + } pixmaps[ channel ] = temp; @@ -291,19 +505,34 @@ public: return pixmaps[ channel ]; } + void setType( TileModel::TNodeTileType type ){ m_type = type; } + void setId( int id ){ m_id = id; } + int id() const{ return m_id; } + + QString getLastError() const{ return m_lastError; } + bool borderFirst( TileModel::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } + private: QPixmap pixmaps[ TileModel::TileChannelCount ]; - + TileModel::TNodeTileType m_type; + NL3D::CTileBorder m_border[ TileModel::TileChannelCount ]; + int m_id; + QString m_lastError; + bool m_borderFirst[ TileModel::TileChannelCount ]; }; TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; -TileItemNode::TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) : m_tileId(tileId) +TileItemNode::TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) { m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); pvt = new TileItemNodePvt(); + pvt->setType( type ); + pvt->setId( tileId ); + + m_hasError = false; setTileFilename( channel, filename ); } @@ -319,11 +548,16 @@ TileItemNode::~TileItemNode() bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) { QString fn = filename; + bool empty = false; if( filename.isEmpty() || ( filename == "empty" ) ) + { fn = ":/placeHolder/images/empty_image.png"; + empty = true; + } - bool b = pvt->loadImage( channel, fn ); + bool b = pvt->loadImage( channel, fn, empty ); + m_hasError = !b; if( !b ) return false; @@ -341,6 +575,26 @@ QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) return itr.value(); } +void TileItemNode::setId( int id ) +{ + pvt->setId( id ); +} + +int TileItemNode::id() const +{ + return pvt->id(); +} + +QString TileItemNode::getLastError() const +{ + return pvt->getLastError(); +} + +bool TileItemNode::borderFirst() const +{ + return false; +} + QVariant TileItemNode::data(int column, int role) const { QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; @@ -375,11 +629,11 @@ QVariant TileItemNode::data(int column, int role) const } else if(role == TileModel::TileIndexRole) { - return QVariant("("+QString::number(m_tileId)+")"); + return QVariant("("+QString::number(pvt->id())+")"); } else if(role == TileModel::TileFilenameIndexRole) { - return QVariant(tileFilename + " ("+QString::number(m_tileId)+")"); + return QVariant(tileFilename + " ("+QString::number(pvt->id())+")"); } return QVariant(); diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 611059ffa..fc5443037 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -109,26 +109,31 @@ class TileItemNodePvt; class TileItemNode : public Node { public: - TileItemNode(int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); + TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; bool setTileFilename(TileModel::TTileChannel channel, QString filename); QString getTileFilename(TileModel::TTileChannel channel); - void setId( int id ){ m_tileId = id; } - int id() const{ return m_tileId; } + void setId( int id ); + int id() const; + QString getLastError() const; + bool borderFirst() const; static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } + bool hasError() const{ return m_hasError; } + private: - int m_tileId; QMap m_tileFilename; QMap m_tileWidget; static TileModel::TTileChannel s_displayChannel; TileItemNodePvt *pvt; + + bool m_hasError; }; #endif // TILE_ITEM_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 037be65cd..d1ab0d238 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -197,7 +197,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode(transPos, TileDiffuse, QString("empty")); + TileItemNode *transTile= new TileItemNode( TileModel::TileTransition, transPos, TileDiffuse, QString("empty")); tileTrans->appendRow(transTile); } @@ -209,7 +209,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode(dispPos, TileDiffuse, QString("empty")); + TileItemNode *dispTile= new TileItemNode( TileModel::TileDisplacement, dispPos, TileDiffuse, QString("empty")); tileDisp->appendRow(dispTile); } @@ -219,9 +219,9 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) return tileSet; } -Node *TileModel::createItemNode( int id, TTileChannel channel, const QString &fileName ) +TileItemNode *TileModel::createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ) { - return new TileItemNode( id, channel, fileName ); + return new TileItemNode( type, id, channel, fileName ); } const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index e855f8871..c22a43091 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -23,6 +23,7 @@ class Node; class TileSetNode; +class TileItemNode; class TileModel : public QAbstractItemModel { @@ -42,7 +43,8 @@ public: Tile128 = 0, Tile256 = 1, TileTransition = 2, - TileDisplacement = 3 + TileDisplacement = 3, + TileNodeTypeCount = 4 }; enum TTileItemRole @@ -85,7 +87,7 @@ public: void swapRows( int a, int b ); TileSetNode *createTileSetNode(QString tileSetName); - static Node *createItemNode( int id, TTileChannel channel, const QString &fileName ); + static TileItemNode *createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ); static const char *getTileTypeName(TNodeTileType type); static uint32 getTileTypeSize(TileModel::TNodeTileType type); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 238a41a52..73c8007d8 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -75,7 +75,7 @@ public: int idx = set->getTile128( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileModel::Tile128, i, TileModel::TileDiffuse, "" ); for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { @@ -94,7 +94,7 @@ public: int idx = set->getTile256( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileModel::Tile256, i, TileModel::TileDiffuse, "" ); for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { From ca1f00e35a5f485e7d8201255eb287ab165ad81a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 17:58:02 +0200 Subject: [PATCH 181/220] Save the tile border, etc data when saving. --- .../src/plugins/tile_editor/tile_item.cpp | 23 +++-- .../src/plugins/tile_editor/tile_item.h | 9 +- .../plugins/tile_editor/tilebank_saver.cpp | 91 ++++++++++++++++--- 3 files changed, 102 insertions(+), 21 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index d60fb4bbb..fe1df0ebf 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -383,11 +383,6 @@ public: if( error == NL3D::CTileSet::addFirstA128128 ) return NL3D::CTileSet::addFirstA128128; -/* - enum TError { ok=0, topInterfaceProblem, bottomInterfaceProblem, leftInterfaceProblem, - rightInterfaceProblem, addFirstA128128, topBottomNotTheSame, rightLeftNotTheSame, - sizeInvalide, errorCount }; -*/ static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; if( error != NL3D::CTileSet::ok ) @@ -484,6 +479,8 @@ public: m_lastError = QObject::tr( "Cannot open file %1" ).arg( fn ); return false; } + + m_borderFirst[ channel ] = false; if( !empty ) { @@ -512,6 +509,8 @@ public: QString getLastError() const{ return m_lastError; } bool borderFirst( TileModel::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } + const NL3D::CTileBorder &border( TileModel::TTileChannel channel ){ return m_border[ channel ]; } + private: QPixmap pixmaps[ TileModel::TileChannelCount ]; TileModel::TNodeTileType m_type; @@ -590,9 +589,19 @@ QString TileItemNode::getLastError() const return pvt->getLastError(); } -bool TileItemNode::borderFirst() const +bool TileItemNode::borderFirst( TileModel::TTileChannel channel ) const { - return false; + return pvt->borderFirst( channel ); +} + +const NL3D::CTileBorder& TileItemNode::border( TileModel::TTileChannel channel ) const +{ + return pvt->border( channel ); +} + +int TileItemNode::alphaRot() const +{ + return 0; } QVariant TileItemNode::data(int column, int role) const diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index fc5443037..2e374061d 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -24,6 +24,11 @@ #include "tile_model.h" +namespace NL3D +{ + class CTileBorder; +} + class TileWidget; class Node @@ -118,7 +123,9 @@ public: void setId( int id ); int id() const; QString getLastError() const; - bool borderFirst() const; + bool borderFirst( TileModel::TTileChannel channel ) const; + const NL3D::CTileBorder& border( TileModel::TTileChannel channel ) const; + int alphaRot() const; static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index fc686c3ad..65559505a 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -96,19 +96,76 @@ public: } } + void setupTiles128( NL3D::CTileSet *set, TileTypeNode *node ) + { + TileItemNode *tileNode = NULL; + for( int i = 0; i < node->childCount(); i++ ) + { + tileNode = static_cast< TileItemNode* >( node->child( i ) ); + + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + { + TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + const NL3D::CTileBorder &border = tileNode->border( channel ); + + if( tileNode->borderFirst( channel ) ) + set->setBorder( bm, border ); + + set->setTile128( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); + } + } + } + + void setupTiles256( NL3D::CTileSet *set, TileTypeNode *node ) + { + TileItemNode *tileNode = NULL; + for( int i = 0; i < node->childCount(); i++ ) + { + tileNode = static_cast< TileItemNode* >( node->child( i ) ); + + for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + { + TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + const NL3D::CTileBorder &border = tileNode->border( channel ); + + if( tileNode->borderFirst( channel ) ) + set->setBorder( bm, border ); + + set->setTile256( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); + } + } + } + void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) { - NL3D::CTileSetTransition *tr = set->getTransition( idx ); - int tid = tr->getTile(); - NL3D::CTile *tile = bank.getTile( tid ); + TileModel::TTileChannel channel; + NL3D::CTile::TBitmap bm; + NL3D::CTileSet::TTransition tr; - if( tile == NULL ) - return; - - for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + // Diffuse, Additive + for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) { - QString fn = node->getTileFilename( TileModel::TTileChannel( i ) ); - tile->setFileName( channelToTBitmap( TileModel::TTileChannel( i ) ), fn.toUtf8().constData() ); + channel =TileModel::TTileChannel( i ); + bm = channelToTBitmap( channel ); + tr = NL3D::CTileSet::TTransition( idx ); + const NL3D::CTileBorder &border = node->border( channel ); + + if( node->borderFirst( channel ) ) + set->setBorder( bm, border ); + set->setTileTransition( tr, node->getTileFilename( channel ).toUtf8().constData(), bm, bank, border ); + } + + // Alpha + { + channel = TileModel::TileAlpha; + bm = channelToTBitmap( channel ); + tr = NL3D::CTileSet::TTransition( idx ); + const NL3D::CTileBorder &border = node->border( channel ); + int rot = node->alphaRot(); + + set->setTileTransitionAlpha( tr, node->getTileFilename( channel ).toUtf8().constData(), bank, border, rot ); } } @@ -149,6 +206,17 @@ public: setupDisplacementTiles( set, tn ); } + void setupTiles( NL3D::CTileSet *set, TileSetNode *node ) + { + TileTypeNode *tn128 = static_cast< TileTypeNode* >( node->child( 0 ) ); + TileTypeNode *tn256 = static_cast< TileTypeNode* >( node->child( 1 ) ); + + setupTiles128( set, tn128 ); + setupTiles256( set, tn256 ); + setupTransitionTiles( set, node ); + setupDisplacementTiles( set, node ); + } + void addLands( const QList< Land > &lands ) { QListIterator< Land > itr( lands ); @@ -185,11 +253,8 @@ public: TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); addTilesToSet( set, n ); - setupTransitionTiles( set, n ); - setupDisplacementTiles( set, n ); - + setupTiles( set, n ); set->setOriented( n->isOriented() ); - set->setTileVegetableDescFileName( n->vegetSet().toUtf8().constData() ); } From df4446701e9879743f454cac81dd90d7899e3bf9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 19:04:34 +0200 Subject: [PATCH 182/220] Rotation can now be set. --- .../tile_editor/tile_editor_main_window.cpp | 24 +++++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 3 +++ .../tile_editor/tile_editor_main_window.ui | 12 ++++++++++ .../src/plugins/tile_editor/tile_item.cpp | 9 ++++++- .../src/plugins/tile_editor/tile_item.h | 2 ++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 7c9ec8f52..aee2002ce 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -58,6 +58,23 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) rotateActions.push_back(m_ui->actionRotateTile270); m_rotationMenu->addActions(rotateActions); m_ui->toolBar->addAction(m_rotationMenu->menuAction()); + m_rotateSM = new QSignalMapper(); + m_rotateAG = new QActionGroup(this); + m_rotateAG->addAction(m_ui->actionRotateTile0); + m_rotateAG->addAction(m_ui->actionRotateTile90); + m_rotateAG->addAction(m_ui->actionRotateTile180); + m_rotateAG->addAction(m_ui->actionRotateTile270); + m_ui->actionRotateTile0->setChecked( true ); + + connect( m_ui->actionRotateTile0, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + connect( m_ui->actionRotateTile90, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + connect( m_ui->actionRotateTile180, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + connect( m_ui->actionRotateTile270, SIGNAL( triggered() ), m_rotateSM, SLOT( map() ) ); + m_rotateSM->setMapping( m_ui->actionRotateTile0, 0 ); + m_rotateSM->setMapping( m_ui->actionRotateTile90, 1 ); + m_rotateSM->setMapping( m_ui->actionRotateTile180, 2 ); + m_rotateSM->setMapping( m_ui->actionRotateTile270, 3 ); + connect( m_rotateSM, SIGNAL( mapped( int ) ), this, SLOT( onRotate( int ) ) ); // Create the tile zoom menu. m_zoomMenu = new QMenu(tr("Zoom"), m_ui->toolBar); @@ -186,6 +203,8 @@ TileEditorMainWindow::~TileEditorMainWindow() delete m_ui; delete m_undoStack; delete m_rotationMenu; + delete m_rotateSM; + delete m_rotateAG; delete m_tileDisplayMenu; delete m_tileEditorMenu; @@ -315,6 +334,11 @@ void TileEditorMainWindow::onZoomFactor(int level) m_ui->listViewTransition->repaint(); } +void TileEditorMainWindow::onRotate( int id ) +{ + TileItemNode::setAlphaRot( id * 90 ); +} + void TileEditorMainWindow::onActionAddTile(bool triggered) { onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index d98ec9651..44b2c9869 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -81,6 +81,7 @@ private Q_SLOTS: void changeActiveTileSet(const QModelIndex &newIndex, const QModelIndex &oldIndex); void onZoomFactor(int level); + void onRotate(int id); private: void onActionAddTile(int tabId); @@ -107,6 +108,8 @@ private: QMenu *m_zoomMenu; QActionGroup *m_zoomActionGroup; QSignalMapper *m_zoomSignalMapper; + QActionGroup *m_rotateAG; + QSignalMapper *m_rotateSM; TileItemDelegate *m_tileItemDelegate; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index f45951aba..8974570a1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -581,6 +581,9 @@ + + true + :/tileRotation/images/rotation0.png:/tileRotation/images/rotation0.png @@ -617,6 +620,9 @@ + + true + :/tileRotation/images/rotation90.png:/tileRotation/images/rotation90.png @@ -629,6 +635,9 @@ + + true + :/tileRotation/images/rotation180.png:/tileRotation/images/rotation180.png @@ -641,6 +650,9 @@ + + true + :/tileRotation/images/rotation270.png:/tileRotation/images/rotation270.png diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index fe1df0ebf..1daa3c297 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -290,6 +290,7 @@ public: m_borderFirst[ i ] = false; m_id = -1; + m_alphaRot = 0; } bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) @@ -511,6 +512,9 @@ public: const NL3D::CTileBorder &border( TileModel::TTileChannel channel ){ return m_border[ channel ]; } + int alphaRot() const{ return m_alphaRot; } + void setAlphaRot( int rot ){ m_alphaRot = rot; } + private: QPixmap pixmaps[ TileModel::TileChannelCount ]; TileModel::TNodeTileType m_type; @@ -518,9 +522,11 @@ private: int m_id; QString m_lastError; bool m_borderFirst[ TileModel::TileChannelCount ]; + int m_alphaRot; }; TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; +int TileItemNode::s_alphaRot = 0; TileItemNode::TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) { @@ -555,6 +561,7 @@ bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file empty = true; } + pvt->setAlphaRot( s_alphaRot ); bool b = pvt->loadImage( channel, fn, empty ); m_hasError = !b; if( !b ) @@ -601,7 +608,7 @@ const NL3D::CTileBorder& TileItemNode::border( TileModel::TTileChannel channel ) int TileItemNode::alphaRot() const { - return 0; + return pvt->alphaRot(); } QVariant TileItemNode::data(int column, int role) const diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 2e374061d..14bc66fe4 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -129,6 +129,7 @@ public: static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } + static void setAlphaRot( int rot ){ s_alphaRot = rot; } bool hasError() const{ return m_hasError; } @@ -137,6 +138,7 @@ private: QMap m_tileWidget; static TileModel::TTileChannel s_displayChannel; + static int s_alphaRot; TileItemNodePvt *pvt; From 80f7dd725d057a08af0d3b46b979ceac494795ac Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 21:33:13 +0200 Subject: [PATCH 183/220] Started to rework tile checks, tile banks loading / saving. A tilebank will now be in the tilemodel, and it will work from there. Also moved some constants into an independent file. --- code/nel/include/nel/3d/tile_bank.h | 2 + .../src/plugins/tile_editor/tile_bank.cpp | 110 ++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 29 +++++ .../src/plugins/tile_editor/tile_constants.h | 26 +++++ .../tile_editor/tile_editor_main_window.cpp | 33 ++++-- .../src/plugins/tile_editor/tile_item.cpp | 94 ++++++++------- .../src/plugins/tile_editor/tile_item.h | 30 ++--- .../src/plugins/tile_editor/tile_model.cpp | 62 +++++++--- .../src/plugins/tile_editor/tile_model.h | 32 ++--- .../plugins/tile_editor/tilebank_loader.cpp | 26 ++--- .../plugins/tile_editor/tilebank_saver.cpp | 42 +++---- 11 files changed, 349 insertions(+), 137 deletions(-) create mode 100644 code/studio/src/plugins/tile_editor/tile_bank.cpp create mode 100644 code/studio/src/plugins/tile_editor/tile_bank.h create mode 100644 code/studio/src/plugins/tile_editor/tile_constants.h diff --git a/code/nel/include/nel/3d/tile_bank.h b/code/nel/include/nel/3d/tile_bank.h index f391554d3..89b8e2272 100644 --- a/code/nel/include/nel/3d/tile_bank.h +++ b/code/nel/include/nel/3d/tile_bank.h @@ -172,6 +172,8 @@ public: return _TileSet.find (name)!=_TileSet.end(); } + void clear(){ _TileSet.clear(); } + void serial(class NLMISC::IStream &f) throw(NLMISC::EStream); private: diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp new file mode 100644 index 000000000..f98b4ef38 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -0,0 +1,110 @@ +#include "tile_bank.h" +#include "nel/3d/tile_bank.h" + +#include + +bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) +{ + QImage img = pixmap.toImage(); + if( img.format() != QImage::Format_ARGB32 ) + img = img.convertToFormat( QImage::Format_ARGB32 ); + + if( img.format() != QImage::Format_ARGB32 ) + return false; + + int c = img.width() * img.height(); + + const unsigned char *data = img.bits(); + const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); + + NLMISC::CBGRA bgra; + pixels.clear(); + + int i = 0; + while( i < c ) + { + bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; + bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; + bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; + bgra.B = ( idata[ i ] & 0x000000FF ); + pixels.push_back( bgra ); + + i++; + } + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +class TileBankPvt +{ +public: + NL3D::CTileBank m_bank; +}; + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TileBank::TileBank() +{ + m_pvt = new TileBankPvt(); +} + +TileBank::~TileBank() +{ + delete m_pvt; +} + +void TileBank::addTileSet( const QString &name ) +{ + m_pvt->m_bank.addTileSet( name.toUtf8().constData() ); + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( 0 ); +} + +void TileBank::addLand( const QString &name ) +{ + m_pvt->m_bank.addLand( name.toUtf8().constData() ); +} + +void TileBank::setLandSets( int idx, const QStringList &l ) +{ + NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); + land->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + land->addTileSet( itr.next().toUtf8().constData() ); + } +} + +bool TileBank::addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return false; + + QPixmap pm = pixmap.value< QPixmap >(); + if( pm.isNull() ) + return false; + + if( pm.width() != pm.height() ) + return false; + + std::vector< NLMISC::CBGRA > pixels; + pixmapToCBGRA( pm, pixels ); + + int tile; + set->addTile128( tile, m_pvt->m_bank ); + + NL3D::CTileBorder border; + border.set( pm.width(), pm.height(), pixels ); + + + + return true; +} \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h new file mode 100644 index 000000000..ab4d28ee8 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -0,0 +1,29 @@ +#ifndef TILE_BANK_H +#define TILE_BANK_H + +#include +#include +#include + +#include "tile_constants.h" + +class TileBankPvt; + +class TileBank +{ +public: + TileBank(); + ~TileBank(); + + void addTileSet( const QString &name ); + void addLand( const QString &name ); + void setLandSets( int idx, const QStringList &l ); + + bool addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + +private: + TileBankPvt *m_pvt; +}; + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_constants.h b/code/studio/src/plugins/tile_editor/tile_constants.h new file mode 100644 index 000000000..e75664d43 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_constants.h @@ -0,0 +1,26 @@ +#ifndef TILE_CONSTANTS_H +#define TILE_CONSTANTS_H + + +namespace TileConstants +{ + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + TileChannelCount = 3 + }; + + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3, + TileNodeTypeCount = 4 + }; +} + + +#endif diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index aee2002ce..dd3ece7c7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -648,7 +648,7 @@ void TileEditorMainWindow::onDiffuseToggled( bool b ) if( !b ) return; - TileItemNode::setDisplayChannel( TileModel::TileDiffuse ); + TileItemNode::setDisplayChannel( TileConstants::TileDiffuse ); updateTab(); } @@ -657,7 +657,7 @@ void TileEditorMainWindow::onAdditiveToggled( bool b ) if( !b ) return; - TileItemNode::setDisplayChannel( TileModel::TileAdditive ); + TileItemNode::setDisplayChannel( TileConstants::TileAdditive ); updateTab(); } @@ -666,7 +666,7 @@ void TileEditorMainWindow::onAlphaToggled( bool b ) if( !b ) return; - TileItemNode::setDisplayChannel( TileModel::TileAlpha ); + TileItemNode::setDisplayChannel( TileConstants::TileAlpha ); updateTab(); } @@ -680,12 +680,12 @@ void TileEditorMainWindow::onTabChanged( int tab ) m_ui->diffuseTrBT->setChecked( true ); } -TileModel::TNodeTileType tabToType( int tabId ) +TileConstants::TNodeTileType tabToType( int tabId ) { - if( tabId >= TileModel::TileNodeTypeCount ) - return TileModel::TileNodeTypeCount; + if( tabId >= TileConstants::TileNodeTypeCount ) + return TileConstants::TileNodeTypeCount; - return TileModel::TNodeTileType( tabId ); + return TileConstants::TNodeTileType( tabId ); } void TileEditorMainWindow::onActionAddTile(int tabId) @@ -705,6 +705,8 @@ void TileEditorMainWindow::onActionAddTile(int tabId) if( !idx.isValid() ) return; + int setId = idx.row(); + TileSetNode *tsn = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); Node *n = tsn->child( tabId ); @@ -715,12 +717,25 @@ void TileEditorMainWindow::onActionAddTile(int tabId) int c = n->childCount(); - TileModel::TNodeTileType type = tabToType( tabId ); + TileConstants::TNodeTileType type = tabToType( tabId ); QStringListIterator itr( fileNames ); while( itr.hasNext() ) { - TileItemNode *newNode = TileModel::createItemNode( type, c, TileModel::TileDiffuse, itr.next() ); + TileItemNode *newNode = m_tileModel->createItemNode( setId, type, c, TileConstants::TileDiffuse, itr.next() ); + if( newNode == NULL ) + { + int reply = QMessageBox::question( this, + tr( "Error adding tile" ), + tr( "Failed to create tile!\nContinue?" ), + QMessageBox::Yes, QMessageBox::No ); + if( reply != QMessageBox::Yes ) + break; + else + continue; + } + + if( newNode->hasError() ) { QString error = newNode->getLastError(); diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 1daa3c297..56f621dee 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -203,7 +203,7 @@ int TileSetNode::columnCount() const /////////////////////////////////////////////////// -TileTypeNode::TileTypeNode(TileModel::TNodeTileType type, Node *parent) : m_nodeTileType(type) +TileTypeNode::TileTypeNode(TileConstants::TNodeTileType type, Node *parent) : m_nodeTileType(type) { m_parentItem = parent; } @@ -230,7 +230,7 @@ int TileTypeNode::columnCount() const return 1; } -TileModel::TNodeTileType TileTypeNode::getTileType() +TileConstants::TNodeTileType TileTypeNode::getTileType() { return m_nodeTileType; } @@ -266,15 +266,15 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// -NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) +NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) { NL3D::CTile::TBitmap bm; switch( channel ) { - case TileModel::TileDiffuse: bm = NL3D::CTile::diffuse; break; - case TileModel::TileAdditive: bm = NL3D::CTile::additive; break; - case TileModel::TileAlpha: bm = NL3D::CTile::alpha; break; + case TileConstants::TileDiffuse: bm = NL3D::CTile::diffuse; break; + case TileConstants::TileAdditive: bm = NL3D::CTile::additive; break; + case TileConstants::TileAlpha: bm = NL3D::CTile::alpha; break; } return bm; @@ -286,7 +286,7 @@ public: TileItemNodePvt() { - for( int i = 0; i < TileModel::TileChannelCount; i++ ) + for( int i = 0; i < TileConstants::TileChannelCount; i++ ) m_borderFirst[ i ] = false; m_id = -1; @@ -325,33 +325,33 @@ public: return true; } - int getWidthForType( TileModel::TNodeTileType type, TileModel::TTileChannel channel ) + int getWidthForType( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel ) { int width = -1; switch( type ) { - case TileModel::Tile128: width = 128; break; - case TileModel::Tile256: width = 256; break; - case TileModel::TileTransition: + case TileConstants::Tile128: width = 128; break; + case TileConstants::Tile256: width = 256; break; + case TileConstants::TileTransition: { - if( channel != TileModel::TileAlpha ) + if( channel != TileConstants::TileAlpha ) width = 128; break; } - case TileModel::TileDisplacement: width = 32; break; + case TileConstants::TileDisplacement: width = 32; break; } return width; } - NL3D::CTileSet::TError checkTile( TileModel::TTileChannel channel ) + NL3D::CTileSet::TError checkTile( TileConstants::TTileChannel channel ) { - if( m_type == TileModel::TileDisplacement ) + if( m_type == TileConstants::TileDisplacement ) return NL3D::CTileSet::ok; - if( channel == TileModel::TileAdditive ) + if( channel == TileConstants::TileAdditive ) return NL3D::CTileSet::ok; int pixel; @@ -365,14 +365,14 @@ public: switch( m_type ) { - case TileModel::Tile128: + case TileConstants::Tile128: error = set.checkTile128( bm, m_border[ channel ], pixel, component ); break; - case TileModel::Tile256: + case TileConstants::Tile256: error = set.checkTile256( bm, m_border[ channel ], pixel, component ); break; - case TileModel::TileTransition: - if( channel != TileModel::TileAlpha ) + case TileConstants::TileTransition: + if( channel != TileConstants::TileAlpha ) error = set.checkTile128( bm, m_border[ channel ], pixel, component ); else error = set.checkTileTransition( NL3D::CTileSet::TTransition( m_id ), bm, m_border[ channel ], index, pixel, component ); @@ -394,13 +394,13 @@ public: switch( m_type ) { - case TileModel::Tile128: - case TileModel::Tile256: + case TileConstants::Tile128: + case TileConstants::Tile256: m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); break; - case TileModel::TileTransition: - if( channel != TileModel::TileAlpha ) + case TileConstants::TileTransition: + if( channel != TileConstants::TileAlpha ) { m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); } @@ -429,7 +429,7 @@ public: return error; } - bool checkPixmap( TileModel::TTileChannel channel, QPixmap &pixmap ) + bool checkPixmap( TileConstants::TTileChannel channel, QPixmap &pixmap ) { int w = pixmap.width(); int h = pixmap.height(); @@ -470,7 +470,7 @@ public: return true; } - bool loadImage( TileModel::TTileChannel channel, const QString &fn, bool empty = false ) + bool loadImage( TileConstants::TTileChannel channel, const QString &fn, bool empty = false ) { QPixmap temp; bool b = temp.load( fn ); @@ -483,52 +483,54 @@ public: m_borderFirst[ channel ] = false; + /* if( !empty ) { if( !checkPixmap( channel, temp ) ) return false; } + */ pixmaps[ channel ] = temp; return true; } - void clearImage( TileModel::TTileChannel channel ) + void clearImage( TileConstants::TTileChannel channel ) { pixmaps[ channel ] = QPixmap(); } - const QPixmap& pixMap( TileModel::TTileChannel channel ) const{ + const QPixmap& pixMap( TileConstants::TTileChannel channel ) const{ return pixmaps[ channel ]; } - void setType( TileModel::TNodeTileType type ){ m_type = type; } + void setType( TileConstants::TNodeTileType type ){ m_type = type; } void setId( int id ){ m_id = id; } int id() const{ return m_id; } QString getLastError() const{ return m_lastError; } - bool borderFirst( TileModel::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } + bool borderFirst( TileConstants::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } - const NL3D::CTileBorder &border( TileModel::TTileChannel channel ){ return m_border[ channel ]; } + const NL3D::CTileBorder &border( TileConstants::TTileChannel channel ){ return m_border[ channel ]; } int alphaRot() const{ return m_alphaRot; } void setAlphaRot( int rot ){ m_alphaRot = rot; } private: - QPixmap pixmaps[ TileModel::TileChannelCount ]; - TileModel::TNodeTileType m_type; - NL3D::CTileBorder m_border[ TileModel::TileChannelCount ]; + QPixmap pixmaps[ TileConstants::TileChannelCount ]; + TileConstants::TNodeTileType m_type; + NL3D::CTileBorder m_border[ TileConstants::TileChannelCount ]; int m_id; QString m_lastError; - bool m_borderFirst[ TileModel::TileChannelCount ]; + bool m_borderFirst[ TileConstants::TileChannelCount ]; int m_alphaRot; }; -TileModel::TTileChannel TileItemNode::s_displayChannel = TileModel::TileDiffuse; +TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; int TileItemNode::s_alphaRot = 0; -TileItemNode::TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent) +TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent) { m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); @@ -550,7 +552,7 @@ TileItemNode::~TileItemNode() qDeleteAll(m_childItems); } -bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString filename) +bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString filename) { QString fn = filename; bool empty = false; @@ -571,9 +573,9 @@ bool TileItemNode::setTileFilename(TileModel::TTileChannel channel, QString file return true; } -QString TileItemNode::getTileFilename(TileModel::TTileChannel channel) +QString TileItemNode::getTileFilename(TileConstants::TTileChannel channel) { - QMap< TileModel::TTileChannel, QString >::const_iterator itr + QMap< TileConstants::TTileChannel, QString >::const_iterator itr = m_tileFilename.find( channel ); if( itr == m_tileFilename.end() ) return ""; @@ -596,12 +598,12 @@ QString TileItemNode::getLastError() const return pvt->getLastError(); } -bool TileItemNode::borderFirst( TileModel::TTileChannel channel ) const +bool TileItemNode::borderFirst( TileConstants::TTileChannel channel ) const { return pvt->borderFirst( channel ); } -const NL3D::CTileBorder& TileItemNode::border( TileModel::TTileChannel channel ) const +const NL3D::CTileBorder& TileItemNode::border( TileConstants::TTileChannel channel ) const { return pvt->border( channel ); } @@ -658,4 +660,10 @@ QVariant TileItemNode::data(int column, int role) const int TileItemNode::columnCount() const { return 1; -} \ No newline at end of file +} + +QVariant TileItemNode::pixmap( TileConstants::TTileChannel channel ) const +{ + return pvt->pixMap( channel ); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 14bc66fe4..342846ab8 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -95,18 +95,18 @@ class TileTypeNode : public Node { public: - TileTypeNode(TileModel::TNodeTileType type, Node *parent=0); + TileTypeNode(TileConstants::TNodeTileType type, Node *parent=0); virtual ~TileTypeNode(); QVariant data(int column, int role) const; int columnCount() const; - TileModel::TNodeTileType getTileType(); + TileConstants::TNodeTileType getTileType(); bool removeChildren( int position, int count ); private: void reindex(); - TileModel::TNodeTileType m_nodeTileType; + TileConstants::TNodeTileType m_nodeTileType; }; class TileItemNodePvt; @@ -114,30 +114,32 @@ class TileItemNodePvt; class TileItemNode : public Node { public: - TileItemNode( TileModel::TNodeTileType type, int tileId, TileModel::TTileChannel channel, QString filename, Node *parent=0); + TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; - bool setTileFilename(TileModel::TTileChannel channel, QString filename); - QString getTileFilename(TileModel::TTileChannel channel); + bool setTileFilename(TileConstants::TTileChannel channel, QString filename); + QString getTileFilename(TileConstants::TTileChannel channel); void setId( int id ); int id() const; QString getLastError() const; - bool borderFirst( TileModel::TTileChannel channel ) const; - const NL3D::CTileBorder& border( TileModel::TTileChannel channel ) const; + bool borderFirst( TileConstants::TTileChannel channel ) const; + const NL3D::CTileBorder& border( TileConstants::TTileChannel channel ) const; int alphaRot() const; - static void setDisplayChannel( TileModel::TTileChannel channel ){ s_displayChannel = channel; } - static TileModel::TTileChannel displayChannel(){ return s_displayChannel; } + static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } + static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } static void setAlphaRot( int rot ){ s_alphaRot = rot; } bool hasError() const{ return m_hasError; } -private: - QMap m_tileFilename; - QMap m_tileWidget; + QVariant pixmap( TileConstants::TTileChannel channel ) const; - static TileModel::TTileChannel s_displayChannel; +private: + QMap m_tileFilename; + QMap m_tileWidget; + + static TileConstants::TTileChannel s_displayChannel; static int s_alphaRot; TileItemNodePvt *pvt; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d1ab0d238..fbdd07223 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -16,6 +16,7 @@ #include "tile_model.h" #include "tile_item.h" +#include "tile_bank.h" #include @@ -35,6 +36,8 @@ TileModel::TileModel(const QStringList &headers, QObject *parent) : QAbstractIte TileModel::CurrentZoomFactor = TileModel::TileZoom100; m_indexDisplay = true; m_fileDisplay = true; + + m_tileBank = new TileBank(); } TileModel::~TileModel() @@ -182,59 +185,74 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) TileSetNode *tileSet = new TileSetNode(tileSetName); // child for 128x128 tiles - TileTypeNode *tile128= new TileTypeNode(Tile128); + TileTypeNode *tile128= new TileTypeNode( TileConstants::Tile128); tileSet->appendRow(tile128); // child for 256x256 tiles - TileTypeNode *tile256= new TileTypeNode(Tile256); + TileTypeNode *tile256= new TileTypeNode( TileConstants::Tile256); tileSet->appendRow(tile256); // child for transition tiles. - TileTypeNode *tileTrans= new TileTypeNode(TileTransition); + TileTypeNode *tileTrans= new TileTypeNode( TileConstants::TileTransition); tileSet->appendRow(tileTrans); // Add the default transition tiles. // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode( TileModel::TileTransition, transPos, TileDiffuse, QString("empty")); + TileItemNode *transTile= new TileItemNode( TileConstants::TileTransition, transPos, TileConstants::TileDiffuse, QString("empty")); tileTrans->appendRow(transTile); } // child for displacement tiles - TileTypeNode *tileDisp= new TileTypeNode(TileDisplacement); + TileTypeNode *tileDisp= new TileTypeNode( TileConstants::TileDisplacement); tileSet->appendRow(tileDisp); // Add the default displacement tiles. // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode( TileModel::TileDisplacement, dispPos, TileDiffuse, QString("empty")); + TileItemNode *dispTile= new TileItemNode( TileConstants::TileDisplacement, dispPos, TileConstants::TileDiffuse, QString("empty")); tileDisp->appendRow(dispTile); } // Append them in the correct order to the tile set. this->appendRow(tileSet); + m_tileBank->addTileSet(tileSetName); return tileSet; } -TileItemNode *TileModel::createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ) +TileItemNode *TileModel::createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) { return new TileItemNode( type, id, channel, fileName ); } -const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) +TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) +{ + TileItemNode *n = new TileItemNode( type, id, channel, fileName ); + + bool b = m_tileBank->addTileToSet( idx, fileName, n->pixmap( channel ), channel, type ); + if( !b ) + { + delete n; + return NULL; + } + + return n; +} + +const char *TileModel::getTileTypeName(TileConstants::TNodeTileType type) { switch(type) { - case Tile128: + case TileConstants::Tile128: return "128"; - case Tile256: + case TileConstants::Tile256: return "256"; - case TileTransition: + case TileConstants::TileTransition: return "Transition"; - case TileDisplacement: + case TileConstants::TileDisplacement: return "Displacement"; default: break; @@ -242,17 +260,17 @@ const char *TileModel::getTileTypeName(TileModel::TNodeTileType type) return "UNKNOWN"; } -uint32 TileModel::getTileTypeSize(TileModel::TNodeTileType type) +uint32 TileModel::getTileTypeSize(TileConstants::TNodeTileType type) { switch(type) { - case Tile128: + case TileConstants::Tile128: return 128; - case Tile256: + case TileConstants::Tile256: return 256; - case TileTransition: + case TileConstants::TileTransition: return 64; - case TileDisplacement: + case TileConstants::TileDisplacement: return 32; default: break; @@ -287,6 +305,16 @@ void TileModel::clear() removeRows( 0, c ); } +void TileModel::addLand( const QString &name ) +{ + m_tileBank->addLand( name ); +} + +void TileModel::setLandSets( int idx, const QStringList &l ) +{ + m_tileBank->setLandSets( idx, l ); +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index c22a43091..8472e6978 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -21,32 +21,18 @@ #include +#include "tile_constants.h" + class Node; class TileSetNode; class TileItemNode; +class TileBank; class TileModel : public QAbstractItemModel { Q_OBJECT public: - enum TTileChannel - { - TileDiffuse = 0, - TileAdditive = 1, - TileAlpha = 2, - TileChannelCount = 3 - }; - - enum TNodeTileType - { - Tile128 = 0, - Tile256 = 1, - TileTransition = 2, - TileDisplacement = 3, - TileNodeTypeCount = 4 - }; - enum TTileItemRole { TilePixmapRole = Qt::UserRole+1, @@ -87,10 +73,11 @@ public: void swapRows( int a, int b ); TileSetNode *createTileSetNode(QString tileSetName); - static TileItemNode *createItemNode( TileModel::TNodeTileType type, int id, TTileChannel channel, const QString &fileName ); + static TileItemNode *createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); + TileItemNode *createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); - static const char *getTileTypeName(TNodeTileType type); - static uint32 getTileTypeSize(TileModel::TNodeTileType type); + static const char *getTileTypeName(TileConstants::TNodeTileType type); + static uint32 getTileTypeSize(TileConstants::TNodeTileType type); static TTileZoomFactor CurrentZoomFactor; @@ -101,6 +88,9 @@ public: void setTexturePath( const QString &path ){ m_texturePath = path; } QString texturePath() const{ return m_texturePath; } + void addLand( const QString &name ); + void setLandSets( int idx, const QStringList &l ); + public Q_SLOTS: void selectFilenameDisplay(bool selected); void selectIndexDisplay(bool selected); @@ -117,6 +107,8 @@ private: Node *rootItem; QString m_texturePath; + + TileBank *m_tileBank; }; #endif // TILE_MODEL_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 73c8007d8..019745afd 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -28,15 +28,15 @@ class TileBankLoaderPvt public: NL3D::CTileBank bank; - static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) { NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; switch( channel ) { - case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileModel::TileAdditive: b = NL3D::CTile::additive; break; - case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; + case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; } return b; @@ -75,11 +75,11 @@ public: int idx = set->getTile128( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( TileModel::Tile128, i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileConstants::Tile128, i, TileConstants::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) { - tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); } node->appendChild( tin ); @@ -94,11 +94,11 @@ public: int idx = set->getTile256( i ); NL3D::CTile *tile = bank.getTile( idx ); - TileItemNode *tin = new TileItemNode( TileModel::Tile256, i, TileModel::TileDiffuse, "" ); + TileItemNode *tin = new TileItemNode( TileConstants::Tile256, i, TileConstants::TileDiffuse, "" ); - for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) { - tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); } node->appendChild( tin ); @@ -115,9 +115,9 @@ public: TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j <= TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j <= TileConstants::TileAlpha; j++ ) { - tin->setTileFilename( TileModel::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileModel::TTileChannel( i ) ) ).c_str() ); + tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); } } } @@ -130,7 +130,7 @@ public: const char *fn = bank.getDisplacementMap( did ); TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - tin->setTileFilename( TileModel::TileDiffuse, fn ); + tin->setTileFilename( TileConstants::TileDiffuse, fn ); } } diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 65559505a..10f86eb14 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -27,35 +27,35 @@ class TileBankSaverPvt public: NL3D::CTileBank bank; - static NL3D::CTile::TBitmap channelToTBitmap( TileModel::TTileChannel channel ) + static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) { NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; switch( channel ) { - case TileModel::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileModel::TileAdditive: b = NL3D::CTile::additive; break; - case TileModel::TileAlpha: b = NL3D::CTile::alpha; break; + case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; + case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; + case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; } return b; } - NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileModel::TNodeTileType type ) + NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileConstants::TNodeTileType type ) { int idx = -1; int bidx = -1; switch( type ) { - case TileModel::Tile128: + case TileConstants::Tile128: { set->addTile128( idx, bank ); bidx = set->getTile128( idx ); break; } - case TileModel::Tile256: + case TileConstants::Tile256: { set->addTile256( idx, bank ); bidx = set->getTile256( idx ); @@ -71,24 +71,24 @@ public: void addTilesToSet( NL3D::CTileSet *set, TileTypeNode *node ) { - TileModel::TNodeTileType type = node->getTileType(); + TileConstants::TNodeTileType type = node->getTileType(); for( int i = 0; i < node->childCount(); i++ ) { TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); NL3D::CTile *tile = addTileToSet( set, type ); - for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) { - QString fn = tin->getTileFilename( TileModel::TTileChannel( j ) ); - tile->setFileName( channelToTBitmap( TileModel::TTileChannel( j ) ) , fn.toUtf8().constData() ); + QString fn = tin->getTileFilename( TileConstants::TTileChannel( j ) ); + tile->setFileName( channelToTBitmap( TileConstants::TTileChannel( j ) ) , fn.toUtf8().constData() ); } } } void addTilesToSet( NL3D::CTileSet *set, TileSetNode *node ) { - for( int i = TileModel::Tile128; i <= TileModel::Tile256; i++ ) + for( int i = TileConstants::Tile128; i <= TileConstants::Tile256; i++ ) { TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( i ) ); @@ -103,9 +103,9 @@ public: { tileNode = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) { - TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); const NL3D::CTileBorder &border = tileNode->border( channel ); @@ -124,9 +124,9 @@ public: { tileNode = static_cast< TileItemNode* >( node->child( i ) ); - for( int j = TileModel::TileDiffuse; j < TileModel::TileAlpha; j++ ) + for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) { - TileModel::TTileChannel channel = TileModel::TTileChannel( j ); + TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); const NL3D::CTileBorder &border = tileNode->border( channel ); @@ -140,14 +140,14 @@ public: void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) { - TileModel::TTileChannel channel; + TileConstants::TTileChannel channel; NL3D::CTile::TBitmap bm; NL3D::CTileSet::TTransition tr; // Diffuse, Additive - for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) { - channel =TileModel::TTileChannel( i ); + channel =TileConstants::TTileChannel( i ); bm = channelToTBitmap( channel ); tr = NL3D::CTileSet::TTransition( idx ); const NL3D::CTileBorder &border = node->border( channel ); @@ -159,7 +159,7 @@ public: // Alpha { - channel = TileModel::TileAlpha; + channel = TileConstants::TileAlpha; bm = channelToTBitmap( channel ); tr = NL3D::CTileSet::TTransition( idx ); const NL3D::CTileBorder &border = node->border( channel ); @@ -187,7 +187,7 @@ public: void setupDisplacementTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) { set->setDisplacement( NL3D::CTileSet::TDisplacement( idx ), - node->getTileFilename( TileModel::TileDiffuse ).toUtf8().constData(), + node->getTileFilename( TileConstants::TileDiffuse ).toUtf8().constData(), bank ); } From 90b9a592b8fec57e045b641d142424e3894dd880 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:22:44 +0200 Subject: [PATCH 184/220] Most of the functionality works with the new code. --- .../src/plugins/tile_editor/tile_bank.cpp | 367 ++++++++++++++++-- .../src/plugins/tile_editor/tile_bank.h | 30 +- .../tile_editor/tile_editor_main_window.cpp | 160 +++----- .../tile_editor/tile_editor_main_window.h | 7 - .../tile_editor/tile_editor_main_window.ui | 52 --- .../src/plugins/tile_editor/tile_item.cpp | 268 +------------ .../src/plugins/tile_editor/tile_item.h | 12 +- .../src/plugins/tile_editor/tile_model.cpp | 92 ++++- .../src/plugins/tile_editor/tile_model.h | 10 + .../plugins/tile_editor/tilebank_loader.cpp | 139 +------ .../plugins/tile_editor/tilebank_saver.cpp | 251 +----------- 11 files changed, 513 insertions(+), 875 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index f98b4ef38..a44158259 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -3,38 +3,48 @@ #include -bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) -{ - QImage img = pixmap.toImage(); - if( img.format() != QImage::Format_ARGB32 ) - img = img.convertToFormat( QImage::Format_ARGB32 ); - - if( img.format() != QImage::Format_ARGB32 ) - return false; - - int c = img.width() * img.height(); - - const unsigned char *data = img.bits(); - const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); - - NLMISC::CBGRA bgra; - pixels.clear(); - - int i = 0; - while( i < c ) - { - bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; - bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; - bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; - bgra.B = ( idata[ i ] & 0x000000FF ); - pixels.push_back( bgra ); - - i++; - } - - return true; -} +namespace{ + bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) + { + QImage img = pixmap.toImage(); + if( img.format() != QImage::Format_ARGB32 ) + img = img.convertToFormat( QImage::Format_ARGB32 ); + + if( img.format() != QImage::Format_ARGB32 ) + return false; + + int c = img.width() * img.height(); + + const unsigned char *data = img.bits(); + const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); + + NLMISC::CBGRA bgra; + pixels.clear(); + + int i = 0; + while( i < c ) + { + bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; + bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; + bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; + bgra.B = ( idata[ i ] & 0x000000FF ); + pixels.push_back( bgra ); + + i++; + } + + return true; + } + + + NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) + { + return NL3D::CTile::TBitmap( int( channel ) ); + } + + +} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -42,6 +52,124 @@ bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) class TileBankPvt { public: + + bool checkSize( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel, int w, int h ) + { + int width = -1; + + switch( type ) + { + case TileConstants::Tile128: + width = 128; + break; + + case TileConstants::Tile256: + width = 256; + break; + + case TileConstants::TileTransition: + { + if( channel == TileConstants::TileAlpha ) + width = 64; + else + width = 128; + + } + break; + + case TileConstants::TileDisplacement: + width = 32; + break; + } + + if( width == w ) + return true; + + return false; + } + + NL3D::CTileSet::TError checkTile( NL3D::CTileSet *set, int tile, TileConstants::TNodeTileType type, NL3D::CTileBorder &border, NL3D::CTile::TBitmap bitmap, QString &msg ) + { + NL3D::CTileSet::TError error; + + if( bitmap == NL3D::CTile::additive ) + return NL3D::CTileSet::ok; + + if( type == TileConstants::TileDisplacement ) + return NL3D::CTileSet::ok; + + int component; + int pixel; + int idx; + + switch( type ) + { + case TileConstants::Tile128: + error = set->checkTile128( bitmap, border, pixel, component ); + break; + + case TileConstants::Tile256: + error = set->checkTile256( bitmap, border, pixel, component ); + break; + + case TileConstants::TileTransition: + { + if( bitmap != NL3D::CTile::alpha ) + error = set->checkTile128( bitmap, border, pixel, component ); + else + error = set->checkTileTransition( NL3D::CTileSet::TTransition( tile ), bitmap, border, idx, pixel, component ); + + break; + } + } + + if( ( error != NL3D::CTileSet::ok ) && ( error != NL3D::CTileSet::addFirstA128128 ) ) + { + static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; + + msg = NL3D::CTileSet::getErrorMessage( error ); + msg += "\n"; + msg += " pixel %1 component %2"; + msg = msg.arg( pixel ); + msg = msg.arg( comp[ component ] ); + } + + return error; + } + + void setTile( NL3D::CTileSet *set, int tile, int rotation, const QString &name, NL3D::CTile::TBitmap bm, TileConstants::TNodeTileType type, NL3D::CTileBorder &border ) + { + switch( type ) + { + case TileConstants::Tile128: + set->setTile128( tile, name.toUtf8().constData(), bm, m_bank ); + break; + + case TileConstants::Tile256: + set->setTile256( tile, name.toUtf8().constData(), bm, m_bank ); + break; + + case TileConstants::TileTransition: + if( bm != NL3D::CTile::alpha ) + set->setTileTransition( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), bm, m_bank, border ); + else + set->setTileTransitionAlpha( NL3D::CTileSet::TTransition( tile ), name.toUtf8().constData(), m_bank, border, rotation ); + break; + + case TileConstants::TileDisplacement: + set->setDisplacement( NL3D::CTileSet::TDisplacement( tile ), name.toUtf8().constData(), m_bank ); + break; + } + + } + + void buildBorder( QPixmap &pm, NL3D::CTileBorder &border ) + { + std::vector< NLMISC::CBGRA > pixels; + pixmapToCBGRA( pm, pixels ); + border.set( pm.width(), pm.height(), pixels ); + } + NL3D::CTileBank m_bank; }; @@ -52,6 +180,7 @@ public: TileBank::TileBank() { m_pvt = new TileBankPvt(); + resetError(); } TileBank::~TileBank() @@ -65,11 +194,51 @@ void TileBank::addTileSet( const QString &name ) NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( 0 ); } +void TileBank::removeTileSet( int idx ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return; + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + land->removeTileSet( set->getName() ); + } + + m_pvt->m_bank.removeTileSet( idx ); +} + +void TileBank::renameTileSet( int idx, const QString &newName ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + if( set == NULL ) + return; + + std::string oldName = set->getName(); + set->setName( newName.toUtf8().constData() ); + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + land->removeTileSet( oldName ); + land->addTileSet( newName.toUtf8().constData() ); + } + +} + void TileBank::addLand( const QString &name ) { m_pvt->m_bank.addLand( name.toUtf8().constData() ); } +void TileBank::removeLand( int idx ) +{ + m_pvt->m_bank.removeLand( idx ); +} + void TileBank::setLandSets( int idx, const QStringList &l ) { NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); @@ -82,29 +251,145 @@ void TileBank::setLandSets( int idx, const QStringList &l ) } } -bool TileBank::addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +void TileBank::getLandSets( int idx, QStringList &l ) { - NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( idx ); + NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); + if( land == NULL ) + return; + + l.clear(); + + std::set< std::string> sets = land->getTileSets(); + std::set< std::string >::const_iterator itr = sets.begin(); + while( itr != sets.end() ) + { + l.push_back( itr->c_str() ); + ++itr; + } +} + +bool TileBank::addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + resetError(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( setIdx ); + + int tile; + switch( type ) + { + case TileConstants::Tile128: set->addTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->addTile256( tile, m_pvt->m_bank ); break; + } + + bool b = setTile( setIdx, tile, name, pixmap, channel, type ); + if( b ) + return true; + + // There was an error, roll back + switch( type ) + { + case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile128( tile, m_pvt->m_bank ); break; + } + + return false; +} + +void TileBank::removeTile( int ts, int type, int tile ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); + + switch( type ) + { + case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; + } +} + +bool TileBank::setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ) +{ + resetError(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileset ); if( set == NULL ) return false; QPixmap pm = pixmap.value< QPixmap >(); if( pm.isNull() ) + { + m_hasError = true; + m_lastError = "Failed to load image."; return false; + } if( pm.width() != pm.height() ) + { + m_hasError = true; + m_lastError = "Image isn't square."; return false; + } - std::vector< NLMISC::CBGRA > pixels; - pixmapToCBGRA( pm, pixels ); - - int tile; - set->addTile128( tile, m_pvt->m_bank ); + if( !m_pvt->checkSize( type, channel, pm.width(), pm.height() ) ) + { + m_hasError = true; + m_lastError = "Invalid image size."; + return false; + } NL3D::CTileBorder border; - border.set( pm.width(), pm.height(), pixels ); + m_pvt->buildBorder( pm, border ); + QString msg; + NL3D::CTileSet::TError error = m_pvt->checkTile( set, tile, type, border, channelToTBitmap( channel ), msg ); + + // Tile checks out fine, set it + if( ( error == NL3D::CTileSet::ok ) || ( error == NL3D::CTileSet::addFirstA128128 ) ) + { + if( error == NL3D::CTileSet::addFirstA128128 ) + set->setBorder( channelToTBitmap( channel ), border ); + + m_pvt->setTile( set, tile, 0 /* rotation */, name, channelToTBitmap( channel ), type, border ); + + return true; + } + + setError( msg ); + + return false; +} + +void TileBank::replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ) +{ + setTile( ts, tile, name, pixmap, channel, TileConstants::TNodeTileType( type ) ); +} + +void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( ts ); + + int tileId; + + NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); + switch( type ) + { + case TileConstants::Tile128: + set->clearTile128( tile, bm, m_pvt->m_bank ); + break; + + case TileConstants::Tile256: + set->clearTile256( tile, bm, m_pvt->m_bank ); + break; + + case TileConstants::TileTransition: + set->clearTransition( NL3D::CTileSet::TTransition( tile ), bm, m_pvt->m_bank ); + break; + + case TileConstants::TileDisplacement: + set->clearDisplacement( NL3D::CTileSet::TDisplacement( tile ), m_pvt->m_bank ); + break; + } + +} + - return true; -} \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index ab4d28ee8..d81ae694b 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -16,13 +16,37 @@ public: ~TileBank(); void addTileSet( const QString &name ); - void addLand( const QString &name ); - void setLandSets( int idx, const QStringList &l ); + void removeTileSet( int idx ); + void renameTileSet( int idx, const QString &newName ); - bool addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void addLand( const QString &name ); + void removeLand( int idx ); + void setLandSets( int idx, const QStringList &l ); + void getLandSets( int idx, QStringList &l ); + + bool addTile( int setIdx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void removeTile( int ts, int type, int tile ); + bool setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); + void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + bool hasError() const{ return m_hasError; } + QString getLastError() const{ return m_lastError; } + void resetError(){ + m_hasError = false; + m_lastError = ""; + } + + void setError( const QString &msg ) + { + m_hasError = true; + m_lastError = msg; + } private: TileBankPvt *m_pvt; + QString m_lastError; + bool m_hasError; }; #endif diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index dd3ece7c7..dffa7a61a 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -110,8 +110,6 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect(m_ui->tileSetAddTB, SIGNAL(clicked()), this, SLOT(onTileSetAdd())); connect(m_ui->tileSetDeleteTB, SIGNAL(clicked()), this, SLOT(onTileSetDelete())); connect(m_ui->tileSetEditTB, SIGNAL(clicked()), this, SLOT(onTileSetEdit())); - connect(m_ui->tileSetUpTB, SIGNAL(clicked()), this, SLOT(onTileSetUp())); - connect(m_ui->tileSetDownTB, SIGNAL(clicked()), this, SLOT(onTileSetDown())); connect(m_ui->landAddTB, SIGNAL(clicked()), this, SLOT(onLandAdd())); connect(m_ui->landRemoveTB, SIGNAL(clicked()), this, SLOT(onLandRemove())); @@ -251,7 +249,8 @@ void TileEditorMainWindow::saveAs( const QString &fn ) } TileBankSaver saver; - bool ok = saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool ok = true; + //saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); if( !ok ) { @@ -272,7 +271,8 @@ void TileEditorMainWindow::open() return; TileBankLoader loader; - bool b = loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool b = true; + //loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); if( !b ) { @@ -398,10 +398,7 @@ void TileEditorMainWindow::onTileSetDelete() QString set = reinterpret_cast< TileSetNode* >( idx.internalPointer() )->getTileSetName(); - TileModel *model = static_cast(m_ui->tileSetLV->model()); - bool ok = model->removeRow( idx.row() ); - - onTileSetRemoved( set ); + m_tileModel->removeTileSet( idx.row() ); } void TileEditorMainWindow::onTileSetEdit() @@ -438,46 +435,7 @@ void TileEditorMainWindow::onTileSetEdit() node->setTileSetName( newName ); m_ui->tileSetLV->reset(); - onTileSetRenamed( oldName, newName ); -} - -void TileEditorMainWindow::onTileSetUp() -{ - QModelIndex idx = m_ui->tileSetLV->currentIndex(); - if( !idx.isValid() ) - return; - - if( idx.row() == 0 ) - return; - - TileModel *model = static_cast(m_ui->tileSetLV->model()); - if( model->rowCount() < 2 ) - return; - - int r = idx.row(); - model->swapRows( r, r - 1 ); - - m_ui->tileSetLV->reset(); - m_ui->tileSetLV->setCurrentIndex( model->index( r - 1, 0 ) ); -} - -void TileEditorMainWindow::onTileSetDown() -{ - QModelIndex idx = m_ui->tileSetLV->currentIndex(); - if( !idx.isValid() ) - return; - - TileModel *model = static_cast(m_ui->tileSetLV->model()); - if( model->rowCount() < idx.row() ) - return; - if( model->rowCount() < 2 ) - return; - - int r = idx.row(); - model->swapRows( r, r + 1 ); - - m_ui->tileSetLV->reset(); - m_ui->tileSetLV->setCurrentIndex( model->index( r + 1, 0 ) ); + m_tileModel->renameTileSet( idx.row(), newName ); } void TileEditorMainWindow::onLandAdd() @@ -503,9 +461,7 @@ void TileEditorMainWindow::onLandAdd() m_ui->landLW->addItem( name ); - Land l; - l.name = name; - m_lands.push_back( l ); + m_tileModel->addLand( name ); } void TileEditorMainWindow::onLandRemove() @@ -526,8 +482,7 @@ void TileEditorMainWindow::onLandRemove() delete item; - QList< Land >::iterator itr = m_lands.begin() + idx; - m_lands.erase( itr ); + m_tileModel->removeLand( idx ); } void TileEditorMainWindow::onLandEdit() @@ -549,10 +504,12 @@ void TileEditorMainWindow::onLandEdit() } int r = m_ui->landLW->currentRow(); - Land &l = m_lands[ r ]; + + QStringList sts; + m_tileModel->getLandSets( r, sts ); LandEditDialog d; - d.setSelectedTileSets( l.tilesets ); + d.setSelectedTileSets( sts ); d.setTileSets( ts ); int result = d.exec(); @@ -560,10 +517,10 @@ void TileEditorMainWindow::onLandEdit() return; // Update the tileset of the land - ts.clear(); - d.getSelectedTileSets( ts ); - l.tilesets.clear(); - l.tilesets = ts; + sts.clear(); + d.getSelectedTileSets( sts ); + + m_tileModel->setLandSets( r, sts ); } void TileEditorMainWindow::onChooseVegetation() @@ -720,37 +677,26 @@ void TileEditorMainWindow::onActionAddTile(int tabId) TileConstants::TNodeTileType type = tabToType( tabId ); QStringListIterator itr( fileNames ); + QString error; + while( itr.hasNext() ) { TileItemNode *newNode = m_tileModel->createItemNode( setId, type, c, TileConstants::TileDiffuse, itr.next() ); if( newNode == NULL ) { + if( m_tileModel->hasError() ) + error = m_tileModel->getLastError(); + int reply = QMessageBox::question( this, tr( "Error adding tile" ), - tr( "Failed to create tile!\nContinue?" ), + error + "\nContinue?", QMessageBox::Yes, QMessageBox::No ); if( reply != QMessageBox::Yes ) break; else continue; } - - - if( newNode->hasError() ) - { - QString error = newNode->getLastError(); - error += "\nContinue?"; - - int reply = QMessageBox::question( this, - tr( "Error adding tile" ), - error, - QMessageBox::Yes, QMessageBox::No ); - if( reply != QMessageBox::Yes ) - break; - else - continue; - } - + n->appendRow( newNode ); c++; } @@ -777,12 +723,13 @@ void TileEditorMainWindow::onActionDeleteTile( int tabId ) return; } - int row = idx.row(); + QModelIndex tsidx = m_ui->tileSetLV->currentIndex(); + if( !tsidx.isValid() ) + return; + int ts = tsidx.row(); + int tile = idx.row(); - QModelIndex parent = idx.parent(); - lv->model()->removeRow( row, parent ); - - //lv->reset(); + m_tileModel->removeTile( ts, tabId, tile ); } void TileEditorMainWindow::onActionDeleteImage( int tabId ) @@ -798,13 +745,25 @@ void TileEditorMainWindow::onActionDeleteImage( int tabId ) return; } + QModelIndex tsidx = m_ui->tileSetLV->currentIndex(); + if( !tsidx.isValid() ) + return; + int ts = tsidx.row(); + TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileItemNode::displayChannel(), "" ); + int tile = n->id(); + + m_tileModel->clearImage( ts, tabId, tile, TileItemNode::displayChannel() ); } void TileEditorMainWindow::onActionReplaceImage( int tabId ) { QListView *lv = getListViewByTab( tabId ); + + QModelIndex tsidx = m_ui->tileSetLV->currentIndex(); + if( !tsidx.isValid() ) + return; + int set = tsidx.row(); QModelIndex idx = lv->currentIndex(); if( !idx.isValid() ) @@ -823,41 +782,22 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) return; TileItemNode *n = reinterpret_cast< TileItemNode* >( idx.internalPointer() ); - n->setTileFilename( TileItemNode::displayChannel(), fileName ); -} + int tile = n->id(); -void TileEditorMainWindow::onTileSetRemoved( const QString &set ) -{ - int c = m_lands.count(); - for( int i = 0; i < c; i++ ) + m_tileModel->replaceImage( set, tabId, tile, TileItemNode::displayChannel(), fileName ); + if( m_tileModel->hasError() ) { - Land &land = m_lands[ i ]; - land.tilesets.removeAll( set ); - } -} - -void TileEditorMainWindow::onTileSetRenamed( const QString &oldname, const QString &newname ) -{ - int c = m_lands.count(); - for( int i = 0; i < c; i++ ) - { - Land &land = m_lands[ i ]; - int idx = land.tilesets.indexOf( oldname ); - if( idx < 0 ) - continue; - - land.tilesets[ idx ] = newname; + QString error = m_tileModel->getLastError(); + QMessageBox::information( this, + tr( "Error replacing tile image" ), + error ); } } void TileEditorMainWindow::onTileBankLoaded() { m_ui->landLW->clear(); - QListIterator< Land > itr( m_lands ); - while( itr.hasNext() ) - { - m_ui->landLW->addItem( itr.next().name ); - } + // load lands m_ui->listView128->reset(); m_ui->listView256->reset(); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 44b2c9869..1ec80cd96 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -25,8 +25,6 @@ #include #include -#include "land.h" - namespace Ui { class TileEditorMainWindow; } @@ -59,8 +57,6 @@ private Q_SLOTS: void onTileSetAdd(); void onTileSetDelete(); void onTileSetEdit(); - void onTileSetUp(); - void onTileSetDown(); void onLandAdd(); void onLandRemove(); @@ -89,8 +85,6 @@ private: void onActionDeleteImage(int tabId); void onActionReplaceImage(int tabId); - void onTileSetRemoved( const QString &set ); - void onTileSetRenamed( const QString &oldname, const QString &newname ); void onTileBankLoaded(); void updateTab(); @@ -127,7 +121,6 @@ private: }; QString m_fileName; - QList< Land > m_lands; }; #endif // TILE_EDITOR_MAIN_WINDOW_H diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui index 8974570a1..08d14ca79 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.ui @@ -426,58 +426,6 @@ Tile Sets - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - ... - - - - :/movementIcons/images/up.png:/movementIcons/images/up.png - - - - - - - ... - - - - :/movementIcons/images/down.png:/movementIcons/images/down.png - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 56f621dee..e952d8d20 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -18,12 +18,8 @@ #include "tile_item.h" -//#include "tile_widget.h" - #include -#include - Node::Node() : m_parentItem(0) { } @@ -266,210 +262,14 @@ void TileTypeNode::reindex() /////////////////////////////////////////////////// -NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) -{ - NL3D::CTile::TBitmap bm; - - switch( channel ) - { - case TileConstants::TileDiffuse: bm = NL3D::CTile::diffuse; break; - case TileConstants::TileAdditive: bm = NL3D::CTile::additive; break; - case TileConstants::TileAlpha: bm = NL3D::CTile::alpha; break; - } - - return bm; -} - class TileItemNodePvt { public: TileItemNodePvt() { - for( int i = 0; i < TileConstants::TileChannelCount; i++ ) - m_borderFirst[ i ] = false; - - m_id = -1; - m_alphaRot = 0; } - bool pixmapToCBGRA( QPixmap &pixmap, std::vector< NLMISC::CBGRA >& pixels ) - { - QImage img = pixmap.toImage(); - if( img.format() != QImage::Format_ARGB32 ) - img = img.convertToFormat( QImage::Format_ARGB32 ); - - if( img.format() != QImage::Format_ARGB32 ) - return false; - - int c = img.width() * img.height(); - - const unsigned char *data = img.bits(); - const unsigned int *idata = reinterpret_cast< const unsigned int* >( data ); - - NLMISC::CBGRA bgra; - pixels.clear(); - - int i = 0; - while( i < c ) - { - bgra.A = ( idata[ i ] & 0xFF000000 ) >> 24; - bgra.R = ( idata[ i ] & 0x00FF0000 ) >> 16; - bgra.G = ( idata[ i ] & 0x0000FF00 ) >> 8; - bgra.B = ( idata[ i ] & 0x000000FF ); - pixels.push_back( bgra ); - - i++; - } - - return true; - } - - int getWidthForType( TileConstants::TNodeTileType type, TileConstants::TTileChannel channel ) - { - int width = -1; - - switch( type ) - { - case TileConstants::Tile128: width = 128; break; - case TileConstants::Tile256: width = 256; break; - case TileConstants::TileTransition: - { - if( channel != TileConstants::TileAlpha ) - width = 128; - break; - } - - case TileConstants::TileDisplacement: width = 32; break; - } - - return width; - } - - NL3D::CTileSet::TError checkTile( TileConstants::TTileChannel channel ) - { - if( m_type == TileConstants::TileDisplacement ) - return NL3D::CTileSet::ok; - - if( channel == TileConstants::TileAdditive ) - return NL3D::CTileSet::ok; - - int pixel; - int component; - int index; - - NL3D::CTileSet set; - NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); - - NL3D::CTileSet::TError error = NL3D::CTileSet::ok; - - switch( m_type ) - { - case TileConstants::Tile128: - error = set.checkTile128( bm, m_border[ channel ], pixel, component ); - break; - case TileConstants::Tile256: - error = set.checkTile256( bm, m_border[ channel ], pixel, component ); - break; - case TileConstants::TileTransition: - if( channel != TileConstants::TileAlpha ) - error = set.checkTile128( bm, m_border[ channel ], pixel, component ); - else - error = set.checkTileTransition( NL3D::CTileSet::TTransition( m_id ), bm, m_border[ channel ], index, pixel, component ); - break; - } - - if( error == NL3D::CTileSet::ok ) - return NL3D::CTileSet::ok; - if( error == NL3D::CTileSet::addFirstA128128 ) - return NL3D::CTileSet::addFirstA128128; - - static const char* comp[]={"Red", "Green", "Blue", "Alpha", ""}; - - if( error != NL3D::CTileSet::ok ) - { - m_lastError = "ERROR: "; - m_lastError += NL3D::CTileSet::getErrorMessage( error ); - m_lastError += "\n"; - - switch( m_type ) - { - case TileConstants::Tile128: - case TileConstants::Tile256: - m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); - break; - - case TileConstants::TileTransition: - if( channel != TileConstants::TileAlpha ) - { - m_lastError += QString( "pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); - } - else - { - if ((error==NL3D::CTileSet::topInterfaceProblem)||(error==NL3D::CTileSet::bottomInterfaceProblem)|| - (error==NL3D::CTileSet::leftInterfaceProblem)||(error==NL3D::CTileSet::rightInterfaceProblem)|| - (error==NL3D::CTileSet::topBottomNotTheSame)||(error==NL3D::CTileSet::rightLeftNotTheSame) - ||(error==NL3D::CTileSet::topInterfaceProblem)) - { - if( index != -1 ) - { - m_lastError += QString( "tile: %1 pixel: %2 component: %3" ).arg( index ).arg( pixel ).arg( comp[ component ] ); - } - else - { - m_lastError += QString( "incompatible with a 128 tile, pixel: %1 component: %2" ).arg( pixel ).arg( comp[ component ] ); - } - } - - } - break; - } - } - - return error; - } - - bool checkPixmap( TileConstants::TTileChannel channel, QPixmap &pixmap ) - { - int w = pixmap.width(); - int h = pixmap.height(); - - if( w != h ) - { - m_lastError = QObject::tr( "Not a square texture." ); - return false; - } - - int width = getWidthForType( m_type, channel ); - - if( width != -1 ) - { - if( width != w ) - { - m_lastError = QObject::tr( "Not the proper size." ); - return false; - } - } - - std::vector< NLMISC::CBGRA > pixels; - - pixmapToCBGRA( pixmap, pixels ); - - m_border[ channel ].set( w, h, pixels ); - - NL3D::CTileSet::TError error = checkTile( channel ); - if( error == NL3D::CTileSet::addFirstA128128 ) - { - m_borderFirst[ channel ] = true; - return true; - } - - if( error != NL3D::CTileSet::ok ) - return false; - - return true; - } - bool loadImage( TileConstants::TTileChannel channel, const QString &fn, bool empty = false ) { QPixmap temp; @@ -477,20 +277,9 @@ public: if( !b ) { - m_lastError = QObject::tr( "Cannot open file %1" ).arg( fn ); return false; } - m_borderFirst[ channel ] = false; - - /* - if( !empty ) - { - if( !checkPixmap( channel, temp ) ) - return false; - } - */ - pixmaps[ channel ] = temp; return true; @@ -505,26 +294,8 @@ public: return pixmaps[ channel ]; } - void setType( TileConstants::TNodeTileType type ){ m_type = type; } - void setId( int id ){ m_id = id; } - int id() const{ return m_id; } - - QString getLastError() const{ return m_lastError; } - bool borderFirst( TileConstants::TTileChannel channel ) const{ return m_borderFirst[ channel ]; } - - const NL3D::CTileBorder &border( TileConstants::TTileChannel channel ){ return m_border[ channel ]; } - - int alphaRot() const{ return m_alphaRot; } - void setAlphaRot( int rot ){ m_alphaRot = rot; } - private: QPixmap pixmaps[ TileConstants::TileChannelCount ]; - TileConstants::TNodeTileType m_type; - NL3D::CTileBorder m_border[ TileConstants::TileChannelCount ]; - int m_id; - QString m_lastError; - bool m_borderFirst[ TileConstants::TileChannelCount ]; - int m_alphaRot; }; TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; @@ -532,13 +303,11 @@ int TileItemNode::s_alphaRot = 0; TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent) { + m_id = tileId; m_parentItem = parent; //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); pvt = new TileItemNodePvt(); - pvt->setType( type ); - pvt->setId( tileId ); - m_hasError = false; setTileFilename( channel, filename ); @@ -563,7 +332,6 @@ bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString empty = true; } - pvt->setAlphaRot( s_alphaRot ); bool b = pvt->loadImage( channel, fn, empty ); m_hasError = !b; if( !b ) @@ -583,36 +351,6 @@ QString TileItemNode::getTileFilename(TileConstants::TTileChannel channel) return itr.value(); } -void TileItemNode::setId( int id ) -{ - pvt->setId( id ); -} - -int TileItemNode::id() const -{ - return pvt->id(); -} - -QString TileItemNode::getLastError() const -{ - return pvt->getLastError(); -} - -bool TileItemNode::borderFirst( TileConstants::TTileChannel channel ) const -{ - return pvt->borderFirst( channel ); -} - -const NL3D::CTileBorder& TileItemNode::border( TileConstants::TTileChannel channel ) const -{ - return pvt->border( channel ); -} - -int TileItemNode::alphaRot() const -{ - return pvt->alphaRot(); -} - QVariant TileItemNode::data(int column, int role) const { QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; @@ -647,11 +385,11 @@ QVariant TileItemNode::data(int column, int role) const } else if(role == TileModel::TileIndexRole) { - return QVariant("("+QString::number(pvt->id())+")"); + return QVariant("("+QString::number(m_id)+")"); } else if(role == TileModel::TileFilenameIndexRole) { - return QVariant(tileFilename + " ("+QString::number(pvt->id())+")"); + return QVariant(tileFilename + " ("+QString::number(m_id)+")"); } return QVariant(); diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 342846ab8..2600f47d4 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -120,19 +120,13 @@ public: int columnCount() const; bool setTileFilename(TileConstants::TTileChannel channel, QString filename); QString getTileFilename(TileConstants::TTileChannel channel); - void setId( int id ); - int id() const; - QString getLastError() const; - bool borderFirst( TileConstants::TTileChannel channel ) const; - const NL3D::CTileBorder& border( TileConstants::TTileChannel channel ) const; - int alphaRot() const; + void setId( int id ){ m_id = id; } + int id() const{ return m_id; } static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } static void setAlphaRot( int rot ){ s_alphaRot = rot; } - bool hasError() const{ return m_hasError; } - QVariant pixmap( TileConstants::TTileChannel channel ) const; private: @@ -142,6 +136,8 @@ private: static TileConstants::TTileChannel s_displayChannel; static int s_alphaRot; + int m_id; + TileItemNodePvt *pvt; bool m_hasError; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index fbdd07223..862b03bce 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -232,7 +232,7 @@ TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType t { TileItemNode *n = new TileItemNode( type, id, channel, fileName ); - bool b = m_tileBank->addTileToSet( idx, fileName, n->pixmap( channel ), channel, type ); + bool b = m_tileBank->addTile( idx, fileName, n->pixmap( channel ), channel, type ); if( !b ) { delete n; @@ -310,11 +310,101 @@ void TileModel::addLand( const QString &name ) m_tileBank->addLand( name ); } +void TileModel::removeLand( int idx ) +{ + m_tileBank->removeLand( idx ); +} + void TileModel::setLandSets( int idx, const QStringList &l ) { m_tileBank->setLandSets( idx, l ); } +void TileModel::getLandSets( int idx, QStringList &l ) +{ + m_tileBank->getLandSets( idx, l ); +} + +void TileModel::removeTileSet( int idx ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( idx ) ); + if( set == NULL ) + return; + + removeRow( idx ); + + m_tileBank->removeTileSet( idx ); +} + +void TileModel::renameTileSet( int idx, const QString &newName ) +{ + m_tileBank->renameTileSet( idx, newName ); +} + +void TileModel::removeTile( int ts, int type, int tile ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( ts ) ); + if( set == NULL ) + return; + + TileTypeNode *typeNode = static_cast< TileTypeNode* >( set->child( type ) ); + if( typeNode == NULL ) + return; + + TileItemNode *tileNode = static_cast< TileItemNode* >( typeNode->child( tile ) ); + if( tileNode == NULL ) + return; + + QModelIndex tileIdx = createIndex( tile, 0, tileNode ); + removeRow( tile, tileIdx.parent() ); + + m_tileBank->removeTile( ts, type, tile ); +} + +bool TileModel::replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ) +{ + Node *set = rootItem->child( ts ); + Node *tn = set->child( type ); + Node *n = tn->child( tile ); + + TileItemNode *tin = static_cast< TileItemNode* >( n ); + QString old = tin->getTileFilename( channel ); + + bool b = tin->setTileFilename( channel, name ); + if( !b ) + return false; + + m_tileBank->replaceImage( ts, type, tile, channel, name, tin->pixmap( channel ) ); + if( m_tileBank->hasError() ) + { + tin->setTileFilename( channel, old ); + return false; + } + + return true; +} + +void TileModel::clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ) +{ + Node *set = rootItem->child( ts ); + Node *tn = set->child( type ); + Node *n = tn->child( tile ); + + TileItemNode *tin = static_cast< TileItemNode* >( n ); + tin->setTileFilename( channel, "" ); + + m_tileBank->clearImage( ts, type, tile, channel ); +} + +QString TileModel::getLastError() const{ + return m_tileBank->getLastError(); +} + +bool TileModel::hasError() const +{ + return m_tileBank->hasError(); +} + void TileModel::selectFilenameDisplay(bool selected) { m_fileDisplay = selected; diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 8472e6978..d2776bc86 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -89,7 +89,17 @@ public: QString texturePath() const{ return m_texturePath; } void addLand( const QString &name ); + void removeLand( int idx ); + void removeTileSet( int idx ); + void renameTileSet( int idx, const QString &newName ); void setLandSets( int idx, const QStringList &l ); + void getLandSets( int idx, QStringList &l ); + void removeTile( int ts, int type, int tile ); + bool replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ); + void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + QString getLastError() const; + bool hasError() const; public Q_SLOTS: void selectFilenameDisplay(bool selected); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 019745afd..945fd0908 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -26,138 +26,6 @@ class TileBankLoaderPvt { public: - NL3D::CTileBank bank; - - static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) - { - NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; - - switch( channel ) - { - case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; - case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; - } - - return b; - } - - void loadLands( QList< Land > &lands ) - { - lands.clear(); - - Land l; - - int c = bank.getLandCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileLand *land = bank.getLand( i ); - l.name = land->getName().c_str(); - - - std::set< std::string > sets = land->getTileSets(); - std::set< std::string >::const_iterator itr = sets.begin(); - while( itr != sets.end() ) - { - l.tilesets.push_back( itr->c_str() ); - ++itr; - } - - lands.push_back( l ); - } - } - - void loadTiles128( NL3D::CTileSet *set, TileTypeNode *node ) - { - int c = set->getNumTile128(); - for( int i = 0; i < c; i++ ) - { - int idx = set->getTile128( i ); - NL3D::CTile *tile = bank.getTile( idx ); - - TileItemNode *tin = new TileItemNode( TileConstants::Tile128, i, TileConstants::TileDiffuse, "" ); - - for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) - { - tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); - } - - node->appendChild( tin ); - } - } - - void loadTiles256( NL3D::CTileSet *set, TileTypeNode *node ) - { - int c = set->getNumTile256(); - for( int i = 0; i < c; i++ ) - { - int idx = set->getTile256( i ); - NL3D::CTile *tile = bank.getTile( idx ); - - TileItemNode *tin = new TileItemNode( TileConstants::Tile256, i, TileConstants::TileDiffuse, "" ); - - for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) - { - tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); - } - - node->appendChild( tin ); - } - } - - void loadTilesTransition( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < NL3D::CTileSet::count; i++ ) - { - const NL3D::CTileSetTransition *tr = set->getTransition( i ); - int idx = tr->getTile(); - NL3D::CTile *tile = bank.getTile( idx ); - - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - - for( int j = TileConstants::TileDiffuse; j <= TileConstants::TileAlpha; j++ ) - { - tin->setTileFilename( TileConstants::TTileChannel( i ), tile->getRelativeFileName( channelToTBitmap( TileConstants::TTileChannel( i ) ) ).c_str() ); - } - } - } - - void loadTilesDisplacement( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < NL3D::CTileSet::CountDisplace; i++ ) - { - uint did = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( i ) ); - const char *fn = bank.getDisplacementMap( did ); - - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - tin->setTileFilename( TileConstants::TileDiffuse, fn ); - } - } - - void loadTileSet( NL3D::CTileSet *set, TileSetNode *node ) - { - loadTiles128( set, static_cast< TileTypeNode* >( node->child( 0 ) ) ); - loadTiles256( set, static_cast< TileTypeNode* >( node->child( 1 ) ) ); - loadTilesTransition( set, static_cast< TileTypeNode* >( node->child( 2 ) ) ); - loadTilesDisplacement( set, static_cast< TileTypeNode* >( node->child( 3 ) ) ); - - node->setOriented( set->getOriented() ); - - node->setVegetSet( set->getTileVegetableDescFileName().c_str() ); - } - - void loadTileSets( TileModel *model ) - { - model->clear(); - - int c = bank.getTileSetCount(); - for( int i = 0; i < c; i++ ) - { - NL3D::CTileSet *set = bank.getTileSet( i ); - TileSetNode *node = model->createTileSetNode( set->getName().c_str() ); - loadTileSet( set, node ); - } - } }; @@ -178,12 +46,7 @@ bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > if( !file.open( filename, false ) ) return false; - p->bank.serial( file ); - - p->loadLands( lands ); - p->loadTileSets( model ); - - model->setTexturePath( p->bank.getAbsPath().c_str() ); + //p->bank.serial( file ); file.close(); diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 10f86eb14..15e31d141 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -25,251 +25,7 @@ class TileBankSaverPvt { public: - NL3D::CTileBank bank; - static NL3D::CTile::TBitmap channelToTBitmap( TileConstants::TTileChannel channel ) - { - NL3D::CTile::TBitmap b = NL3D::CTile::bitmapCount; - - switch( channel ) - { - case TileConstants::TileDiffuse: b = NL3D::CTile::diffuse; break; - case TileConstants::TileAdditive: b = NL3D::CTile::additive; break; - case TileConstants::TileAlpha: b = NL3D::CTile::alpha; break; - } - - return b; - } - - NL3D::CTile* addTileToSet( NL3D::CTileSet *set, TileConstants::TNodeTileType type ) - { - int idx = -1; - int bidx = -1; - - switch( type ) - { - case TileConstants::Tile128: - { - set->addTile128( idx, bank ); - bidx = set->getTile128( idx ); - break; - } - - case TileConstants::Tile256: - { - set->addTile256( idx, bank ); - bidx = set->getTile256( idx ); - break; - } - } - - if( idx == -1 ) - return NULL; - - return bank.getTile( bidx ); - } - - void addTilesToSet( NL3D::CTileSet *set, TileTypeNode *node ) - { - TileConstants::TNodeTileType type = node->getTileType(); - - for( int i = 0; i < node->childCount(); i++ ) - { - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - NL3D::CTile *tile = addTileToSet( set, type ); - - for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) - { - QString fn = tin->getTileFilename( TileConstants::TTileChannel( j ) ); - tile->setFileName( channelToTBitmap( TileConstants::TTileChannel( j ) ) , fn.toUtf8().constData() ); - } - } - } - - void addTilesToSet( NL3D::CTileSet *set, TileSetNode *node ) - { - for( int i = TileConstants::Tile128; i <= TileConstants::Tile256; i++ ) - { - TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( i ) ); - - addTilesToSet( set, tn ); - } - } - - void setupTiles128( NL3D::CTileSet *set, TileTypeNode *node ) - { - TileItemNode *tileNode = NULL; - for( int i = 0; i < node->childCount(); i++ ) - { - tileNode = static_cast< TileItemNode* >( node->child( i ) ); - - for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) - { - TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); - NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); - const NL3D::CTileBorder &border = tileNode->border( channel ); - - if( tileNode->borderFirst( channel ) ) - set->setBorder( bm, border ); - - set->setTile128( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); - } - } - } - - void setupTiles256( NL3D::CTileSet *set, TileTypeNode *node ) - { - TileItemNode *tileNode = NULL; - for( int i = 0; i < node->childCount(); i++ ) - { - tileNode = static_cast< TileItemNode* >( node->child( i ) ); - - for( int j = TileConstants::TileDiffuse; j < TileConstants::TileAlpha; j++ ) - { - TileConstants::TTileChannel channel = TileConstants::TTileChannel( j ); - NL3D::CTile::TBitmap bm = channelToTBitmap( channel ); - const NL3D::CTileBorder &border = tileNode->border( channel ); - - if( tileNode->borderFirst( channel ) ) - set->setBorder( bm, border ); - - set->setTile256( i, tileNode->getTileFilename( channel ).toUtf8().constData(), bm, bank ); - } - } - } - - void setupTransitionTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) - { - TileConstants::TTileChannel channel; - NL3D::CTile::TBitmap bm; - NL3D::CTileSet::TTransition tr; - - // Diffuse, Additive - for( int i = TileConstants::TileDiffuse; i < TileConstants::TileAlpha; i++ ) - { - channel =TileConstants::TTileChannel( i ); - bm = channelToTBitmap( channel ); - tr = NL3D::CTileSet::TTransition( idx ); - const NL3D::CTileBorder &border = node->border( channel ); - - if( node->borderFirst( channel ) ) - set->setBorder( bm, border ); - set->setTileTransition( tr, node->getTileFilename( channel ).toUtf8().constData(), bm, bank, border ); - } - - // Alpha - { - channel = TileConstants::TileAlpha; - bm = channelToTBitmap( channel ); - tr = NL3D::CTileSet::TTransition( idx ); - const NL3D::CTileBorder &border = node->border( channel ); - int rot = node->alphaRot(); - - set->setTileTransitionAlpha( tr, node->getTileFilename( channel ).toUtf8().constData(), bank, border, rot ); - } - } - - void setupTransitionTiles( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < node->childCount(); i++ ) - { - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - setupTransitionTile( set, tin, i ); - } - } - - void setupTransitionTiles( NL3D::CTileSet *set, TileSetNode *node ) - { - TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 2 ) ); - setupTransitionTiles( set, tn ); - } - - void setupDisplacementTile( NL3D::CTileSet *set, TileItemNode *node, int idx ) - { - set->setDisplacement( NL3D::CTileSet::TDisplacement( idx ), - node->getTileFilename( TileConstants::TileDiffuse ).toUtf8().constData(), - bank ); - } - - void setupDisplacementTiles( NL3D::CTileSet *set, TileTypeNode *node ) - { - for( int i = 0; i < node->childCount(); i++ ) - { - TileItemNode *tin = static_cast< TileItemNode* >( node->child( i ) ); - setupDisplacementTile( set, tin, i ); - } - } - - void setupDisplacementTiles( NL3D::CTileSet *set, TileSetNode *node ) - { - TileTypeNode *tn = static_cast< TileTypeNode* >( node->child( 3 ) ); - setupDisplacementTiles( set, tn ); - } - - void setupTiles( NL3D::CTileSet *set, TileSetNode *node ) - { - TileTypeNode *tn128 = static_cast< TileTypeNode* >( node->child( 0 ) ); - TileTypeNode *tn256 = static_cast< TileTypeNode* >( node->child( 1 ) ); - - setupTiles128( set, tn128 ); - setupTiles256( set, tn256 ); - setupTransitionTiles( set, node ); - setupDisplacementTiles( set, node ); - } - - void addLands( const QList< Land > &lands ) - { - QListIterator< Land > itr( lands ); - while( itr.hasNext() ) - { - bank.addLand( itr.next().name.toUtf8().constData() ); - } - } - - - void addTileSets( const TileModel* model, const QList< Land > &lands ) - { - // Add the tilesets - for( int i = 0; i < model->rowCount(); i++ ) - { - QModelIndex idx = model->index( i, 0 ); - if( !idx.isValid() ) - continue; - - TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - QString set = n->getTileSetName(); - bank.addTileSet( set.toUtf8().constData() ); - } - - // Set the data to tilesets - for( int i = 0; i < bank.getTileSetCount(); i++ ) - { - NL3D::CTileSet *set = bank.getTileSet( i ); - - QModelIndex idx = model->index( i, 0 ); - if( !idx.isValid() ) - continue; - - TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - - addTilesToSet( set, n ); - setupTiles( set, n ); - set->setOriented( n->isOriented() ); - set->setTileVegetableDescFileName( n->vegetSet().toUtf8().constData() ); - } - - // Add tilesets to lands - for( int i = 0; i < bank.getLandCount(); i++ ) - { - NL3D::CTileLand *land = bank.getLand( i ); - const Land &l = lands[ i ]; - - for( int j = 0; j < l.tilesets.count(); j++ ) - { - land->addTileSet( l.tilesets[ j ].toUtf8().constData() ); - } - } - } }; TileBankSaver::TileBankSaver() @@ -285,18 +41,13 @@ TileBankSaver::~TileBankSaver() bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< Land > &lands ) { - p->addLands( lands ); - p->addTileSets( model, lands ); - - p->bank.setAbsPath( model->texturePath().toUtf8().constData() ); - // Save to file NLMISC::COFile f; bool b = f.open( fileName, false, false, false ); if( !b ) return false; - p->bank.serial( f ); + //p->bank.serial( f ); f.flush(); f.close(); From de15faa5d265a7c2d70dee90021bdeffc071ea26 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:33:11 +0200 Subject: [PATCH 185/220] Vegetation set stuff. --- .../src/plugins/tile_editor/tile_bank.cpp | 19 +++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 10 ++++------ .../src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_model.h | 3 +++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index a44158259..8d9c3447c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -393,3 +393,22 @@ void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChann } +void TileBank::setVegetation( int tileSet, const QString &vegetation ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->setTileVegetableDescFileName( vegetation.toUtf8().constData() ); +} + + +QString TileBank::getVegetation( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return ""; + + return set->getTileVegetableDescFileName().c_str(); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index d81ae694b..e29f4564c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -29,6 +29,9 @@ public: bool setTile( int tileset, int tile, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + void setVegetation( int tileSet, const QString &vegetation ); + QString getVegetation( int tileSet ) const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index dffa7a61a..3331857c1 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -542,8 +542,7 @@ void TileEditorMainWindow::onChooseVegetation() if( vegetSet.isEmpty() ) return; - TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - node->setVegetSet( vegetSet ); + m_tileModel->setVegetation( idx.row(), vegetSet ); m_ui->chooseVegetPushButton->setText( vegetSet ); } @@ -560,8 +559,7 @@ void TileEditorMainWindow::onResetVegetation() } m_ui->chooseVegetPushButton->setText( "..." ); - TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - node->setVegetSet( "" ); + m_tileModel->setVegetation( idx.row(), "" ); } void TileEditorMainWindow::onChooseTexturePath() @@ -860,9 +858,9 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons if( newIndex.isValid() ) newNode = reinterpret_cast< TileSetNode* >( newIndex.internalPointer() ); - if( newNode != NULL ) + if( newIndex.isValid() ) { - QString vegetSet = newNode->vegetSet(); + QString vegetSet = m_tileModel->getVegetation( newIndex.row() ); if( !vegetSet.isEmpty() ) m_ui->chooseVegetPushButton->setText( vegetSet ); diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 862b03bce..09d50cbef 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -396,6 +396,16 @@ void TileModel::clearImage( int ts, int type, int tile, TileConstants::TTileChan m_tileBank->clearImage( ts, type, tile, channel ); } +void TileModel::setVegetation( int tileSet, const QString &vegetation ) +{ + m_tileBank->setVegetation( tileSet, vegetation ); +} + +QString TileModel::getVegetation( int tileSet ) const +{ + return m_tileBank->getVegetation( tileSet ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index d2776bc86..9d8e00cde 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -98,6 +98,9 @@ public: bool replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + void setVegetation( int tileSet, const QString &vegetation ); + QString getVegetation( int tileSet ) const; + QString getLastError() const; bool hasError() const; From bcfcb5bb83d7dee09983100c4cd7a9dbbb180f87 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:41:33 +0200 Subject: [PATCH 186/220] Oriented stuff. --- .../src/plugins/tile_editor/tile_bank.cpp | 18 ++++++++++++++++++ .../studio/src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 10 +++++----- .../src/plugins/tile_editor/tile_item.cpp | 1 - .../studio/src/plugins/tile_editor/tile_item.h | 8 -------- .../src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_model.h | 3 +++ 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 8d9c3447c..85e69dd49 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -412,3 +412,21 @@ QString TileBank::getVegetation( int tileSet ) const return set->getTileVegetableDescFileName().c_str(); } +void TileBank::setOriented( int tileSet, bool b ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->setOriented( b ); +} + +bool TileBank::getOriented( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return false; + + return set->getOriented(); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index e29f4564c..ce6aa737c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -32,6 +32,9 @@ public: void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; + + void setOriented( int tileSet, bool b ); + bool getOriented( int tileSet ) const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 3331857c1..516db5ce3 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -590,12 +590,12 @@ void TileEditorMainWindow::onOrientedStateChanged( int state ) if( !idx.isValid() ) return; - TileSetNode *node = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); - + int row = idx.row(); + if( state == Qt::Checked ) - node->setOriented( true ); + m_tileModel->setOriented( row, true ); else - node->setOriented( false ); + m_tileModel->setOriented( row, false ); } void TileEditorMainWindow::onDiffuseToggled( bool b ) @@ -867,7 +867,7 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons else m_ui->chooseVegetPushButton->setText( "..." ); - m_ui->orientedCheckBox->setChecked( newNode->isOriented() ); + m_ui->orientedCheckBox->setChecked( m_tileModel->getOriented( newIndex.row() ) ); } else { diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index e952d8d20..7c10ef9dc 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -173,7 +173,6 @@ void Node::clear() TileSetNode::TileSetNode(QString tileSetName, Node *parent) : m_tileSetName(tileSetName) { m_parentItem = parent; - m_oriented = false; } TileSetNode::~TileSetNode() diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 2600f47d4..8df33361b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -79,16 +79,8 @@ public: const QString &getTileSetName(){ return m_tileSetName; } void setTileSetName( const QString &name ){ m_tileSetName = name; } - void setVegetSet( const QString &s ){ m_vegetSet = s; } - QString vegetSet() const{ return m_vegetSet; } - - bool isOriented() const{ return m_oriented; } - void setOriented( bool b ){ m_oriented = b; } - private: QString m_tileSetName; - QString m_vegetSet; - bool m_oriented; }; class TileTypeNode : public Node diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 09d50cbef..f1372be80 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -406,6 +406,16 @@ QString TileModel::getVegetation( int tileSet ) const return m_tileBank->getVegetation( tileSet ); } +void TileModel::setOriented( int tileSet, bool b ) +{ + m_tileBank->setOriented( tileSet, b ); +} + +bool TileModel::getOriented( int tileSet ) const +{ + return m_tileBank->getOriented( tileSet ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 9d8e00cde..a58b55ce1 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -101,6 +101,9 @@ public: void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; + void setOriented( int tileSet, bool b ); + bool getOriented( int tileSet ) const; + QString getLastError() const; bool hasError() const; From 716903fd5f004bd4fd515fa2ae0eb1dc2132f432 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:53:22 +0200 Subject: [PATCH 187/220] Surface data. --- .../src/plugins/tile_editor/tile_bank.cpp | 20 +++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 16 +++++++++++++++ .../tile_editor/tile_editor_main_window.h | 1 + .../src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ .../src/plugins/tile_editor/tile_model.h | 3 +++ 6 files changed, 53 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 85e69dd49..86c2646f9 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -430,3 +430,23 @@ bool TileBank::getOriented( int tileSet ) const return set->getOriented(); } + +void TileBank::setSurfaceData( int tileSet, unsigned long data ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + set->SurfaceData = data; +} + +unsigned long TileBank::getSurfaceData( int tileSet ) const +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return 0; + + return set->SurfaceData; +} + + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index ce6aa737c..dddafe032 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -35,6 +35,9 @@ public: void setOriented( int tileSet, bool b ); bool getOriented( int tileSet ) const; + + void setSurfaceData( int tileSet, unsigned long data ); + unsigned long getSurfaceData( int tileSet ) const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 516db5ce3..f673d75c4 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -183,6 +183,7 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) connect( m_ui->actionOpenTileBank, SIGNAL( triggered() ), this, SLOT( open() ) ); connect( m_ui->orientedCheckBox, SIGNAL( stateChanged( int ) ), this, SLOT( onOrientedStateChanged( int ) ) ); + connect( m_ui->surfaceDataLineEdit, SIGNAL( textEdited( const QString& ) ), this, SLOT( onSurfaceDataChanged( const QString& ) ) ); connect( m_ui->diffuse128BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); connect( m_ui->diffuse256BT, SIGNAL( toggled( bool ) ), this, SLOT( onDiffuseToggled( bool ) ) ); @@ -598,6 +599,20 @@ void TileEditorMainWindow::onOrientedStateChanged( int state ) m_tileModel->setOriented( row, false ); } +void TileEditorMainWindow::onSurfaceDataChanged( const QString &text ) +{ + QModelIndex idx = m_ui->tileSetLV->currentIndex(); + if( !idx.isValid() ) + return; + + bool ok = false; + unsigned long data = text.toUInt( &ok ); + if( !ok ) + return; + + m_tileModel->setSurfaceData( idx.row(), data ); +} + void TileEditorMainWindow::onDiffuseToggled( bool b ) { if( !b ) @@ -868,6 +883,7 @@ void TileEditorMainWindow::changeActiveTileSet(const QModelIndex &newIndex, cons m_ui->chooseVegetPushButton->setText( "..." ); m_ui->orientedCheckBox->setChecked( m_tileModel->getOriented( newIndex.row() ) ); + m_ui->surfaceDataLineEdit->setText( QString::number( m_tileModel->getSurfaceData( newIndex.row() ) ) ); } else { diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 1ec80cd96..c9b96928c 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -68,6 +68,7 @@ private Q_SLOTS: void onChooseTexturePath(); void onOrientedStateChanged( int state ); + void onSurfaceDataChanged( const QString &text ); void onDiffuseToggled( bool b ); void onAdditiveToggled( bool b ); diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index f1372be80..e1d7019b4 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -416,6 +416,16 @@ bool TileModel::getOriented( int tileSet ) const return m_tileBank->getOriented( tileSet ); } +void TileModel::setSurfaceData( int tileSet, unsigned long data ) +{ + m_tileBank->setSurfaceData( tileSet, data ); +} + +unsigned long TileModel::getSurfaceData( int tileSet ) const +{ + return m_tileBank->getSurfaceData( tileSet ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index a58b55ce1..daec140ea 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -104,6 +104,9 @@ public: void setOriented( int tileSet, bool b ); bool getOriented( int tileSet ) const; + void setSurfaceData( int tileSet, unsigned long data ); + unsigned long getSurfaceData( int tileSet ) const; + QString getLastError() const; bool hasError() const; From 1309834e497f7bc37d8a7ef11c079ba672d17b5a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:59:05 +0200 Subject: [PATCH 188/220] Texture path. --- code/studio/src/plugins/tile_editor/tile_bank.cpp | 10 ++++++++++ code/studio/src/plugins/tile_editor/tile_bank.h | 3 +++ .../plugins/tile_editor/tile_editor_main_window.cpp | 2 +- code/studio/src/plugins/tile_editor/tile_model.cpp | 10 ++++++++++ code/studio/src/plugins/tile_editor/tile_model.h | 8 +++----- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 86c2646f9..a4dd3f358 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -449,4 +449,14 @@ unsigned long TileBank::getSurfaceData( int tileSet ) const return set->SurfaceData; } +void TileBank::setTexturePath( const QString &path ) +{ + m_pvt->m_bank.setAbsPath( path.toUtf8().constData() ); +} + +QString TileBank::getTexturePath() const +{ + return m_pvt->m_bank.getAbsPath().c_str(); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index dddafe032..c42546895 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -38,6 +38,9 @@ public: void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; + + void setTexturePath( const QString &path ); + QString getTexturePath() const; bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index f673d75c4..e8f19cedc 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -816,7 +816,7 @@ void TileEditorMainWindow::onTileBankLoaded() m_ui->listView256->reset(); m_ui->listViewTransition->reset(); - QString path = m_tileModel->texturePath(); + QString path = m_tileModel->getTexturePath(); if( path.isEmpty() ) m_ui->tileBankTexturePathPB->setText( "..." ); else diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index e1d7019b4..e1249cb14 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -426,6 +426,16 @@ unsigned long TileModel::getSurfaceData( int tileSet ) const return m_tileBank->getSurfaceData( tileSet ); } +void TileModel::setTexturePath( const QString &path ) +{ + m_tileBank->setTexturePath( path ); +} + +QString TileModel::getTexturePath() const +{ + return m_tileBank->getTexturePath(); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index daec140ea..96193fd38 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -85,9 +85,6 @@ public: void clear(); - void setTexturePath( const QString &path ){ m_texturePath = path; } - QString texturePath() const{ return m_texturePath; } - void addLand( const QString &name ); void removeLand( int idx ); void removeTileSet( int idx ); @@ -107,6 +104,9 @@ public: void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; + void setTexturePath( const QString &path ); + QString getTexturePath() const; + QString getLastError() const; bool hasError() const; @@ -125,8 +125,6 @@ private: //int m_activeEditChannel; Node *rootItem; - QString m_texturePath; - TileBank *m_tileBank; }; From 1255cdb3e79760327eb4c71eb867a65c479b5c73 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 22:14:39 +0200 Subject: [PATCH 189/220] Saving tilebank --- code/studio/src/plugins/tile_editor/tile_bank.cpp | 5 +++++ code/studio/src/plugins/tile_editor/tile_bank.h | 7 +++++++ .../src/plugins/tile_editor/tile_editor_main_window.cpp | 3 +-- code/studio/src/plugins/tile_editor/tile_model.cpp | 5 +++++ code/studio/src/plugins/tile_editor/tile_model.h | 7 +++++++ code/studio/src/plugins/tile_editor/tilebank_saver.cpp | 4 ++-- code/studio/src/plugins/tile_editor/tilebank_saver.h | 4 +--- 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index a4dd3f358..62fcb3565 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -459,4 +459,9 @@ QString TileBank::getTexturePath() const return m_pvt->m_bank.getAbsPath().c_str(); } +void TileBank::serial( NLMISC::IStream &f ) +{ + m_pvt->m_bank.serial( f ); +} + diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index c42546895..d267486a8 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -7,6 +7,11 @@ #include "tile_constants.h" +namespace NLMISC +{ + class IStream; +} + class TileBankPvt; class TileBank @@ -41,6 +46,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + + void serial( NLMISC::IStream &f ); bool hasError() const{ return m_hasError; } QString getLastError() const{ return m_lastError; } diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index e8f19cedc..ed8c1ae54 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -250,8 +250,7 @@ void TileEditorMainWindow::saveAs( const QString &fn ) } TileBankSaver saver; - bool ok = true; - //saver.save( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool ok = saver.save( fn.toUtf8().constData(), m_tileModel ); if( !ok ) { diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index e1249cb14..4b14f54fb 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -431,6 +431,11 @@ void TileModel::setTexturePath( const QString &path ) m_tileBank->setTexturePath( path ); } +void TileModel::serial( NLMISC::IStream &f ) +{ + m_tileBank->serial( f ); +} + QString TileModel::getTexturePath() const { return m_tileBank->getTexturePath(); diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 96193fd38..c831daae2 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -23,6 +23,11 @@ #include "tile_constants.h" +namespace NLMISC +{ + class IStream; +} + class Node; class TileSetNode; class TileItemNode; @@ -107,6 +112,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + void serial( NLMISC::IStream &f ); + QString getLastError() const; bool hasError() const; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 15e31d141..a0b8abcfb 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -39,7 +39,7 @@ TileBankSaver::~TileBankSaver() p = NULL; } -bool TileBankSaver::save( const char *fileName, const TileModel* model, const QList< Land > &lands ) +bool TileBankSaver::save( const char *fileName, TileModel* model ) { // Save to file NLMISC::COFile f; @@ -47,7 +47,7 @@ bool TileBankSaver::save( const char *fileName, const TileModel* model, const QL if( !b ) return false; - //p->bank.serial( f ); + model->serial( f ); f.flush(); f.close(); diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index 2a2806fe1..ef1e0de94 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -20,10 +20,8 @@ #include #include -#include "land.h" class TileModel; - class TileBankSaverPvt; class TileBankSaver @@ -32,7 +30,7 @@ public: TileBankSaver(); ~TileBankSaver(); - bool save( const char *filename, const TileModel* model, const QList< Land > &lands ); + bool save( const char *filename, TileModel* model ); private: TileBankSaverPvt *p; From cc12fb91b4d78fc9c8211749eea4e995b7c1d3c3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 02:58:31 +0200 Subject: [PATCH 190/220] Tile loading more or less works. TODO: investigate why displacement map lookup causes crashes. --- code/nel/include/nel/3d/tile_bank.h | 5 + code/studio/src/plugins/tile_editor/land.h | 31 ---- .../src/plugins/tile_editor/tile_bank.cpp | 142 ++++++++++++++++++ .../src/plugins/tile_editor/tile_bank.h | 10 ++ .../tile_editor/tile_editor_main_window.cpp | 26 ++-- .../src/plugins/tile_editor/tile_images.h | 23 +++ .../src/plugins/tile_editor/tile_item.cpp | 8 + .../src/plugins/tile_editor/tile_item.h | 1 + .../src/plugins/tile_editor/tile_model.cpp | 128 +++++++++++++++- .../src/plugins/tile_editor/tile_model.h | 16 +- .../plugins/tile_editor/tilebank_loader.cpp | 16 +- .../src/plugins/tile_editor/tilebank_loader.h | 6 +- .../plugins/tile_editor/tilebank_saver.cpp | 9 -- .../src/plugins/tile_editor/tilebank_saver.h | 3 +- 14 files changed, 342 insertions(+), 82 deletions(-) delete mode 100644 code/studio/src/plugins/tile_editor/land.h create mode 100644 code/studio/src/plugins/tile_editor/tile_images.h diff --git a/code/nel/include/nel/3d/tile_bank.h b/code/nel/include/nel/3d/tile_bank.h index 89b8e2272..00e0f2cae 100644 --- a/code/nel/include/nel/3d/tile_bank.h +++ b/code/nel/include/nel/3d/tile_bank.h @@ -86,6 +86,11 @@ public: _BitmapName[bitmapType]=name; } + std::string getFileName (TBitmap bitmapType) const + { + return _BitmapName[bitmapType]; + } + /// Get the additional orientation (CCW) for alpha texture. uint8 getRotAlpha () { diff --git a/code/studio/src/plugins/tile_editor/land.h b/code/studio/src/plugins/tile_editor/land.h deleted file mode 100644 index 93d244d9d..000000000 --- a/code/studio/src/plugins/tile_editor/land.h +++ /dev/null @@ -1,31 +0,0 @@ -// Ryzom Core Studio - Tile Editor plugin -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef LAND_H -#define LAND_H - -#include - -struct Land -{ - QString name; - QStringList tilesets; -}; - - -#endif - diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 62fcb3565..3a7b34ca8 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -229,6 +229,16 @@ void TileBank::renameTileSet( int idx, const QString &newName ) } +void TileBank::getTileSets( QStringList &l ) +{ + int c = m_pvt->m_bank.getTileSetCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( i ); + l.push_back( set->getName().c_str() ); + } +} + void TileBank::addLand( const QString &name ) { m_pvt->m_bank.addLand( name.toUtf8().constData() ); @@ -239,6 +249,18 @@ void TileBank::removeLand( int idx ) m_pvt->m_bank.removeLand( idx ); } +void TileBank::getLands( QStringList &l ) +{ + l.clear(); + + int c = m_pvt->m_bank.getLandCount(); + for( int i = 0; i < c; i++ ) + { + NL3D::CTileLand *land = m_pvt->m_bank.getLand( i ); + l.push_back( land->getName().c_str() ); + } +} + void TileBank::setLandSets( int idx, const QStringList &l ) { NL3D::CTileLand *land = m_pvt->m_bank.getLand( idx ); @@ -392,6 +414,126 @@ void TileBank::clearImage( int ts, int type, int tile, TileConstants::TTileChann } +int TileBank::getTileCount( int tileSet, TileConstants::TNodeTileType type ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return -1; + + int c = 0; + + switch( type ) + { + case TileConstants::Tile128: + c = set->getNumTile128(); + break; + + case TileConstants::Tile256: + c = set->getNumTile256(); + break; + + case TileConstants::TileTransition: + c = NL3D::CTileSet::count; + break; + + case TileConstants::TileDisplacement: + c = NL3D::CTileSet::CountDisplace; + break; + } + + return c; +} + +int TileBank::getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return -1; + + int tile = -1; + + switch( type ) + { + case TileConstants::Tile128: + tile = set->getTile128( tileIdInSet ); + break; + + case TileConstants::Tile256: + tile = set->getTile256( tileIdInSet ); + break; + + case TileConstants::TileTransition: + tile = set->getTransition( tileIdInSet )->getTile(); + break; + + case TileConstants::TileDisplacement: + tile = set->getDisplacementTile( NL3D::CTileSet::TDisplacement( tileIdInSet ) ); + break; + } + + return tile; +} + +void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ) +{ + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + switch( type ) + { + case TileConstants::Tile128: + case TileConstants::Tile256: + case TileConstants::TileTransition: + { + NL3D::CTile *t = m_pvt->m_bank.getTile( tileId ); + if( t == NULL ) + return; + + images.diffuse = t->getFileName( channelToTBitmap( TileConstants::TileDiffuse ) ).c_str(); + images.additive = t->getFileName( channelToTBitmap( TileConstants::TileAdditive ) ).c_str(); + images.alpha = t->getFileName( channelToTBitmap( TileConstants::TileAlpha ) ).c_str(); + } + break; + + case TileConstants::TileDisplacement: + { + images.diffuse = m_pvt->m_bank.getDisplacementMap( tileId ); + } + break; + } + +} + +void TileBank::getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ) +{ + l.clear(); + + NL3D::CTileSet *set = m_pvt->m_bank.getTileSet( tileSet ); + if( set == NULL ) + return; + + int c = getTileCount( tileSet, type ); + + TileImages images; + + for( int i = 0; i < c; i++ ) + { + images.clear(); + + int id = getRealTileId( tileSet, type, i ); + if( id < 0 ) + { + l.push_back( images ); + continue; + } + + getTileImages( tileSet, type, id, images ); + + l.push_back( images ); + } + +} void TileBank::setVegetation( int tileSet, const QString &vegetation ) { diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index d267486a8..e420fac9c 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -4,8 +4,10 @@ #include #include #include +#include #include "tile_constants.h" +#include "tile_images.h" namespace NLMISC { @@ -23,9 +25,11 @@ public: void addTileSet( const QString &name ); void removeTileSet( int idx ); void renameTileSet( int idx, const QString &newName ); + void getTileSets( QStringList &l ); void addLand( const QString &name ); void removeLand( int idx ); + void getLands( QStringList &l ); void setLandSets( int idx, const QStringList &l ); void getLandSets( int idx, QStringList &l ); @@ -35,6 +39,12 @@ public: void replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name, const QVariant &pixmap ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); + + int getTileCount( int tileSet, TileConstants::TNodeTileType type ); + int getRealTileId( int tileSet, TileConstants::TNodeTileType type, int tileIdInSet ); + void getTileImages( int tileSet, TileConstants::TNodeTileType type, int tileId, TileImages &images ); + void getTileImages( int tileSet, TileConstants::TNodeTileType type, QList< TileImages > &l ); + void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index ed8c1ae54..86953f6a7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -271,8 +271,7 @@ void TileEditorMainWindow::open() return; TileBankLoader loader; - bool b = true; - //loader.load( fn.toUtf8().constData(), m_tileModel, m_lands ); + bool b = loader.load( fn.toUtf8().constData(), m_tileModel ); if( !b ) { @@ -374,7 +373,7 @@ void TileEditorMainWindow::onTileSetAdd() } // Create and append the new tile set to the model. - TileSetNode *tileSet = model->createTileSetNode(text); + m_tileModel->addTileSet( text ); // Retrieve how many rows there currently are and set the current index using that. uint32 rows = model->rowCount(); @@ -684,8 +683,6 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QString selectedFilter; QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); - int c = n->childCount(); - TileConstants::TNodeTileType type = tabToType( tabId ); QStringListIterator itr( fileNames ); @@ -693,8 +690,9 @@ void TileEditorMainWindow::onActionAddTile(int tabId) while( itr.hasNext() ) { - TileItemNode *newNode = m_tileModel->createItemNode( setId, type, c, TileConstants::TileDiffuse, itr.next() ); - if( newNode == NULL ) + bool b = m_tileModel->addTile( setId, type, itr.next(), TileConstants::TileDiffuse ); + + if( !b ) { if( m_tileModel->hasError() ) error = m_tileModel->getLastError(); @@ -708,9 +706,7 @@ void TileEditorMainWindow::onActionAddTile(int tabId) else continue; } - - n->appendRow( newNode ); - c++; + } QModelIndex rootIdx = m_tileModel->index( tabId, 0, m_ui->tileSetLV->currentIndex()); @@ -809,7 +805,15 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) void TileEditorMainWindow::onTileBankLoaded() { m_ui->landLW->clear(); - // load lands + QStringList lands; + m_tileModel->getLands( lands ); + QStringListIterator itr( lands ); + while( itr.hasNext() ) + { + m_ui->landLW->addItem( itr.next() ); + } + + m_tileModel->onTBLoaded(); m_ui->listView128->reset(); m_ui->listView256->reset(); diff --git a/code/studio/src/plugins/tile_editor/tile_images.h b/code/studio/src/plugins/tile_editor/tile_images.h new file mode 100644 index 000000000..699fe3f11 --- /dev/null +++ b/code/studio/src/plugins/tile_editor/tile_images.h @@ -0,0 +1,23 @@ +#ifndef TILE_IMAGES_H +#define TILE_IMAGES_H + +#include + +struct TileImages +{ + QString diffuse; + QString additive; + QString alpha; + + void clear() + { + diffuse.clear(); + additive.clear(); + alpha.clear(); + } +}; + + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 7c10ef9dc..cba20ce2d 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -312,6 +312,14 @@ TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileC setTileFilename( channel, filename ); } +TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) +{ + m_id = tileId; + m_parentItem = parent; + pvt = new TileItemNodePvt(); + m_hasError = false; +} + TileItemNode::~TileItemNode() { delete pvt; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 8df33361b..08de0ec1f 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -107,6 +107,7 @@ class TileItemNode : public Node { public: TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent=0); + TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; int columnCount() const; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 4b14f54fb..d9e9b7ef3 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -218,16 +218,10 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // Append them in the correct order to the tile set. this->appendRow(tileSet); - m_tileBank->addTileSet(tileSetName); - + return tileSet; } -TileItemNode *TileModel::createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) -{ - return new TileItemNode( type, id, channel, fileName ); -} - TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) { TileItemNode *n = new TileItemNode( type, id, channel, fileName ); @@ -305,6 +299,12 @@ void TileModel::clear() removeRows( 0, c ); } +void TileModel::onTBLoaded() +{ + loadTileSets(); +} + + void TileModel::addLand( const QString &name ) { m_tileBank->addLand( name ); @@ -315,6 +315,11 @@ void TileModel::removeLand( int idx ) m_tileBank->removeLand( idx ); } +void TileModel::getLands( QStringList &l ) +{ + m_tileBank->getLands( l ); +} + void TileModel::setLandSets( int idx, const QStringList &l ) { m_tileBank->setLandSets( idx, l ); @@ -325,6 +330,15 @@ void TileModel::getLandSets( int idx, QStringList &l ) m_tileBank->getLandSets( idx, l ); } + +bool TileModel::addTileSet( const QString &name ) +{ + m_tileBank->addTileSet( name ); + TileSetNode *tsn = createTileSetNode( name ); + + return false; +} + void TileModel::removeTileSet( int idx ) { TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( idx ) ); @@ -341,6 +355,35 @@ void TileModel::renameTileSet( int idx, const QString &newName ) m_tileBank->renameTileSet( idx, newName ); } +bool TileModel::addTile( int ts, int type, const QString &fileName, TileConstants::TTileChannel channel ) +{ + TileSetNode *tsn = static_cast< TileSetNode* >( rootItem->child( ts ) ); + if( tsn == NULL ) + return false; + + TileTypeNode *ttn = static_cast< TileTypeNode* >( tsn->child( type ) ); + if( ttn == NULL ) + return false; + + int tile = ttn->childCount(); + + TileConstants::TNodeTileType t = TileConstants::TNodeTileType( type ); + + TileItemNode *item = new TileItemNode( t, tile, channel, fileName ); + + bool b = m_tileBank->addTile( ts, fileName, item->pixmap( channel ), channel, t ); + if( !b ) + { + delete item; + return false; + } + + item->setParent( ttn ); + ttn->appendRow( item ); + + return true; +} + void TileModel::removeTile( int ts, int type, int tile ) { TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( ts ) ); @@ -458,4 +501,73 @@ void TileModel::selectFilenameDisplay(bool selected) void TileModel::selectIndexDisplay(bool selected) { m_indexDisplay = selected; -} \ No newline at end of file +} + +void TileModel::loadTileSets() +{ + QStringList l; + m_tileBank->getTileSets( l ); + + // Create tile sets + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + createTileSetNode( itr.next() ); + } + + // Loads sets + int c = rootItem->childCount(); + for( int i = 0; i < c; i++ ) + { + loadTileSet( i ); + } +} + + +void TileModel::loadTileSet( int tileSet ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( tileSet ) ); + + QList< TileImages > l; + //for( int i = TileConstants::Tile128; i < TileConstants::TileNodeTypeCount; i++ ) + //for( int i = TileConstants::Tile128; i < TileConstants::TileTransition; i++ ) + for( int i = TileConstants::Tile128; i < TileConstants::TileDisplacement; i++ ) + { + TileConstants::TNodeTileType type = TileConstants::TNodeTileType( i ); + l.clear(); + m_tileBank->getTileImages( tileSet, type, l ); + + loadTileTypeNode( tileSet, type, l ); + } +} + +void TileModel::loadTileTypeNode( int tileSet, int type, const QList< TileImages > &l ) +{ + TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( tileSet ) ); + TileTypeNode *ttn = static_cast< TileTypeNode* >( set->child( type ) ); + + int tile = 0; + + QList< TileImages >::const_iterator itr = l.begin(); + while( itr != l.end() ) + { + const TileImages &images = *itr; + + TileItemNode *item = NULL; + + if( ( type == TileConstants::Tile128 ) || ( type == TileConstants::Tile256 ) ) + item = new TileItemNode( TileConstants::TNodeTileType( type ), tile, ttn ); + else + item = static_cast< TileItemNode* >( ttn->child( tile ) ); + + item->setTileFilename( TileConstants::TileDiffuse, images.diffuse ); + item->setTileFilename( TileConstants::TileAdditive, images.additive ); + item->setTileFilename( TileConstants::TileAlpha, images.alpha ); + + if( ( type == TileConstants::Tile128 ) || ( type == TileConstants::Tile256 ) ) + ttn->appendRow( item ); + + ++itr; + tile++; + } +} diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index c831daae2..b0e3232b9 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -22,6 +22,7 @@ #include #include "tile_constants.h" +#include "tile_images.h" namespace NLMISC { @@ -32,6 +33,7 @@ class Node; class TileSetNode; class TileItemNode; class TileBank; +class TileModelPvt; class TileModel : public QAbstractItemModel { @@ -77,8 +79,6 @@ public: void swapRows( int a, int b ); - TileSetNode *createTileSetNode(QString tileSetName); - static TileItemNode *createItemNode( TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); TileItemNode *createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); static const char *getTileTypeName(TileConstants::TNodeTileType type); @@ -89,13 +89,20 @@ public: bool hasTileSet( const QString &name ); void clear(); + void onTBLoaded(); void addLand( const QString &name ); void removeLand( int idx ); + void getLands( QStringList &l ); + + bool addTileSet( const QString &name ); + void removeTileSet( int idx ); void renameTileSet( int idx, const QString &newName ); void setLandSets( int idx, const QStringList &l ); void getLandSets( int idx, QStringList &l ); + + bool addTile( int ts, int type, const QString &fileName, TileConstants::TTileChannel channel ); void removeTile( int ts, int type, int tile ); bool replaceImage( int ts, int type, int tile, TileConstants::TTileChannel channel, const QString &name ); void clearImage( int ts, int type, int tile, TileConstants::TTileChannel channel ); @@ -122,7 +129,11 @@ public Q_SLOTS: void selectIndexDisplay(bool selected); private: + TileSetNode *createTileSetNode(QString tileSetName); Node *getItem(const QModelIndex &index) const; + void loadTileSets(); + void loadTileSet( int tileSet ); + void loadTileTypeNode( int tileSet, int type, const QList< TileImages > &l ); bool m_fileDisplay; bool m_indexDisplay; @@ -133,6 +144,7 @@ private: Node *rootItem; TileBank *m_tileBank; + TileModelPvt *pvt; }; #endif // TILE_MODEL_H diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 945fd0908..1aaa055f0 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -18,35 +18,23 @@ #include "tilebank_loader.h" #include "tile_model.h" -#include "tile_item.h" - -#include "nel/3d/tile_bank.h" #include "nel/misc/file.h" -class TileBankLoaderPvt -{ -public: -}; - - TileBankLoader::TileBankLoader() { - p = new TileBankLoaderPvt; } TileBankLoader::~TileBankLoader() { - delete p; - p = NULL; } -bool TileBankLoader::load( const char *filename, TileModel *model, QList< Land > &lands ) +bool TileBankLoader::load( const char *filename, TileModel *model ) { NLMISC::CIFile file; if( !file.open( filename, false ) ) return false; - //p->bank.serial( file ); + model->serial( file ); file.close(); diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h index 1f3498d6e..643cab67f 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.h +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -17,10 +17,7 @@ #ifndef TILEBANK_LOADER_H #define TILEBANK_LOADER_H -#include "land.h" - class TileModel; -class TileBankLoaderPvt; class TileBankLoader { @@ -28,10 +25,9 @@ public: TileBankLoader(); ~TileBankLoader(); - bool load( const char *filename, TileModel *model, QList< Land > &lands ); + bool load( const char *filename, TileModel *model ); private: - TileBankLoaderPvt *p; }; diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index a0b8abcfb..3f087c979 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -22,21 +22,12 @@ #include "nel/3d/tile_bank.h" #include "nel/misc/file.h" -class TileBankSaverPvt -{ -public: - -}; - TileBankSaver::TileBankSaver() { - p = new TileBankSaverPvt(); } TileBankSaver::~TileBankSaver() { - delete p; - p = NULL; } bool TileBankSaver::save( const char *fileName, TileModel* model ) diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.h b/code/studio/src/plugins/tile_editor/tilebank_saver.h index ef1e0de94..0f8983157 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -22,7 +22,6 @@ #include class TileModel; -class TileBankSaverPvt; class TileBankSaver { @@ -33,7 +32,7 @@ public: bool save( const char *filename, TileModel* model ); private: - TileBankSaverPvt *p; + }; #endif From a7022146ec1a347225f1279b6143fb9ce2c4732f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:17:29 +0200 Subject: [PATCH 191/220] Makes no sense, but doesn't seem to be crashing anymore o.O --- code/studio/src/plugins/tile_editor/tile_model.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index d9e9b7ef3..46ef27ca0 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -529,9 +529,7 @@ void TileModel::loadTileSet( int tileSet ) TileSetNode *set = static_cast< TileSetNode* >( rootItem->child( tileSet ) ); QList< TileImages > l; - //for( int i = TileConstants::Tile128; i < TileConstants::TileNodeTypeCount; i++ ) - //for( int i = TileConstants::Tile128; i < TileConstants::TileTransition; i++ ) - for( int i = TileConstants::Tile128; i < TileConstants::TileDisplacement; i++ ) + for( int i = TileConstants::Tile128; i < TileConstants::TileNodeTypeCount; i++ ) { TileConstants::TNodeTileType type = TileConstants::TNodeTileType( i ); l.clear(); From 53e118eb043a0ab55b2d67dd9e2cf78c503ea6d3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:20:30 +0200 Subject: [PATCH 192/220] Clear before loading the model data. --- code/studio/src/plugins/tile_editor/tile_model.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 46ef27ca0..14016024a 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -301,6 +301,7 @@ void TileModel::clear() void TileModel::onTBLoaded() { + clear(); loadTileSets(); } From 29bf9e0a93f0af14a3217b7d21c8f11d8d69f1d7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:35:10 +0200 Subject: [PATCH 193/220] Set all images by default. --- .../src/plugins/tile_editor/tile_item.cpp | 17 +++++---------- .../src/plugins/tile_editor/tile_item.h | 1 - .../src/plugins/tile_editor/tile_model.cpp | 21 ++++--------------- .../src/plugins/tile_editor/tile_model.h | 2 -- 4 files changed, 9 insertions(+), 32 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index cba20ce2d..7d339b1db 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -300,24 +300,17 @@ private: TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; int TileItemNode::s_alphaRot = 0; -TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent) -{ - m_id = tileId; - m_parentItem = parent; - //nlinfo("dispalying tile %d - %s", m_tileId, m_tileFilename[TileModel::TileDiffuse].toAscii().data()); - - pvt = new TileItemNodePvt(); - m_hasError = false; - - setTileFilename( channel, filename ); -} - TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) { m_id = tileId; m_parentItem = parent; pvt = new TileItemNodePvt(); m_hasError = false; + + for( int i = 0; i < TileConstants::TileChannelCount; i++ ) + { + setTileFilename( TileConstants::TTileChannel( i ), "" ); + } } TileItemNode::~TileItemNode() diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 08de0ec1f..85da09c4f 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -106,7 +106,6 @@ class TileItemNodePvt; class TileItemNode : public Node { public: - TileItemNode( TileConstants::TNodeTileType type, int tileId, TileConstants::TTileChannel channel, QString filename, Node *parent=0); TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent=0); virtual ~TileItemNode(); QVariant data(int column, int role) const; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index 14016024a..f4b9dfa15 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -200,7 +200,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::count from NeL for(int transPos=0; transPos<48; transPos++) { - TileItemNode *transTile= new TileItemNode( TileConstants::TileTransition, transPos, TileConstants::TileDiffuse, QString("empty")); + TileItemNode *transTile= new TileItemNode( TileConstants::TileTransition, transPos ); tileTrans->appendRow(transTile); } @@ -212,7 +212,7 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) // TODO tie this to CTileSet::CountDisplace from NeL for(int dispPos=0; dispPos<16; dispPos++) { - TileItemNode *dispTile= new TileItemNode( TileConstants::TileDisplacement, dispPos, TileConstants::TileDiffuse, QString("empty")); + TileItemNode *dispTile= new TileItemNode( TileConstants::TileDisplacement, dispPos ); tileDisp->appendRow(dispTile); } @@ -222,20 +222,6 @@ TileSetNode *TileModel::createTileSetNode(QString tileSetName) return tileSet; } -TileItemNode *TileModel::createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ) -{ - TileItemNode *n = new TileItemNode( type, id, channel, fileName ); - - bool b = m_tileBank->addTile( idx, fileName, n->pixmap( channel ), channel, type ); - if( !b ) - { - delete n; - return NULL; - } - - return n; -} - const char *TileModel::getTileTypeName(TileConstants::TNodeTileType type) { switch(type) @@ -370,7 +356,8 @@ bool TileModel::addTile( int ts, int type, const QString &fileName, TileConstant TileConstants::TNodeTileType t = TileConstants::TNodeTileType( type ); - TileItemNode *item = new TileItemNode( t, tile, channel, fileName ); + TileItemNode *item = new TileItemNode( t, tile ); + item->setTileFilename( channel, fileName ); bool b = m_tileBank->addTile( ts, fileName, item->pixmap( channel ), channel, t ); if( !b ) diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index b0e3232b9..8a89076bb 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -79,8 +79,6 @@ public: void swapRows( int a, int b ); - TileItemNode *createItemNode( int idx, TileConstants::TNodeTileType type, int id, TileConstants::TTileChannel channel, const QString &fileName ); - static const char *getTileTypeName(TileConstants::TNodeTileType type); static uint32 getTileTypeSize(TileConstants::TNodeTileType type); From 6c8ae2fafe166a39c30bf74063eddcf298774969 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 13:18:41 +0200 Subject: [PATCH 194/220] Line endings and copyright headers... --- .../src/plugins/tile_editor/tile_bank.cpp | 17 +++++++ .../src/plugins/tile_editor/tile_bank.h | 19 +++++++- .../src/plugins/tile_editor/tile_constants.h | 47 +++++++++++++------ .../src/plugins/tile_editor/tile_images.h | 17 +++++++ .../src/plugins/tile_editor/tile_model.h | 4 +- 5 files changed, 86 insertions(+), 18 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 3a7b34ca8..47e26511f 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "tile_bank.h" #include "nel/3d/tile_bank.h" diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index e420fac9c..55901584a 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef TILE_BANK_H #define TILE_BANK_H @@ -54,7 +71,7 @@ public: void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; - void setTexturePath( const QString &path ); + void setTexturePath( const QString &path ); QString getTexturePath() const; void serial( NLMISC::IStream &f ); diff --git a/code/studio/src/plugins/tile_editor/tile_constants.h b/code/studio/src/plugins/tile_editor/tile_constants.h index e75664d43..bf09f21a5 100644 --- a/code/studio/src/plugins/tile_editor/tile_constants.h +++ b/code/studio/src/plugins/tile_editor/tile_constants.h @@ -1,24 +1,41 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef TILE_CONSTANTS_H #define TILE_CONSTANTS_H namespace TileConstants { - enum TTileChannel - { - TileDiffuse = 0, - TileAdditive = 1, - TileAlpha = 2, - TileChannelCount = 3 - }; - - enum TNodeTileType - { - Tile128 = 0, - Tile256 = 1, - TileTransition = 2, - TileDisplacement = 3, - TileNodeTypeCount = 4 + enum TTileChannel + { + TileDiffuse = 0, + TileAdditive = 1, + TileAlpha = 2, + TileChannelCount = 3 + }; + + enum TNodeTileType + { + Tile128 = 0, + Tile256 = 1, + TileTransition = 2, + TileDisplacement = 3, + TileNodeTypeCount = 4 }; } diff --git a/code/studio/src/plugins/tile_editor/tile_images.h b/code/studio/src/plugins/tile_editor/tile_images.h index 699fe3f11..e17267001 100644 --- a/code/studio/src/plugins/tile_editor/tile_images.h +++ b/code/studio/src/plugins/tile_editor/tile_images.h @@ -1,3 +1,20 @@ +// Ryzom Core Studio - Tile Editor plugin +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #ifndef TILE_IMAGES_H #define TILE_IMAGES_H diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index 8a89076bb..dafbf09f8 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -108,10 +108,10 @@ public: void setVegetation( int tileSet, const QString &vegetation ); QString getVegetation( int tileSet ) const; - void setOriented( int tileSet, bool b ); + void setOriented( int tileSet, bool b ); bool getOriented( int tileSet ) const; - void setSurfaceData( int tileSet, unsigned long data ); + void setSurfaceData( int tileSet, unsigned long data ); unsigned long getSurfaceData( int tileSet ) const; void setTexturePath( const QString &path ); From 1e9e492f0f98600b5adce48d4cbb587fe30e1bdc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 13:42:56 +0200 Subject: [PATCH 195/220] Rotation is now set in the tilebank wrapper and applied when replacing a tile. --- .../src/plugins/tile_editor/tile_bank.cpp | 18 +++++++++++++++++- .../studio/src/plugins/tile_editor/tile_bank.h | 3 +++ .../tile_editor/tile_editor_main_window.cpp | 2 +- .../src/plugins/tile_editor/tile_item.cpp | 1 - .../studio/src/plugins/tile_editor/tile_item.h | 2 -- .../src/plugins/tile_editor/tile_model.cpp | 5 +++++ .../src/plugins/tile_editor/tile_model.h | 2 ++ 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 47e26511f..9a4d15469 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -198,6 +198,7 @@ TileBank::TileBank() { m_pvt = new TileBankPvt(); resetError(); + m_rotation = 0; } TileBank::~TileBank() @@ -378,6 +379,16 @@ bool TileBank::setTile( int tileset, int tile, const QString &name, const QVaria NL3D::CTileBorder border; m_pvt->buildBorder( pm, border ); + if( ( type == TileConstants::TileTransition ) && ( channel == TileConstants::TileAlpha ) ) + { + int rotBits = m_rotation; + while( rotBits > 0 ) + { + border.rotate(); + rotBits--; + } + } + QString msg; NL3D::CTileSet::TError error = m_pvt->checkTile( set, tile, type, border, channelToTBitmap( channel ), msg ); @@ -387,7 +398,7 @@ bool TileBank::setTile( int tileset, int tile, const QString &name, const QVaria if( error == NL3D::CTileSet::addFirstA128128 ) set->setBorder( channelToTBitmap( channel ), border ); - m_pvt->setTile( set, tile, 0 /* rotation */, name, channelToTBitmap( channel ), type, border ); + m_pvt->setTile( set, tile, m_rotation, name, channelToTBitmap( channel ), type, border ); return true; } @@ -618,6 +629,11 @@ QString TileBank::getTexturePath() const return m_pvt->m_bank.getAbsPath().c_str(); } +void TileBank::setRotation( int rotation ) +{ + m_rotation = rotation; +} + void TileBank::serial( NLMISC::IStream &f ) { m_pvt->m_bank.serial( f ); diff --git a/code/studio/src/plugins/tile_editor/tile_bank.h b/code/studio/src/plugins/tile_editor/tile_bank.h index 55901584a..a4620ad41 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -74,6 +74,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + void setRotation( int rotation ); + void serial( NLMISC::IStream &f ); bool hasError() const{ return m_hasError; } @@ -93,6 +95,7 @@ private: TileBankPvt *m_pvt; QString m_lastError; bool m_hasError; + int m_rotation; }; #endif diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 86953f6a7..0341502d5 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -335,7 +335,7 @@ void TileEditorMainWindow::onZoomFactor(int level) void TileEditorMainWindow::onRotate( int id ) { - TileItemNode::setAlphaRot( id * 90 ); + m_tileModel->setAlphaRot( id ); } void TileEditorMainWindow::onActionAddTile(bool triggered) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 7d339b1db..f39ba87dc 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -298,7 +298,6 @@ private: }; TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; -int TileItemNode::s_alphaRot = 0; TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) { diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 85da09c4f..7af553c8e 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -117,7 +117,6 @@ public: static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } - static void setAlphaRot( int rot ){ s_alphaRot = rot; } QVariant pixmap( TileConstants::TTileChannel channel ) const; @@ -126,7 +125,6 @@ private: QMap m_tileWidget; static TileConstants::TTileChannel s_displayChannel; - static int s_alphaRot; int m_id; diff --git a/code/studio/src/plugins/tile_editor/tile_model.cpp b/code/studio/src/plugins/tile_editor/tile_model.cpp index f4b9dfa15..2af4c6a84 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.cpp +++ b/code/studio/src/plugins/tile_editor/tile_model.cpp @@ -472,6 +472,11 @@ QString TileModel::getTexturePath() const return m_tileBank->getTexturePath(); } +void TileModel::setAlphaRot( int rotation ) +{ + m_tileBank->setRotation( rotation ); +} + QString TileModel::getLastError() const{ return m_tileBank->getLastError(); } diff --git a/code/studio/src/plugins/tile_editor/tile_model.h b/code/studio/src/plugins/tile_editor/tile_model.h index dafbf09f8..c6bfc8788 100644 --- a/code/studio/src/plugins/tile_editor/tile_model.h +++ b/code/studio/src/plugins/tile_editor/tile_model.h @@ -117,6 +117,8 @@ public: void setTexturePath( const QString &path ); QString getTexturePath() const; + void setAlphaRot( int rotation ); + void serial( NLMISC::IStream &f ); QString getLastError() const; From f23a557e77be6bd294711c239d09bb7409e2c357 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 15:16:25 +0200 Subject: [PATCH 196/220] Save the last directoy where we loaded a tilebank from. --- .../src/plugins/tile_editor/tile_editor_main_window.cpp | 5 ++++- .../studio/src/plugins/tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 0341502d5..62aea3fcb 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -264,7 +264,7 @@ void TileEditorMainWindow::open() { QString fn = QFileDialog::getOpenFileName( this, tr( "Loading tilebank" ), - "", + m_lastOpenDir, tr( "tilebank files (*.tilebank)" ) ); if( fn.isEmpty() ) @@ -284,6 +284,9 @@ void TileEditorMainWindow::open() onTileBankLoaded(); m_fileName = fn; + + int idx = fn.lastIndexOf( '/' ); + m_lastOpenDir = fn.left( idx ); } void TileEditorMainWindow::onZoomFactor(int level) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index c9b96928c..550c6bb75 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -122,6 +122,7 @@ private: }; QString m_fileName; + QString m_lastOpenDir; }; #endif // TILE_EDITOR_MAIN_WINDOW_H From 53f771690c5e4e3b6d0c65777ae01ec586a9030e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 15:34:29 +0200 Subject: [PATCH 197/220] Save the last directory where we loaded a tile image from. --- .../tile_editor/tile_editor_main_window.cpp | 14 ++++++++++++-- .../plugins/tile_editor/tile_editor_main_window.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 62aea3fcb..a6571c3e7 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -684,7 +684,9 @@ void TileEditorMainWindow::onActionAddTile(int tabId) QFileDialog::Options options; QString selectedFilter; - QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", "." , "Images (*.png);;All Files (*.*)", &selectedFilter, options); + QStringList fileNames = QFileDialog::getOpenFileNames(this, "Choose Tile Texture", m_lastTileDir , "Images (*.png);;All Files (*.*)", &selectedFilter, options); + if( fileNames.empty() ) + return; TileConstants::TNodeTileType type = tabToType( tabId ); @@ -719,6 +721,10 @@ void TileEditorMainWindow::onActionAddTile(int tabId) lv->reset(); lv->setRootIndex( rootIdx ); lv->setCurrentIndex( lv->model()->index( 0, 0, rootIdx ) ); + + QString fn = fileNames[ 0 ].replace( '\\', '/' ); + int slashIdx = fn.lastIndexOf( '/' ); + m_lastTileDir = fn.left( slashIdx ); } void TileEditorMainWindow::onActionDeleteTile( int tabId ) @@ -787,7 +793,7 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) QString fileName = QFileDialog::getOpenFileName( this, tr( "Select tile image" ), - "", + m_lastTileDir, tr( "PNG files (*.png)" ) ); if( fileName.isEmpty() ) return; @@ -803,6 +809,10 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) tr( "Error replacing tile image" ), error ); } + + QString fn = fileName.replace( '\\', '/' ); + int slashIdx = fn.lastIndexOf( '/' ); + m_lastTileDir = fn.left( slashIdx ); } void TileEditorMainWindow::onTileBankLoaded() diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 550c6bb75..9dee6954d 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -123,6 +123,7 @@ private: QString m_fileName; QString m_lastOpenDir; + QString m_lastTileDir; }; #endif // TILE_EDITOR_MAIN_WINDOW_H From f22f9fbc08ae1466ad67ece84432af02fde627ce Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 16:01:45 +0200 Subject: [PATCH 198/220] Repaint immediately when the display channel is changed. --- .../plugins/tile_editor/tile_editor_main_window.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index a6571c3e7..9f4851058 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -848,7 +848,15 @@ void TileEditorMainWindow::onTileBankLoaded() void TileEditorMainWindow::updateTab() { - m_ui->tileViewTabWidget->currentWidget()->repaint(); + int idx = m_ui->tileViewTabWidget->currentIndex(); + + switch( idx ) + { + case 0: m_ui->listView128->viewport()->repaint(); break; + case 1: m_ui->listView256->viewport()->repaint(); break; + case 2: m_ui->listViewTransition->viewport()->repaint(); break; + case 3: m_ui->listViewDisplacement->viewport()->repaint(); break; + } } TileModel* TileEditorMainWindow::createTileModel() From 4f05fea63c8c5b83ae6293b0deb99b9891295e3d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:01:44 +0200 Subject: [PATCH 199/220] Removed unused variable. --- code/studio/src/plugins/tile_editor/tile_item.cpp | 2 -- code/studio/src/plugins/tile_editor/tile_item.h | 1 - 2 files changed, 3 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index f39ba87dc..04889e61b 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -304,7 +304,6 @@ TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node m_id = tileId; m_parentItem = parent; pvt = new TileItemNodePvt(); - m_hasError = false; for( int i = 0; i < TileConstants::TileChannelCount; i++ ) { @@ -332,7 +331,6 @@ bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString } bool b = pvt->loadImage( channel, fn, empty ); - m_hasError = !b; if( !b ) return false; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 7af553c8e..1af7833dd 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -130,7 +130,6 @@ private: TileItemNodePvt *pvt; - bool m_hasError; }; #endif // TILE_ITEM_H From 3fc31ee2ada0a680b85e584c522298457f3fa4cf Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:04:30 +0200 Subject: [PATCH 200/220] Removed yet another unused variable. --- code/studio/src/plugins/tile_editor/tile_item.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 04889e61b..311b711cc 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -269,7 +269,7 @@ public: { } - bool loadImage( TileConstants::TTileChannel channel, const QString &fn, bool empty = false ) + bool loadImage( TileConstants::TTileChannel channel, const QString &fn ) { QPixmap temp; bool b = temp.load( fn ); @@ -322,15 +322,13 @@ TileItemNode::~TileItemNode() bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString filename) { QString fn = filename; - bool empty = false; if( filename.isEmpty() || ( filename == "empty" ) ) { fn = ":/placeHolder/images/empty_image.png"; - empty = true; } - bool b = pvt->loadImage( channel, fn, empty ); + bool b = pvt->loadImage( channel, fn ); if( !b ) return false; From 2f56a5eee4d42c384f1435d762352be9f4c18977 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:25:50 +0200 Subject: [PATCH 201/220] Statically load the empty tile image so that we don't need to have over 9000 instances of it. Also display an error message if loading fails on startup. --- .../tile_editor/tile_editor_main_window.cpp | 14 ++++++++ .../tile_editor/tile_editor_main_window.h | 2 ++ .../src/plugins/tile_editor/tile_item.cpp | 36 ++++++++++++++----- .../src/plugins/tile_editor/tile_item.h | 1 + 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 9f4851058..90f4c7131 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -37,6 +37,8 @@ #include "land_edit_dialog.h" +#include + TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::TileEditorMainWindow) @@ -44,6 +46,11 @@ TileEditorMainWindow::TileEditorMainWindow(QWidget *parent) m_ui->setupUi(this); m_undoStack = new QUndoStack(this); + if( !TileItemNode::loadEmptyPixmap() ) + { + QTimer::singleShot( 0, this, SLOT( onEmptyImageLoadFailed() ) ); + } + // Retrieve the menu manager Core::ICore *core = Core::ICore::instance(); Core::MenuManager *menuManager = core->menuManager(); @@ -341,6 +348,13 @@ void TileEditorMainWindow::onRotate( int id ) m_tileModel->setAlphaRot( id ); } +void TileEditorMainWindow::onEmptyImageLoadFailed() +{ + QMessageBox::critical( this, + tr( "Empty image load failed" ), + tr( "Couldn't load the image for empty tiles :(" ) ); +} + void TileEditorMainWindow::onActionAddTile(bool triggered) { onActionAddTile(m_ui->tileViewTabWidget->currentIndex()); diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h index 9dee6954d..d06d6deca 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.h +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.h @@ -80,6 +80,8 @@ private Q_SLOTS: void onZoomFactor(int level); void onRotate(int id); + void onEmptyImageLoadFailed(); + private: void onActionAddTile(int tabId); void onActionDeleteTile(int tabId); diff --git a/code/studio/src/plugins/tile_editor/tile_item.cpp b/code/studio/src/plugins/tile_editor/tile_item.cpp index 311b711cc..71fe336a2 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item.cpp @@ -271,6 +271,12 @@ public: bool loadImage( TileConstants::TTileChannel channel, const QString &fn ) { + if( fn.isEmpty() ) + { + pixmaps[ channel ] = TileItemNodePvt::emptyPm(); + return true; + } + QPixmap temp; bool b = temp.load( fn ); @@ -284,6 +290,17 @@ public: return true; } + static bool loadEmptyImage() + { + bool b = empty.load( ":/placeHolder/images/empty_image.png" ); + if( !b ) + { + empty = QPixmap(); + } + + return b; + } + void clearImage( TileConstants::TTileChannel channel ) { pixmaps[ channel ] = QPixmap(); @@ -293,10 +310,15 @@ public: return pixmaps[ channel ]; } + static QPixmap& emptyPm(){ return empty; } + private: QPixmap pixmaps[ TileConstants::TileChannelCount ]; + static QPixmap empty; + }; +QPixmap TileItemNodePvt::empty = QPixmap(); TileConstants::TTileChannel TileItemNode::s_displayChannel = TileConstants::TileDiffuse; TileItemNode::TileItemNode( TileConstants::TNodeTileType type, int tileId, Node *parent ) @@ -321,14 +343,7 @@ TileItemNode::~TileItemNode() bool TileItemNode::setTileFilename(TileConstants::TTileChannel channel, QString filename) { - QString fn = filename; - - if( filename.isEmpty() || ( filename == "empty" ) ) - { - fn = ":/placeHolder/images/empty_image.png"; - } - - bool b = pvt->loadImage( channel, fn ); + bool b = pvt->loadImage( channel, filename ); if( !b ) return false; @@ -346,6 +361,11 @@ QString TileItemNode::getTileFilename(TileConstants::TTileChannel channel) return itr.value(); } +bool TileItemNode::loadEmptyPixmap() +{ + return TileItemNodePvt::loadEmptyImage(); +} + QVariant TileItemNode::data(int column, int role) const { QString tileFilename = m_tileFilename[ TileItemNode::s_displayChannel ]; diff --git a/code/studio/src/plugins/tile_editor/tile_item.h b/code/studio/src/plugins/tile_editor/tile_item.h index 1af7833dd..5387a710d 100644 --- a/code/studio/src/plugins/tile_editor/tile_item.h +++ b/code/studio/src/plugins/tile_editor/tile_item.h @@ -117,6 +117,7 @@ public: static void setDisplayChannel( TileConstants::TTileChannel channel ){ s_displayChannel = channel; } static TileConstants::TTileChannel displayChannel(){ return s_displayChannel; } + static bool loadEmptyPixmap(); QVariant pixmap( TileConstants::TTileChannel channel ) const; From b41686aa444af7ceee73b8fb534f4cbe2388c101 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 17:14:59 +0200 Subject: [PATCH 202/220] If I add a 256x256 tile, maybe I should remove it as 256x256, not 128x128... --- code/studio/src/plugins/tile_editor/tile_bank.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 9a4d15469..8e4d8f511 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -329,7 +329,7 @@ bool TileBank::addTile( int setIdx, const QString &name, const QVariant &pixmap, switch( type ) { case TileConstants::Tile128: set->removeTile128( tile, m_pvt->m_bank ); break; - case TileConstants::Tile256: set->removeTile128( tile, m_pvt->m_bank ); break; + case TileConstants::Tile256: set->removeTile256( tile, m_pvt->m_bank ); break; } return false; From 0f42cb7f4969251d9913b674aa5ce6bfd995f750 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 17:40:39 +0200 Subject: [PATCH 203/220] Update the tile list right away if the image is replaced. --- code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp index 90f4c7131..4b00fb044 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_main_window.cpp @@ -827,6 +827,8 @@ void TileEditorMainWindow::onActionReplaceImage( int tabId ) QString fn = fileName.replace( '\\', '/' ); int slashIdx = fn.lastIndexOf( '/' ); m_lastTileDir = fn.left( slashIdx ); + + updateTab(); } void TileEditorMainWindow::onTileBankLoaded() From 62ea5d19cee518396173fe23955c89fd21e0a751 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 19:54:01 +0200 Subject: [PATCH 204/220] Fixed qrc path. --- code/studio/src/plugins/georges_editor/georges_dirtree_form.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui b/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui index e14857e89..64f8cc57c 100644 --- a/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui +++ b/code/studio/src/plugins/georges_editor/georges_dirtree_form.ui @@ -77,7 +77,7 @@ - + From df4755222b90bb0e7d248fe17b4f7fabbc8e50f3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:10:11 +0200 Subject: [PATCH 205/220] GUI Editor Linux build fix --- code/studio/src/plugins/gui_editor/texture_chooser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/studio/src/plugins/gui_editor/texture_chooser.cpp b/code/studio/src/plugins/gui_editor/texture_chooser.cpp index 57a0e8d51..3f988d4f3 100644 --- a/code/studio/src/plugins/gui_editor/texture_chooser.cpp +++ b/code/studio/src/plugins/gui_editor/texture_chooser.cpp @@ -20,7 +20,7 @@ #include "nel/misc/file.h" #include #include -#include +#include #include #include From d82d5ec9f666b0bebe6f7c48569a9bf17ddb2da7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:12:46 +0200 Subject: [PATCH 206/220] World Editor plugin Linux build fix. --- code/studio/src/plugins/world_editor/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/code/studio/src/plugins/world_editor/CMakeLists.txt b/code/studio/src/plugins/world_editor/CMakeLists.txt index ac5231aea..441ff5d02 100644 --- a/code/studio/src/plugins/world_editor/CMakeLists.txt +++ b/code/studio/src/plugins/world_editor/CMakeLists.txt @@ -60,6 +60,7 @@ TARGET_LINK_LIBRARIES( studio_plugin_world_editor qt_property_browser ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY} + ${LIBXML2_LIBRARIES} ) NL_DEFAULT_PROPS(studio_plugin_world_editor "Tools: Studio Plugin: World Editor") From 37e9c885b7a5d9fd6fed54dc930bbfb0897a1d74 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:59:58 +0200 Subject: [PATCH 207/220] Add the property browser library to the CPack archive when generated. --- code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt b/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt index f4ed13e0a..fa834dabf 100644 --- a/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt +++ b/code/studio/src/3rdparty/qtpropertybrowser/CMakeLists.txt @@ -96,3 +96,5 @@ ADD_DEFINITIONS(-DQT_SHARED) NL_DEFAULT_PROPS(qt_property_browser "3rdParty: Qt Property Browser 2.5") NL_ADD_RUNTIME_FLAGS(qt_property_browser) NL_ADD_LIB_SUFFIX(qt_property_browser) + +INSTALL(TARGETS qt_property_browser LIBRARY DESTINATION ${NL_LIB_PREFIX} ARCHIVE DESTINATION ${NL_LIB_PREFIX} COMPONENT libraries) From 340684e1d672e823e590a0913a586c54ae574f15 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 10 Aug 2014 15:25:59 +0200 Subject: [PATCH 208/220] Don't enter edit mode in the treeview. --- .../studio/src/plugins/georges_editor/georges_treeview_form.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_form.ui b/code/studio/src/plugins/georges_editor/georges_treeview_form.ui index 0bf52a3ea..42d9afcf9 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_form.ui +++ b/code/studio/src/plugins/georges_editor/georges_treeview_form.ui @@ -73,6 +73,9 @@ 0 + + QAbstractItemView::NoEditTriggers + true From 63fd3faad61c9e01e215b49e02fb81d63cca9baa Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 19:26:55 +0200 Subject: [PATCH 209/220] First iteration of the property browser. --- .../src/plugins/georges_editor/CMakeLists.txt | 3 +- .../plugins/georges_editor/browser_ctrl.cpp | 89 +++++++++++++++++++ .../src/plugins/georges_editor/browser_ctrl.h | 33 +++++++ .../georges_treeview_dialog.cpp | 8 ++ .../georges_editor/georges_treeview_dialog.h | 4 + .../georges_editor/georgesform_model.cpp | 2 +- 6 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl.cpp create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl.h diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index bab12b7e1..679af334e 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -15,7 +15,8 @@ SET(OVQT_PLUG_GEORGES_EDITOR_HDR georges_editor_plugin.h georges_dirtree_dialog.h georges_filesystem_model.h georges_treeview_dialog.h - expandable_headerview.h) + expandable_headerview.h + browser_ctrl.h) SET(OVQT_PLUG_GEORGES_EDITOR_UIS georges_editor_form.ui georges_dirtree_form.ui diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp new file mode 100644 index 000000000..1e9ed2606 --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -0,0 +1,89 @@ +#include "browser_ctrl.h" +#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" +#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" +#include + +#include "nel/georges/form.h" + +#include "formitem.h" + +class BrowserCtrlPvt +{ +public: + BrowserCtrlPvt() + { + mgr = new QtVariantPropertyManager(); + factory = new QtVariantEditorFactory(); + } + + ~BrowserCtrlPvt() + { + delete mgr; + mgr = NULL; + delete factory; + factory = NULL; + } + + QtVariantPropertyManager *mgr; + QtVariantEditorFactory *factory; + QtTreePropertyBrowser *m_browser; +}; + +BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : +QObject( browser ) +{ + m_pvt = new BrowserCtrlPvt(); + m_pvt->m_browser = browser; +} + +BrowserCtrl::~BrowserCtrl() +{ + delete m_pvt; + m_pvt = NULL; +} + +void BrowserCtrl::clicked( const QModelIndex &idx ) +{ + m_pvt->m_browser->clear(); + + GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); + NLGEORGES::UFormElm &root = m_form->getRootNode(); + NLGEORGES::UFormElm *node = NULL; + bool b = false; + + b = m_form->getRootNode().getNodeByName( &node, item->formName().c_str() ); + + if( !b || ( node == NULL ) ) + return; + + if( !node->isStruct() ) + return; + + NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); + for( int i = 0; i < st->Elements.size(); i++ ) + { + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + + QString key = elm.Name.c_str(); + QString value = ""; + + if( elm.Element != NULL ) + { + const NLGEORGES::UType *typ = elm.Element->getType(); + NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; + if( typ != NULL ) + ttyp = typ->getType(); + + NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); + std::string v; + atom->getValue( v, NLGEORGES::UFormElm::NoEval ); + value = v.c_str(); + } + + QtVariantProperty *p = m_pvt->mgr->addProperty( QVariant::String, key ); + p->setValue( value ); + m_pvt->m_browser->addProperty( p ); + } + +} + diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h new file mode 100644 index 000000000..52655c141 --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -0,0 +1,33 @@ +#ifndef BROWSER_CTRL_H +#define BROWSER_CTRL_H + +#include + +namespace NLGEORGES +{ + class UForm; +} + +class QtTreePropertyBrowser; +class QModelIndex; + +class BrowserCtrlPvt; + +class BrowserCtrl : public QObject +{ + Q_OBJECT +public: + BrowserCtrl( QtTreePropertyBrowser *browser ); + ~BrowserCtrl(); + void setForm( NLGEORGES::UForm *form ){ m_form = form; } + +public Q_SLOTS: + void clicked( const QModelIndex &idx ); + +private: + BrowserCtrlPvt *m_pvt; + + NLGEORGES::UForm *m_form; +}; + +#endif diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp index f1819f52a..a8e7e7451 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -43,6 +43,7 @@ #include "formitem.h" #include "formdelegate.h" #include "expandable_headerview.h" +#include "browser_ctrl.h" using namespace NLMISC; using namespace NLGEORGES; @@ -76,16 +77,22 @@ namespace GeorgesQt m_ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); + m_browserCtrl = new BrowserCtrl( m_ui.propertiesBrowser ); + connect(m_ui.treeView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&))); connect(m_ui.treeView, SIGNAL(doubleClicked (QModelIndex)), this, SLOT(doubleClicked (QModelIndex))); + connect(m_ui.treeView, SIGNAL(clicked(const QModelIndex&)), + m_browserCtrl, SLOT(clicked(const QModelIndex&))); connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); } CGeorgesTreeViewDialog::~CGeorgesTreeViewDialog() { + m_browserCtrl = NULL; + delete m_form; qDebug() << "DTOR"; } @@ -104,6 +111,7 @@ namespace GeorgesQt void CGeorgesTreeViewDialog::setForm(const CForm *form) { m_form = (UForm*)form; + m_browserCtrl->setForm( (UForm*)form ); } NLGEORGES::CForm* CGeorgesTreeViewDialog::getFormByName(const QString formName) diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h index 6f7b57acc..b2171cf03 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h @@ -32,6 +32,8 @@ // Project includes +class BrowserCtrl; + namespace NLGEORGES { class UForm; @@ -113,6 +115,8 @@ namespace GeorgesQt bool m_modified; + BrowserCtrl *m_browserCtrl; + }; /* CGeorgesTreeViewDialog */ } /* namespace GeorgesQt */ diff --git a/code/studio/src/plugins/georges_editor/georgesform_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_model.cpp index 387bc8917..2cc5c1280 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/studio/src/plugins/georges_editor/georgesform_model.cpp @@ -307,7 +307,7 @@ namespace GeorgesQt // Is a struct ? if ( (entry.getType () == NLGEORGES::UFormDfn::EntryDfn) || (entry.getType () == NLGEORGES::UFormDfn::EntryVirtualDfn) ) - { + { // Is an array of struct ? if (entry.getArrayFlag ()) { From 964a5d4e4c74d3f6856f5605a135be1bd64a02e1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 20:17:10 +0200 Subject: [PATCH 210/220] Shown properties can now be edited. --- .../plugins/georges_editor/browser_ctrl.cpp | 93 +++++++++++++------ 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 1e9ed2606..b82c7733c 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -7,6 +7,26 @@ #include "formitem.h" +QVariant::Type getValueType( const NLGEORGES::UType *typ ) +{ + QVariant::Type t = QVariant::String; + + NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; + if( typ != NULL ) + ttyp = typ->getType(); + + switch( ttyp ) + { + case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; + case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; + case NLGEORGES::UType::Double: t = QVariant::Double; break; + case NLGEORGES::UType::Color: t = QVariant::Color; break; + case NLGEORGES::UType::String: t = QVariant::String; break; + } + + return t; +} + class BrowserCtrlPvt { public: @@ -22,8 +42,52 @@ public: mgr = NULL; delete factory; factory = NULL; + m_browser = NULL; } + void setupElement( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) + { + QString key = elm.Name.c_str(); + QString value = ""; + QVariant::Type t = QVariant::String; + + if( elm.Element != NULL ) + { + t = getValueType( elm.Element->getType() ); + + NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); + std::string v; + atom->getValue( v, NLGEORGES::UFormElm::NoEval ); + value = v.c_str(); + } + + QtVariantProperty *p = mgr->addProperty( t, key ); + p->setValue( value ); + m_browser->addProperty( p ); + } + + void setupForm( NLGEORGES::CFormElmStruct *st ) + { + for( int i = 0; i < st->Elements.size(); i++ ) + { + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + setupElement( elm ); + } + + m_browser->setFactoryForManager( mgr, factory ); + } + + void clear() + { + m_browser->clear(); + } + + void setBrowser( QtTreePropertyBrowser *browser ) + { + m_browser = browser; + } + +private: QtVariantPropertyManager *mgr; QtVariantEditorFactory *factory; QtTreePropertyBrowser *m_browser; @@ -33,7 +97,7 @@ BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : QObject( browser ) { m_pvt = new BrowserCtrlPvt(); - m_pvt->m_browser = browser; + m_pvt->setBrowser( browser ); } BrowserCtrl::~BrowserCtrl() @@ -44,7 +108,7 @@ BrowserCtrl::~BrowserCtrl() void BrowserCtrl::clicked( const QModelIndex &idx ) { - m_pvt->m_browser->clear(); + m_pvt->clear(); GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); NLGEORGES::UFormElm &root = m_form->getRootNode(); @@ -60,30 +124,7 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) return; NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - for( int i = 0; i < st->Elements.size(); i++ ) - { - NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - - QString key = elm.Name.c_str(); - QString value = ""; - - if( elm.Element != NULL ) - { - const NLGEORGES::UType *typ = elm.Element->getType(); - NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; - if( typ != NULL ) - ttyp = typ->getType(); - - NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); - std::string v; - atom->getValue( v, NLGEORGES::UFormElm::NoEval ); - value = v.c_str(); - } - - QtVariantProperty *p = m_pvt->mgr->addProperty( QVariant::String, key ); - p->setValue( value ); - m_pvt->m_browser->addProperty( p ); - } + m_pvt->setupForm( st ); } From 2cea18eae8edab2cbfed487914823a1f6c875a7b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 21:00:33 +0200 Subject: [PATCH 211/220] Apply changes. --- .../plugins/georges_editor/browser_ctrl.cpp | 42 +++++++++++++++++++ .../src/plugins/georges_editor/browser_ctrl.h | 12 +++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index b82c7733c..207c665a9 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -34,6 +34,7 @@ public: { mgr = new QtVariantPropertyManager(); factory = new QtVariantEditorFactory(); + m_currentNode = NULL; } ~BrowserCtrlPvt() @@ -74,12 +75,14 @@ public: setupElement( elm ); } + m_currentNode = st; m_browser->setFactoryForManager( mgr, factory ); } void clear() { m_browser->clear(); + m_currentNode = NULL; } void setBrowser( QtTreePropertyBrowser *browser ) @@ -87,10 +90,25 @@ public: m_browser = browser; } + void onValueChanged( QtProperty *p, const QVariant &value ) + { + if( m_currentNode == NULL ) + return; + + std::string k = p->propertyName().toUtf8().constData(); + std::string v = value.toString().toUtf8().constData(); + + m_currentNode->setValueByName( v.c_str(), k.c_str() ); + } + + QtVariantPropertyManager* manager() const{ return mgr; } + private: QtVariantPropertyManager *mgr; QtVariantEditorFactory *factory; QtTreePropertyBrowser *m_browser; + + NLGEORGES::UFormElm *m_currentNode; }; BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : @@ -108,6 +126,7 @@ BrowserCtrl::~BrowserCtrl() void BrowserCtrl::clicked( const QModelIndex &idx ) { + disableMgrConnections(); m_pvt->clear(); GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); @@ -126,5 +145,28 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); m_pvt->setupForm( st ); + enableMgrConnections(); + +} + +void BrowserCtrl::onValueChanged( QtProperty *p, const QVariant &value ) +{ + m_pvt->onValueChanged( p, value ); +} + +void BrowserCtrl::enableMgrConnections() +{ + QtVariantPropertyManager *mgr = m_pvt->manager(); + + connect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), + this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); +} + +void BrowserCtrl::disableMgrConnections() +{ + QtVariantPropertyManager *mgr = m_pvt->manager(); + + disconnect( mgr, SIGNAL( valueChanged( QtProperty*, const QVariant & ) ), + this, SLOT( onValueChanged( QtProperty*, const QVariant & ) ) ); } diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h index 52655c141..da14e14c9 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -10,6 +10,8 @@ namespace NLGEORGES class QtTreePropertyBrowser; class QModelIndex; +class QVariant; +class QtProperty; class BrowserCtrlPvt; @@ -24,9 +26,15 @@ public: public Q_SLOTS: void clicked( const QModelIndex &idx ); -private: - BrowserCtrlPvt *m_pvt; +private Q_SLOTS: + void onValueChanged( QtProperty *p, const QVariant &value ); +private: + void enableMgrConnections(); + void disableMgrConnections(); + + + BrowserCtrlPvt *m_pvt; NLGEORGES::UForm *m_form; }; From 02b2fc5b81874da80dca60e1f968ceddd801bd52 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 15 Aug 2014 23:49:12 +0200 Subject: [PATCH 212/220] Fixed a crash. Setting a value into a valueless Georges node doesn't assign a type, which leads to a crash when trying to poll the value directly from the node. However if the value is polled indirectly using the node's name the value can be retrieved without a crash. --- .../src/plugins/georges_editor/browser_ctrl.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 207c665a9..5499854a9 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -35,6 +35,7 @@ public: mgr = new QtVariantPropertyManager(); factory = new QtVariantEditorFactory(); m_currentNode = NULL; + m_rootNode = NULL; } ~BrowserCtrlPvt() @@ -56,9 +57,11 @@ public: { t = getValueType( elm.Element->getType() ); - NLGEORGES::CFormElmAtom *atom = static_cast< NLGEORGES::CFormElmAtom* >( elm.Element ); + std::string formName; + elm.Element->getFormName( formName, NULL ); + std::string v; - atom->getValue( v, NLGEORGES::UFormElm::NoEval ); + m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); value = v.c_str(); } @@ -98,17 +101,21 @@ public: std::string k = p->propertyName().toUtf8().constData(); std::string v = value.toString().toUtf8().constData(); - m_currentNode->setValueByName( v.c_str(), k.c_str() ); + bool created = false; + m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); } QtVariantPropertyManager* manager() const{ return mgr; } + void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } + private: QtVariantPropertyManager *mgr; QtVariantEditorFactory *factory; QtTreePropertyBrowser *m_browser; NLGEORGES::UFormElm *m_currentNode; + NLGEORGES::CFormElm *m_rootNode; }; BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : @@ -131,6 +138,8 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) GeorgesQt::CFormItem *item = static_cast< GeorgesQt::CFormItem* >( idx.internalPointer() ); NLGEORGES::UFormElm &root = m_form->getRootNode(); + NLGEORGES::CFormElm *rootNode = dynamic_cast< NLGEORGES::CFormElm* >( &root ); + m_pvt->setRootNode( rootNode ); NLGEORGES::UFormElm *node = NULL; bool b = false; From 9128c712e69d6b7ef64f6c48053de56eda81d2f1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:01:07 +0200 Subject: [PATCH 213/220] Only add atoms to the property browser. --- .../src/plugins/georges_editor/browser_ctrl.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 5499854a9..eb2ef7508 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -47,7 +47,7 @@ public: m_browser = NULL; } - void setupElement( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) + void setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) { QString key = elm.Name.c_str(); QString value = ""; @@ -70,12 +70,15 @@ public: m_browser->addProperty( p ); } - void setupForm( NLGEORGES::CFormElmStruct *st ) + void setupStruct( NLGEORGES::CFormElmStruct *st ) { for( int i = 0; i < st->Elements.size(); i++ ) { NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - setupElement( elm ); + if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) + continue; + + setupAtom( elm ); } m_currentNode = st; @@ -152,7 +155,7 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) return; NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - m_pvt->setupForm( st ); + m_pvt->setupStruct( st ); enableMgrConnections(); From 76a7980e23b5cbfbd5cb9b6fe39bafa4b0805820 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:47:29 +0200 Subject: [PATCH 214/220] Handle selected arrays too ( show size, changing it isn't implemented yet ). --- .../plugins/georges_editor/browser_ctrl.cpp | 67 ++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index eb2ef7508..ded5737ce 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -70,18 +70,45 @@ public: m_browser->addProperty( p ); } - void setupStruct( NLGEORGES::CFormElmStruct *st ) + void setupArray( NLGEORGES::UFormElm *node ) { + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); + uint size = 0; + arr->getArraySize( size ); + + std::string name; + arr->getFormName( name, NULL ); + QString key = name.c_str(); + key = key.mid( 1 ); + + QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); + p->setValue( size ); + m_browser->addProperty( p ); + + } + + void setupStruct( NLGEORGES::UFormElm *node ) + { + NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); + for( int i = 0; i < st->Elements.size(); i++ ) { - NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) - continue; - + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; setupAtom( elm ); } + } - m_currentNode = st; + void setupNode( NLGEORGES::UFormElm *node ) + { + if( node->isStruct() ) + setupStruct( node ); + else + if( node->isArray() ) + setupArray( node ); + else + return; + + m_currentNode = node; m_browser->setFactoryForManager( mgr, factory ); } @@ -96,11 +123,8 @@ public: m_browser = browser; } - void onValueChanged( QtProperty *p, const QVariant &value ) + void onStructValueChanged( QtProperty *p, const QVariant &value ) { - if( m_currentNode == NULL ) - return; - std::string k = p->propertyName().toUtf8().constData(); std::string v = value.toString().toUtf8().constData(); @@ -108,6 +132,23 @@ public: m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); } + void onArrayValueChanged( QtProperty *p, const QVariant &value ) + { + + } + + void onValueChanged( QtProperty *p, const QVariant &value ) + { + if( m_currentNode == NULL ) + return; + + if( m_currentNode->isStruct() ) + onStructValueChanged( p, value ); + else + if( m_currentNode->isArray() ) + onArrayValueChanged( p, value ); + } + QtVariantPropertyManager* manager() const{ return mgr; } void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } @@ -151,11 +192,7 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) if( !b || ( node == NULL ) ) return; - if( !node->isStruct() ) - return; - - NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - m_pvt->setupStruct( st ); + m_pvt->setupNode( node ); enableMgrConnections(); From 3c90938c47ded5e59b1ccce7689fbc06d630ae03 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:51:30 +0200 Subject: [PATCH 215/220] Only add atoms to the property browser.. --- code/studio/src/plugins/georges_editor/browser_ctrl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index ded5737ce..1a71b57c6 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -94,6 +94,9 @@ public: for( int i = 0; i < st->Elements.size(); i++ ) { NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) + continue; + setupAtom( elm ); } } From 408e050ce22513360714216ea9dd4916e1ed2022 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 03:10:50 +0200 Subject: [PATCH 216/220] Only add atoms to the property browser.. --- code/studio/src/plugins/georges_editor/browser_ctrl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 1a71b57c6..a6dd288d8 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -97,6 +97,13 @@ public: if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) continue; + if( elm.Element == NULL ) + { + NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); + if( entry.getArrayFlag() ) + continue; + } + setupAtom( elm ); } } From d5dec4a68139ccaf2d6c8fe1e27aaaf19b12e7a7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 03:46:52 +0200 Subject: [PATCH 217/220] Use the string 'array size' as the name for the property holding the array size. --- code/studio/src/plugins/georges_editor/browser_ctrl.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index a6dd288d8..f430ff675 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -76,11 +76,7 @@ public: uint size = 0; arr->getArraySize( size ); - std::string name; - arr->getFormName( name, NULL ); - QString key = name.c_str(); - key = key.mid( 1 ); - + QString key = QObject::tr( "Array size" ); QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); p->setValue( size ); m_browser->addProperty( p ); @@ -144,6 +140,9 @@ public: void onArrayValueChanged( QtProperty *p, const QVariant &value ) { + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); + std::string formName; + arr->getFormName( formName, NULL ); } From e5a7b28e4b7bae0b21928f3a7b5a5a919f9b6c20 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 18 Aug 2014 01:50:07 +0200 Subject: [PATCH 218/220] Moved BrowserCtrlPvt to it's own files. --- .../src/plugins/georges_editor/CMakeLists.txt | 4 +- .../plugins/georges_editor/browser_ctrl.cpp | 164 +----------------- .../georges_editor/browser_ctrl_pvt.cpp | 156 +++++++++++++++++ .../plugins/georges_editor/browser_ctrl_pvt.h | 50 ++++++ 4 files changed, 210 insertions(+), 164 deletions(-) create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp create mode 100644 code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h diff --git a/code/studio/src/plugins/georges_editor/CMakeLists.txt b/code/studio/src/plugins/georges_editor/CMakeLists.txt index 679af334e..c2d3c1da7 100644 --- a/code/studio/src/plugins/georges_editor/CMakeLists.txt +++ b/code/studio/src/plugins/georges_editor/CMakeLists.txt @@ -16,7 +16,9 @@ SET(OVQT_PLUG_GEORGES_EDITOR_HDR georges_editor_plugin.h georges_filesystem_model.h georges_treeview_dialog.h expandable_headerview.h - browser_ctrl.h) + browser_ctrl.h + browser_ctrl_pvt.h + ) SET(OVQT_PLUG_GEORGES_EDITOR_UIS georges_editor_form.ui georges_dirtree_form.ui diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index f430ff675..8801894e2 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -7,169 +7,7 @@ #include "formitem.h" -QVariant::Type getValueType( const NLGEORGES::UType *typ ) -{ - QVariant::Type t = QVariant::String; - - NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; - if( typ != NULL ) - ttyp = typ->getType(); - - switch( ttyp ) - { - case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; - case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; - case NLGEORGES::UType::Double: t = QVariant::Double; break; - case NLGEORGES::UType::Color: t = QVariant::Color; break; - case NLGEORGES::UType::String: t = QVariant::String; break; - } - - return t; -} - -class BrowserCtrlPvt -{ -public: - BrowserCtrlPvt() - { - mgr = new QtVariantPropertyManager(); - factory = new QtVariantEditorFactory(); - m_currentNode = NULL; - m_rootNode = NULL; - } - - ~BrowserCtrlPvt() - { - delete mgr; - mgr = NULL; - delete factory; - factory = NULL; - m_browser = NULL; - } - - void setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) - { - QString key = elm.Name.c_str(); - QString value = ""; - QVariant::Type t = QVariant::String; - - if( elm.Element != NULL ) - { - t = getValueType( elm.Element->getType() ); - - std::string formName; - elm.Element->getFormName( formName, NULL ); - - std::string v; - m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); - value = v.c_str(); - } - - QtVariantProperty *p = mgr->addProperty( t, key ); - p->setValue( value ); - m_browser->addProperty( p ); - } - - void setupArray( NLGEORGES::UFormElm *node ) - { - NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); - uint size = 0; - arr->getArraySize( size ); - - QString key = QObject::tr( "Array size" ); - QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); - p->setValue( size ); - m_browser->addProperty( p ); - - } - - void setupStruct( NLGEORGES::UFormElm *node ) - { - NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); - - for( int i = 0; i < st->Elements.size(); i++ ) - { - NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; - if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) - continue; - - if( elm.Element == NULL ) - { - NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); - if( entry.getArrayFlag() ) - continue; - } - - setupAtom( elm ); - } - } - - void setupNode( NLGEORGES::UFormElm *node ) - { - if( node->isStruct() ) - setupStruct( node ); - else - if( node->isArray() ) - setupArray( node ); - else - return; - - m_currentNode = node; - m_browser->setFactoryForManager( mgr, factory ); - } - - void clear() - { - m_browser->clear(); - m_currentNode = NULL; - } - - void setBrowser( QtTreePropertyBrowser *browser ) - { - m_browser = browser; - } - - void onStructValueChanged( QtProperty *p, const QVariant &value ) - { - std::string k = p->propertyName().toUtf8().constData(); - std::string v = value.toString().toUtf8().constData(); - - bool created = false; - m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); - } - - void onArrayValueChanged( QtProperty *p, const QVariant &value ) - { - NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); - std::string formName; - arr->getFormName( formName, NULL ); - - } - - void onValueChanged( QtProperty *p, const QVariant &value ) - { - if( m_currentNode == NULL ) - return; - - if( m_currentNode->isStruct() ) - onStructValueChanged( p, value ); - else - if( m_currentNode->isArray() ) - onArrayValueChanged( p, value ); - } - - QtVariantPropertyManager* manager() const{ return mgr; } - - void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } - -private: - QtVariantPropertyManager *mgr; - QtVariantEditorFactory *factory; - QtTreePropertyBrowser *m_browser; - - NLGEORGES::UFormElm *m_currentNode; - NLGEORGES::CFormElm *m_rootNode; -}; +#include "browser_ctrl_pvt.h" BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : QObject( browser ) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp new file mode 100644 index 000000000..f49ebc1ba --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -0,0 +1,156 @@ +#include "browser_ctrl_pvt.h" +#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" +#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" +#include + +namespace +{ + + QVariant::Type getValueType( const NLGEORGES::UType *typ ) + { + QVariant::Type t = QVariant::String; + + NLGEORGES::UType::TType ttyp = NLGEORGES::UType::String; + if( typ != NULL ) + ttyp = typ->getType(); + + switch( ttyp ) + { + case NLGEORGES::UType::UnsignedInt: t = QVariant::UInt; break; + case NLGEORGES::UType::SignedInt: t = QVariant::Int; break; + case NLGEORGES::UType::Double: t = QVariant::Double; break; + case NLGEORGES::UType::Color: t = QVariant::Color; break; + case NLGEORGES::UType::String: t = QVariant::String; break; + } + + return t; + } + +} + + +BrowserCtrlPvt::BrowserCtrlPvt( QObject *parent ) : +QObject( parent ) +{ + mgr = new QtVariantPropertyManager(); + factory = new QtVariantEditorFactory(); + m_currentNode = NULL; + m_rootNode = NULL; +} + +BrowserCtrlPvt::~BrowserCtrlPvt() +{ + delete mgr; + mgr = NULL; + delete factory; + factory = NULL; + m_browser = NULL; +} + +void BrowserCtrlPvt::setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ) +{ + QString key = elm.Name.c_str(); + QString value = ""; + QVariant::Type t = QVariant::String; + + if( elm.Element != NULL ) + { + t = getValueType( elm.Element->getType() ); + + std::string formName; + elm.Element->getFormName( formName, NULL ); + + std::string v; + m_rootNode->getValueByName( v, formName.c_str(), NLGEORGES::UFormElm::NoEval, NULL, 0 ); + value = v.c_str(); + } + + QtVariantProperty *p = mgr->addProperty( t, key ); + p->setValue( value ); + m_browser->addProperty( p ); +} + +void BrowserCtrlPvt::setupArray( NLGEORGES::UFormElm *node ) +{ + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( node ); + uint size = 0; + arr->getArraySize( size ); + + QString key = QObject::tr( "Array size" ); + QtVariantProperty *p = mgr->addProperty( QVariant::Int, key ); + p->setValue( size ); + m_browser->addProperty( p ); + +} + +void BrowserCtrlPvt::setupStruct( NLGEORGES::UFormElm *node ) +{ + NLGEORGES::CFormElmStruct *st = static_cast< NLGEORGES::CFormElmStruct* >( node ); + + for( int i = 0; i < st->Elements.size(); i++ ) + { + NLGEORGES::CFormElmStruct::CFormElmStructElm &elm = st->Elements[ i ]; + if( ( elm.Element != NULL ) && !elm.Element->isAtom() ) + continue; + + if( elm.Element == NULL ) + { + NLGEORGES::CFormDfn::CEntry &entry = st->FormDfn->getEntry( i ); + if( entry.getArrayFlag() ) + continue; + } + + setupAtom( elm ); + } +} + +void BrowserCtrlPvt::setupNode( NLGEORGES::UFormElm *node ) +{ + if( node->isStruct() ) + setupStruct( node ); + else + if( node->isArray() ) + setupArray( node ); + else + return; + + m_currentNode = node; + m_browser->setFactoryForManager( mgr, factory ); +} + +void BrowserCtrlPvt::clear() +{ + m_browser->clear(); + m_currentNode = NULL; +} + + +void BrowserCtrlPvt::onStructValueChanged( QtProperty *p, const QVariant &value ) +{ + std::string k = p->propertyName().toUtf8().constData(); + std::string v = value.toString().toUtf8().constData(); + + bool created = false; + m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); +} + +void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) +{ + NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); + std::string formName; + arr->getFormName( formName, NULL ); +} + +void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) +{ + if( m_currentNode == NULL ) + return; + + if( m_currentNode->isStruct() ) + onStructValueChanged( p, value ); + else + if( m_currentNode->isArray() ) + onArrayValueChanged( p, value ); +} + + diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h new file mode 100644 index 000000000..51d756cfa --- /dev/null +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h @@ -0,0 +1,50 @@ +#ifndef BROWSER_CTRL_PVT_H +#define BROWSER_CTRL_PVT_H + +#include + +namespace NLGEORGES +{ + class CFormElm; + class UFormElm; + class CFormElmStruct; +} + +class QtVariantPropertyManager; +class QtVariantEditorFactory; +class QtTreePropertyBrowser; +class QVariant; +class QtProperty; + +class BrowserCtrlPvt : public QObject +{ + Q_OBJECT +public: + BrowserCtrlPvt( QObject *parent = NULL ); + ~BrowserCtrlPvt(); + + void clear(); + void setupNode( NLGEORGES::UFormElm *node ); + void onValueChanged( QtProperty *p, const QVariant &value ); + + QtVariantPropertyManager* manager() const{ return mgr; } + void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } + void setBrowser( QtTreePropertyBrowser *browser ){ m_browser = browser; } + +private: + void setupStruct( NLGEORGES::UFormElm *node ); + void setupArray( NLGEORGES::UFormElm *node ); + void setupAtom( NLGEORGES::CFormElmStruct::CFormElmStructElm &elm ); + + void onStructValueChanged( QtProperty *p, const QVariant &value ); + void onArrayValueChanged( QtProperty *p, const QVariant &value ); + + QtVariantPropertyManager *mgr; + QtVariantEditorFactory *factory; + QtTreePropertyBrowser *m_browser; + + NLGEORGES::UFormElm *m_currentNode; + NLGEORGES::CFormElm *m_rootNode; +}; + +#endif From 6b5f6da8097dd48a4c13128727ec2c5299884f5c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 18 Aug 2014 18:03:48 +0200 Subject: [PATCH 219/220] Array resize. --- .../plugins/georges_editor/browser_ctrl.cpp | 7 +++ .../src/plugins/georges_editor/browser_ctrl.h | 4 ++ .../georges_editor/browser_ctrl_pvt.cpp | 46 +++++++++++++++++++ .../plugins/georges_editor/browser_ctrl_pvt.h | 3 ++ .../src/plugins/georges_editor/formitem.cpp | 25 +++++++++- .../src/plugins/georges_editor/formitem.h | 4 ++ .../georges_treeview_dialog.cpp | 22 +++++++++ .../georges_editor/georges_treeview_dialog.h | 4 ++ .../georges_editor/georgesform_model.cpp | 40 ++++++++++++++++ .../georges_editor/georgesform_model.h | 3 ++ 10 files changed, 157 insertions(+), 1 deletion(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index 8801894e2..d881f42a2 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -14,6 +14,8 @@ QObject( browser ) { m_pvt = new BrowserCtrlPvt(); m_pvt->setBrowser( browser ); + + connect( m_pvt, SIGNAL( arrayResized( const QString&, int ) ), this, SLOT( onArrayResized( const QString&, int ) ) ); } BrowserCtrl::~BrowserCtrl() @@ -50,6 +52,11 @@ void BrowserCtrl::onValueChanged( QtProperty *p, const QVariant &value ) m_pvt->onValueChanged( p, value ); } +void BrowserCtrl::onArrayResized( const QString &name, int size ) +{ + Q_EMIT arrayResized( name, size ); +} + void BrowserCtrl::enableMgrConnections() { QtVariantPropertyManager *mgr = m_pvt->manager(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h index da14e14c9..6014b0419 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -26,8 +26,12 @@ public: public Q_SLOTS: void clicked( const QModelIndex &idx ); +Q_SIGNALS: + void arrayResized( const QString &name, int size ); + private Q_SLOTS: void onValueChanged( QtProperty *p, const QVariant &value ); + void onArrayResized( const QString &name, int size ); private: void enableMgrConnections(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp index f49ebc1ba..52eaabfa6 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -139,6 +139,52 @@ void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) NLGEORGES::CFormElmArray *arr = static_cast< NLGEORGES::CFormElmArray* >( m_currentNode ); std::string formName; arr->getFormName( formName, NULL ); + + int newSize = value.toInt(); + int oldSize = arr->Elements.size(); + + if( newSize == oldSize ) + return; + + if( newSize < oldSize ) + { + for( int i = newSize; i < oldSize; i++ ) + { + delete arr->Elements[ i ].Element; + } + + arr->Elements.resize( newSize ); + } + else + { + arr->Elements.resize( newSize ); + + + const NLGEORGES::CFormDfn *parentDfn; + const NLGEORGES::CFormDfn *nodeDfn; + uint indexDfn; + const NLGEORGES::CType *type; + NLGEORGES::UFormDfn::TEntryType entryType; + NLGEORGES::CFormElm *node; + bool created; + bool isArray; + + QString idx; + + for( int i = oldSize; i < newSize; i++ ) + { + idx.clear(); + idx += "["; + idx += QString::number( i ); + idx += "]"; + + bool b; + b = arr->createNodeByName( idx.toUtf8().constData(), &parentDfn, indexDfn, &nodeDfn, &type, &node, entryType, isArray, created ); + } + } + + QString name = formName.c_str(); + Q_EMIT arrayResized( name, newSize ); } void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h index 51d756cfa..5bf93da4a 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h @@ -31,6 +31,9 @@ public: void setRootNode( NLGEORGES::CFormElm *root ){ m_rootNode = root; } void setBrowser( QtTreePropertyBrowser *browser ){ m_browser = browser; } +Q_SIGNALS: + void arrayResized( const QString &name, int size ); + private: void setupStruct( NLGEORGES::UFormElm *node ); void setupArray( NLGEORGES::UFormElm *node ); diff --git a/code/studio/src/plugins/georges_editor/formitem.cpp b/code/studio/src/plugins/georges_editor/formitem.cpp index 426009ca3..1ca2ecbe1 100644 --- a/code/studio/src/plugins/georges_editor/formitem.cpp +++ b/code/studio/src/plugins/georges_editor/formitem.cpp @@ -38,7 +38,7 @@ namespace GeorgesQt CFormItem::~CFormItem() { - qDeleteAll(childItems); + clearChildren(); } void CFormItem::appendChild(CFormItem *item) @@ -214,6 +214,29 @@ namespace GeorgesQt return QIcon(); } + CFormItem* CFormItem::findItem( const QString &formName ) + { + CFormItem *item = NULL; + + if( _FormName.c_str() == formName ) + return this; + + for( int i = 0; i < childItems.count(); i++ ) + { + item = childItems[ i ]->findItem( formName ); + if( item != NULL ) + return item; + } + + return item; + } + + void CFormItem::clearChildren() + { + qDeleteAll( childItems ); + childItems.clear(); + } + CFormItem *CFormItem::add (TSub type, const char *name, uint structId, const char *formName, uint slot, NLGEORGES::UForm *formPtr) { CFormItem *newNode = new CFormItem(); diff --git a/code/studio/src/plugins/georges_editor/formitem.h b/code/studio/src/plugins/georges_editor/formitem.h index cc2dafece..d29dfce0c 100644 --- a/code/studio/src/plugins/georges_editor/formitem.h +++ b/code/studio/src/plugins/georges_editor/formitem.h @@ -72,6 +72,10 @@ namespace GeorgesQt QIcon getItemImage(CFormItem *rootItem); + CFormItem* findItem( const QString &formName ); + + void clearChildren(); + private: QList childItems; QList itemData; diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp index a8e7e7451..838fa8cc2 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -74,6 +74,7 @@ namespace GeorgesQt m_ui.treeViewTabWidget->setTabEnabled (2,false); m_form = 0; + m_model = NULL; m_ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu); @@ -87,11 +88,13 @@ namespace GeorgesQt m_browserCtrl, SLOT(clicked(const QModelIndex&))); connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); + connect(m_browserCtrl, SIGNAL(arrayResized(const QString&,int)), this, SLOT(onArrayResized(const QString&,int))); } CGeorgesTreeViewDialog::~CGeorgesTreeViewDialog() { m_browserCtrl = NULL; + m_model = NULL; delete m_form; qDebug() << "DTOR"; @@ -265,6 +268,8 @@ namespace GeorgesQt setWindowTitle(loadedForm); // //Modules::mainWin().getTabBar(); + + m_model = model; } } @@ -446,6 +451,23 @@ namespace GeorgesQt //} } + void CGeorgesTreeViewDialog::onArrayResized( const QString &name, int size ) + { + QModelIndex current = m_ui.treeView->currentIndex(); + QModelIndex parent = current.parent(); + int r = current.row(); + int c = current.column(); + + m_model->arrayResized( name, size ); + m_ui.treeView->reset(); + m_ui.treeView->expandAll(); + + QModelIndex idx = m_model->index( r, c, parent ); + if( !idx.isValid() ) + return; + m_ui.treeView->setCurrentIndex( idx ); + } + void CGeorgesTreeViewDialog::closeEvent(QCloseEvent *event) { Q_EMIT closing(); diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h index b2171cf03..7b40fc3ef 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.h @@ -47,6 +47,7 @@ namespace GeorgesQt { class CGeorges; + class CGeorgesFormModel; class CGeorgesTreeViewDialog: public QDockWidget { @@ -102,6 +103,8 @@ namespace GeorgesQt void filterRows(); void headerClicked(int); + void onArrayResized( const QString &name, int size ); + private: Ui::CGeorgesTreeViewDialog m_ui; ExpandableHeaderView *m_header; @@ -116,6 +119,7 @@ namespace GeorgesQt bool m_modified; BrowserCtrl *m_browserCtrl; + CGeorgesFormModel *m_model; }; /* CGeorgesTreeViewDialog */ diff --git a/code/studio/src/plugins/georges_editor/georgesform_model.cpp b/code/studio/src/plugins/georges_editor/georgesform_model.cpp index 2cc5c1280..90eaaaacd 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.cpp +++ b/code/studio/src/plugins/georges_editor/georgesform_model.cpp @@ -460,6 +460,46 @@ CFormItem *CGeorgesFormModel::addArray(CFormItem *parent, } +void CGeorgesFormModel::arrayResized( const QString &name, int size ) +{ + CFormItem *item = m_rootItem->findItem( name ); + if( item == NULL ) + return; + + NLGEORGES::UFormElm *elm = NULL; + + item->form()->getRootNode().getNodeByName( &elm, name.toUtf8().constData() ); + + if( elm == NULL ) + return; + + NLGEORGES::CFormElmArray *celm = dynamic_cast< NLGEORGES::CFormElmArray* >( elm ); + if( celm == NULL ) + return; + + item->clearChildren(); + + for( int i = 0; i < celm->Elements.size(); i++ ) + { + NLGEORGES::CFormElmArray::CElement &e = celm->Elements[ i ]; + + QString formName = name; + formName += '['; + formName += QString::number( i ); + formName += ']'; + + QString n; + if( e.Name.empty() ) + n = "#" + QString::number( i ); + else + n = e.Name.c_str(); + + item->add( CFormItem::Form, n.toUtf8().constData(), i, formName.toUtf8().constData(), 0, item->form() ); + } + +} + + /******************************************************************************/ diff --git a/code/studio/src/plugins/georges_editor/georgesform_model.h b/code/studio/src/plugins/georges_editor/georgesform_model.h index 07589b63c..4ca91398b 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.h +++ b/code/studio/src/plugins/georges_editor/georgesform_model.h @@ -74,6 +74,9 @@ namespace GeorgesQt { Q_EMIT dataChanged(index, index); } + + void arrayResized( const QString &name, int size ); + private: void setupModelData(); void loadFormData(NLGEORGES::UFormElm *rootElm, CFormItem *parent); From d4585aea4d5cf95a4d002e337eb37a8127701526 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 18 Aug 2014 19:49:32 +0200 Subject: [PATCH 220/220] Save changes. --- .../studio/src/plugins/georges_editor/browser_ctrl.cpp | 6 ++++++ code/studio/src/plugins/georges_editor/browser_ctrl.h | 2 ++ .../src/plugins/georges_editor/browser_ctrl_pvt.cpp | 3 +++ .../src/plugins/georges_editor/browser_ctrl_pvt.h | 1 + .../src/plugins/georges_editor/georges_editor_form.cpp | 10 ++++++++-- .../plugins/georges_editor/georges_treeview_dialog.cpp | 2 ++ 6 files changed, 22 insertions(+), 2 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index d881f42a2..aa431b45c 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -16,6 +16,7 @@ QObject( browser ) m_pvt->setBrowser( browser ); connect( m_pvt, SIGNAL( arrayResized( const QString&, int ) ), this, SLOT( onArrayResized( const QString&, int ) ) ); + connect( m_pvt, SIGNAL( modified() ), this, SLOT( onModified() ) ); } BrowserCtrl::~BrowserCtrl() @@ -57,6 +58,11 @@ void BrowserCtrl::onArrayResized( const QString &name, int size ) Q_EMIT arrayResized( name, size ); } +void BrowserCtrl::onModified() +{ + Q_EMIT modified(); +} + void BrowserCtrl::enableMgrConnections() { QtVariantPropertyManager *mgr = m_pvt->manager(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.h b/code/studio/src/plugins/georges_editor/browser_ctrl.h index 6014b0419..9c70f51bb 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.h @@ -28,10 +28,12 @@ public Q_SLOTS: Q_SIGNALS: void arrayResized( const QString &name, int size ); + void modified(); private Q_SLOTS: void onValueChanged( QtProperty *p, const QVariant &value ); void onArrayResized( const QString &name, int size ); + void onModified(); private: void enableMgrConnections(); diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp index 52eaabfa6..0e22765da 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -132,6 +132,8 @@ void BrowserCtrlPvt::onStructValueChanged( QtProperty *p, const QVariant &value bool created = false; m_currentNode->setValueByName( v.c_str(), k.c_str(), &created ); + + Q_EMIT modified(); } void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) @@ -185,6 +187,7 @@ void BrowserCtrlPvt::onArrayValueChanged( QtProperty *p, const QVariant &value ) QString name = formName.c_str(); Q_EMIT arrayResized( name, newSize ); + Q_EMIT modified(); } void BrowserCtrlPvt::onValueChanged( QtProperty *p, const QVariant &value ) diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h index 5bf93da4a..0d0363c1f 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.h @@ -33,6 +33,7 @@ public: Q_SIGNALS: void arrayResized( const QString &name, int size ); + void modified(); private: void setupStruct( NLGEORGES::UFormElm *node ); diff --git a/code/studio/src/plugins/georges_editor/georges_editor_form.cpp b/code/studio/src/plugins/georges_editor/georges_editor_form.cpp index a0240eef8..dc0ca409d 100644 --- a/code/studio/src/plugins/georges_editor/georges_editor_form.cpp +++ b/code/studio/src/plugins/georges_editor/georges_editor_form.cpp @@ -271,10 +271,16 @@ namespace GeorgesQt void GeorgesEditorForm::setModified () { qDebug() << "setModified"; + bool saveEnabled = false; if (m_lastActiveDock) - m_saveAction->setEnabled(m_lastActiveDock->isModified()); + saveEnabled = m_lastActiveDock->isModified(); else - m_saveAction->setEnabled(false); + saveEnabled = false; + + m_saveAction->setEnabled( saveEnabled ); + + QAction *saveAction = Core::ICore::instance()->menuManager()->action( Core::Constants::SAVE ); + saveAction->setEnabled( saveEnabled ); } void GeorgesEditorForm::focusChanged ( QWidget * old, QWidget * now ) diff --git a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp index 838fa8cc2..3ecc73045 100644 --- a/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp +++ b/code/studio/src/plugins/georges_editor/georges_treeview_dialog.cpp @@ -89,6 +89,8 @@ namespace GeorgesQt connect(m_header, SIGNAL(headerClicked(int)), this, SLOT(headerClicked(int))); connect(m_browserCtrl, SIGNAL(arrayResized(const QString&,int)), this, SLOT(onArrayResized(const QString&,int))); + + connect(m_browserCtrl, SIGNAL(modified()), this, SLOT(modifiedFile())); } CGeorgesTreeViewDialog::~CGeorgesTreeViewDialog()