From 5432f4eb584019034f3928cbbd90506deb3c6fee Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 2 Dec 2011 07:55:24 -0600 Subject: [PATCH 001/234] Changed: Added the basic UI structure of the new Tile Editor plugin. --HG-- branch : branch-tile-edit-ovqt-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 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 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 zcmV;%3_0_OP)N2bPDNB8 zb~7$DE;i7Ety%y83`0poK~#8N?OS3v(F?m$xJdyhRME=5Ft^*7RW;O03n1W zglr@sAsZwiku9Jggvcf+RVgl2i)f|QS{G0;C|0dIF7>z^Yiez4&+%ygsXcZ*e*L~T zxi5EKW`h1P(=!}$&hOlN-+OuQ{(j$bm-mLTD}PrMxT1j16)0svteh=FY-5Yqe#8;P zu+%PRU5I)_1uJ7&tb|3e*-Y*8KKbndMa-VoXZbjLPZZ?ux5L7N5m0*631v6OKJIWp(&8JKMJz&c?U<{&@>c475D-;8cY}J?!N}^`Jz+8PyXBicmJtf!d-t{4|jgv zCYN{op%n-xK3fNQLun`g3w!~bjls`V9#4Z~AJ@C#mXGQ{#LXYp;&gc&`TLSD4*{ZE zOczRzq`=|dR=eTQd#k{Om2mJ~7pP9hs9tbmA~>7S0}2B?2Vfk3ls}vR``@mTaO1^g zGKSx(1aBxl81G7g0WClQ3w1PW|221491Oi#0Yh)Nu=n*PlVZSV$87ql6At6DA3K5z4w^#d?NM6`4+Y!GkJ;l&k6H^B9*7#4 zzc=!gnL8}snJQI~vDpE;UMYj?UoMq#-Ag4f8J6Cf2F3~%6diW_rSxdrXz@*PqeX{e zM+*-`kLC|g8O_-nF`B(QY;?|b*3qm%>*&?ntfMoowT-54vW}+qSU*ka4*fK_%kn{D zN6;JbZH5bp9ol+@ZEQ5}1ag|aV5!ImoM{KjUW}*ls%tmu>^Kuo~R%;*( zT{i&<a?K zKkjx)tBF?O9T$nwG5Q}W#ST-QgP+^XV`Gsd@5wx)0_#4DDbVUX#5F(D~?W zIabNdIbrVFVhqYIOXLyWtVd*(788jLJVV4?&%4JQCo5V|tWU7oQ{$vL2~T8*7$sj$ zP}!z)8^_L5eZ!NpVIzX-J@~(t6(~SQ@HZ$xq-Oz&8LFD=mYF$eF?P92bBhl=J06ot z(nMCYo{}K7d(XPiCzUR1QinNNi2#u!LSrQ-Cmj<&$2UAN3%U_f9l`6?Y851Q>c2z* z%w7fPJDW3M_~F@D%)m;w=B~?2C24P#qw9Lk%taDN@<|tYBE&l{)msbu+;;_QWd$KmSxXZFGLL$h5lJ#V(B4NpOiTGT! z-Z*)YBqt`4?R;z|5ID(8we9tKNbL!|=y4(>S&AFFSs94G^eJW&5L7OC<-j>0C^!5t6zr&rB*n&zbpd z6A$HZHCd)sCMVg-NSIqw>BiLVdfeS@y%7{iiUgHpi7?0dUuMdJq--$b^jv-a&=z9WknbEWIfT6oERM=a-1L?SGL<8$$+&#OM{yGlA!92By@ip z*w*Ndc^9CBVIsQlt!bpYO6e+EXAFeyhKYYU0Ad%)l-m=WrYR|OEkDXQG*5vsE~{r z$(SnC_*|W|aEqu{IT*A_gIB?$V^avwvSsBKl$5MyDhc|1at*mJ31h(hx4#z~~%G4sfSz2^s`x=u( zICP~%@;kKNw|M_AWrT7> z^XcjGup|yoMAj2|@&FPbwMTv47ya_vJ)KSF5krLrR%7;7j?LWq+~tWhVcjpLO9-zq zLRzokjNdxziw8wDm_|&MYFKtWUKT)fb5G=H$Rm&kr1ytD?2CT+?Vk2J{YWtGGtzf~ zqQ$ug-0Gs`We=z|K>DWeQ-15LFCG+DqZz@kM4;ecjGWviBTtqm0jPAWHPGbdZeR4v zZ}$wXW+MpvN;Fy)K(soqbGPSZ^XYV)lStnR-sZQ?`r<+66>P*-!ytFqT>$Rp+}ff5 zM4smFvFmjZ(ZFu-Sq{eexjuSURf7G(iAm(rbEX8i=SpIThkM^dvyLPx|Gzo0hQ$qneDcV94p_ z0m`Ju$@2tQb6+yVw&Mp9W%y%?fc`6I_eSD)zF?nIn&uLSJa>I6i9C;es?!KiaeFih zfP0i>Y{Na8wz==TC;0WE-P5jz&KR^?FuZhbBS z5$DL*YDEDofCA%H7m*fF60$Kp| zVm9E!Uw-6{3Bco@$k(1s#+}*(TqignV{0fx;Fg>YKdDjUD{R8FejEnNmGAHZOb!&F zj>hw8{Z^Q>D-6ve;MS&{{1egN<15hx}#q25-oB#j-07*qoM6N<$ 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 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 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 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 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 f57c47af5471107642a3d42b7b100b9b0a45b5c3 Mon Sep 17 00:00:00 2001 From: sfb Date: Wed, 7 Dec 2011 13:46:27 -0600 Subject: [PATCH 002/234] Changed: #1409 Tile Edit Qt - Adding some of the hierarchy logic to the list views. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 96 +++++++++++++++---- .../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, 121 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 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 + //{ + // 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); + - for(int column=0; columncolumnCount(index.parent()); column++) + // 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++) { - QModelIndex child = model->index(index.row()+1, column, index.parent()); - model->setData(child, QVariant(text), Qt::EditRole); + QVector tileInfo; + tileInfo.push_back(QString("filename").append(QString::number(transPos+1))); + TileItem *transTile= new TileItem(tileInfo); + tileTrans->appendRow(transTile); } - } - else - { - QVector items; - items.push_back(QVariant(text)); - TileItem *item = new TileItem(items, 0); - model->appendRow(item); + + // 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 dfc1b0ba946b9d0376bd0b0d98550a50a42dfaba Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 9 Dec 2011 07:03:33 -0600 Subject: [PATCH 003/234] Changed: #1409 Made the tile set and tile type tabs connect. Added the context menu to each tab. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../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 17f1a286e2f1492b127dbb56c7d469091bb1f9ec Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 9 Dec 2011 08:10:02 -0600 Subject: [PATCH 004/234] Changed: #1409 Fixed some things for a sane compiler (Linux/gcc) --HG-- branch : branch-tile-edit-ovqt-plugin --- .../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 04c6c1b48ad572d49593b6967260e711ce2dcbcd Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 22 Dec 2011 19:58:59 -0600 Subject: [PATCH 005/234] Changed: #1409 Added hierarchy to the tile model, renamed the base class to 'Node' --HG-- branch : branch-tile-edit-ovqt-plugin --- .../tile_editor/tile_editor_main_window.cpp | 71 +------- .../src/plugins/tile_editor/tile_item.cpp | 172 ++++++++++++------ .../src/plugins/tile_editor/tile_item.h | 84 ++++++--- .../src/plugins/tile_editor/tile_model.cpp | 68 +++++-- .../src/plugins/tile_editor/tile_model.h | 15 +- 5 files changed, 252 insertions(+), 158 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); - - - // 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() - //} + TileSetNode *tileSet = model->createTileSetNode(text); - // 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; +} + +TileSetNode::~TileSetNode() { + qDeleteAll(m_childItems); } -TileTypeTileItem::~TileTypeTileItem() +QVariant TileSetNode::data(int column) const { - qDeleteAll(childItems); + return QVariant(m_tileSetName); } -QVariant TileTypeTileItem::data(int column) const +/////////////////////////////////////////////////// + +TileTypeNode::TileTypeNode(TNodeTileType type, Node *parent) : m_nodeTileType(type) { - QVariant val = itemData.value(column); + 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; +} + - 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 +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); + void appendRow(const QList &items); + void appendRow(Node *item); + +protected: + QList m_childItems; + QVector m_itemData; + Node *m_parentItem; +}; + +class TileSetNode : public Node +{ +public: + TileSetNode(QString tileSetName, Node *parent=0); + virtual ~TileSetNode(); + QVariant data(int column) const; - //QImage *getTileImageFromChannel(int channel); + const QString &getTileSetName(); +private: + QString m_tileSetName; +}; - //int getTileIndex() { return m_tileIndex; } - //QString getTileFilename() { return m_tileFilename; } +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; -protected: - QList childItems; - QVector itemData; - TileItem *parentItem; + TNodeTileType getTileType(); - //QMap m_tileChannels; - //int m_tileIndex; - //QString m_tileFilename; + static const char *getTileTypeName(TNodeTileType type); +private: + TNodeTileType m_nodeTileType; }; -class TileTypeTileItem : public TileItem +class TileItemNode : public Node { public: - TileTypeTileItem(const QVector &data, TileItem *parent=0); - virtual ~TileTypeTileItem(); + 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 99ec1aab27429cf584bc849633a89ee0b277f5b4 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 30 Dec 2011 14:36:51 -0600 Subject: [PATCH 006/234] 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. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../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 | 48 +++---- .../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, 444 insertions(+), 88 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())); + + //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(); + //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 +{ + if(role == Qt::DisplayRole) + return QVariant(m_tileSetName); + return QVariant(); +} + +int TileSetNode::columnCount() const { - return QVariant(m_tileSetName); + 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 m_nodeTileType; + return 1; } - -const char *TileTypeNode::getTileTypeName(TNodeTileType type) +TileModel::TNodeTileType TileTypeNode::getTileType() { - switch(type) - { - case Tile128: - return "128"; - case Tile256: - return "256"; - case TileTransition: - return "Transition"; - case TileDisplacement: - return "Displacement"; - default: - break; - } - return "UNKNOWN"; + return m_nodeTileType; } + + + /////////////////////////////////////////////////// -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); - virtual ~TileTypeNode(); - QVariant data(int column) const; - TNodeTileType getTileType(); + TileTypeNode(TileModel::TNodeTileType type, Node *parent=0); + virtual ~TileTypeNode(); + QVariant data(int column, int role) const; + int columnCount() const; - 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 f6f664452dbfb8dff05be01605c074d64480e353 Mon Sep 17 00:00:00 2001 From: sfb Date: Mon, 27 Feb 2012 08:40:23 -0600 Subject: [PATCH 007/234] Changed: #1409 Removing the tile item delegate, modifying the model with custom roles for view modes. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../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; + + painter->drawPixmap(rect.adjusted(iconPosModX, iconPosModY, iconPosModX, iconPosModY).topLeft(), tile); + - 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); + //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 5eb9d2f2a0984b404f8708bb1bab242f9fda7893 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 2 Mar 2012 14:17:38 -0600 Subject: [PATCH 008/234] Changed: #1409 Adding zoom functionality to views, trying to fix icon size problem. --HG-- branch : branch-tile-edit-ovqt-plugin --- .../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 df07598a45718dabb5823a0b27982329032f8bcd Mon Sep 17 00:00:00 2001 From: sfb Date: Mon, 17 Sep 2012 15:12:01 -0500 Subject: [PATCH 010/234] merging legacy dfn-based method into geqt. Warning: broke the build. --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/formitem.cpp | 198 ++- .../src/plugins/georges_editor/formitem.h | 17 +- .../georges_treeview_dialog.cpp | 132 +- .../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, 1144 insertions(+), 728 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; - - // 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); - - // 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; + 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())); + + // 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); + } + + 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 a42a58590eb7af9e25e3a0761502f15fae0ce4df Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 20 Sep 2012 16:39:21 -0500 Subject: [PATCH 011/234] 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. --HG-- branch : branch-features-geqt-plugin --- .../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 | 392 ++++++----------- .../src/plugins/georges_editor/formitem.h | 160 +++---- .../plugins/georges_editor/georges_editor.qrc | 7 + .../georges_treeview_dialog.cpp | 265 ++++++------ .../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, 482 insertions(+), 917 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) + 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) + { + std::string newName = value.toString().toStdString(); + _Name = newName; + + // Create an action to update the form. + } + return true; + } + + bool CFormItem::isEditable(int column) + { + // Ensure only valid types can be edited. + if(_Type == Null) + return false; + + // Make sure only the first column (name) can be editted. + if (column != 0) return false; - itemData[column] = value; - if (formElm->isAtom()) + 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) { - const NLGEORGES::UType *type = formElm->getType(); - if (type) + // 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 { - switch (type->getType()) + 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) { - case NLGEORGES::UType::UnsignedInt: - case NLGEORGES::UType::SignedInt: - case NLGEORGES::UType::Double: - case NLGEORGES::UType::String: - if (parentItem->formElm->isArray()) + if(parentDfn) { - //((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()); - } - } - } + // Not sure what the hell to do with this. Gets filename from parent dfn? } - else + return QIcon(":/images/struct.ico"); + } + else if(type == NLGEORGES::UFormDfn::EntryVirtualDfn) + { + if(node) { - 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()); - } + // 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() ? } - break; - case NLGEORGES::UType::Color: - nldebug("Color is TODO"); - break; - default: - break; + return QIcon(":/images/vstruct.ico"); } } + //return QIcon(":/images/struct.ico"); } - else - { - nldebug("setting sth other than Atom"); - } - //formElm->setValueByName(); - return true; + return QIcon(); } -// 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 *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"); - } - - 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"); -// } - } + 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; + + 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(); - - if(!index.isValid()) - return; + //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(); - 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); - - // 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); + //CGeorgesFormProxyModel * mp = dynamic_cast(m_ui.treeView->model()); + //CGeorgesFormModel *m = dynamic_cast(mp->sourceModel()); + //QModelIndex sourceIndex = mp->mapToSource(index); - 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 (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); - 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); - - // 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(); + // 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..."); - 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; - } - } + // 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); + + // // 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(); - m_ui.treeView->expandAll(); - } + // 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(); + // } - } // 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 c770c7ac78fb20a5e9147cd3a8b6583f22ace769 Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 27 Sep 2012 08:22:50 -0500 Subject: [PATCH 012/234] Added: #1306 Added undo/redo action for renaming array entry names --HG-- branch : branch-features-geqt-plugin --- .../src/plugins/georges_editor/actions.cpp | 82 ++++++++++++++++++- .../src/plugins/georges_editor/actions.h | 23 ++++++ .../src/plugins/georges_editor/formitem.cpp | 60 ++++++++------ .../src/plugins/georges_editor/formitem.h | 5 ++ .../georges_editor/georges_editor_form.cpp | 7 +- .../georges_editor/georges_editor_form.h | 3 +- 6 files changed, 149 insertions(+), 31 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; - - // Create an action to update the form. + 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; + } + } } - 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 cc5e8c043ef8c9a0d42ce48df3d1e0d778e85f11 Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 28 Sep 2012 07:33:51 -0500 Subject: [PATCH 013/234] Changed: #1306 Moved creation of undo command for form array renames to the model. --HG-- branch : branch-features-geqt-plugin --- .../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()); - } - - } - - 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()); - } - + 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); + } } - } \ 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 6560f0c4735e6367ee3852ec98ec224b66c5593e Mon Sep 17 00:00:00 2001 From: sfb Date: Fri, 28 Sep 2012 09:50:44 -0500 Subject: [PATCH 014/234] Changed: #1306 Fixed index bug with form array rename. --HG-- branch : branch-features-geqt-plugin --- .../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 f7ffb4b8656f1e2ceb6115ac7d9ff88565a2e21a Mon Sep 17 00:00:00 2001 From: sfb Date: Thu, 18 Oct 2012 20:56:31 -0500 Subject: [PATCH 015/234] GEQt Plugin: Starting to add the context menu back. --HG-- branch : branch-features-geqt-plugin --- .../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()); + + if(m) + { + CFormItem *item = m->getItem(index); - // // Right click on the "parents" item + // 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 c5cafc7accaaec1e5d647abbf743ad057397ef42 Mon Sep 17 00:00:00 2001 From: mattraykowski Date: Sun, 21 Oct 2012 13:48:02 -0700 Subject: [PATCH 016/234] Changed: Enabled custom context menu signal to open a menu at the mouse position. --HG-- branch : branch-features-geqt-plugin --- .../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 a45cf415c326c2075e4a159b8f540b8d2a54127d Mon Sep 17 00:00:00 2001 From: mattraykowski Date: Sun, 21 Oct 2012 13:58:44 -0700 Subject: [PATCH 017/234] Changed: if-statements for context menu selection - no logic --HG-- branch : branch-features-geqt-plugin --- .../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 fd5d961ba758ccd37215c822b4a748cc755b5110 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Apr 2014 00:49:17 +0200 Subject: [PATCH 018/234] Build fixes. --HG-- branch : gsoc2014-dfighter --- .../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 4f39a58e310a073f7e87b4840356f5b54cf04fff Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Apr 2014 02:10:14 +0200 Subject: [PATCH 019/234] Tile Editor crash fixes. --HG-- branch : gsoc2014-dfighter --- .../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 91f859bc8a2a2509e85bcd0ad04b0e39bdd3fbf0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 6 May 2014 01:30:28 +0200 Subject: [PATCH 020/234] Moved ovqt to /code/studio --HG-- branch : gsoc2014-dfighter --- 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 zcmV+c7XImpP)N2bPDNB8 zb~7$DE;i7Ety%y86@E!XK~#8N?OS(Ll~=aEC}6=t@4bWcdK(um9qy&~-W9MRV#5Z; zo>;IX8Uu>m*c*1ECZ@kkl1Zk|WLoCUn)mYFJZH_U>A$!4aXua*Du}w?A7QP%zVBYX za(=(P&u-^jne5xYZyETOffvC*P*Bh!yyc zJ?R^e)$QmSzuDe7F78E)=Y_u`EiLVvpx_X=d8**(ngD0_WO(@K;2V&QpwL1@$jgzG zHXHsy*{v^paL@aNw)WvhF&f=JoLtqIF>?!!o%{@aSAT}A`7eBc&-;b`L3tbegK{x@ z-p)r7aQXVr5f)Vn2iHXX^B&KrpKoIyGtJvSbFY_7B(uwM-dSmUUb~kHv<77`M7cW z>&Frhn=k{`_L_z#kt+S)%06bCyLb9_BKZ6E&hf#+z3-{7vvJUP(jdR4(1m3k2ZRTY zQdUBr-S!0mO&|PV8r+h=&;r&fHf%ckSnzBCafyvQ4L-B5mYY0jkXCjY3v!xohenpb z!6kw2ZMsJ!tDbb=hKD~Lf2x+W6UDo^?j&4bM3mdf! zk+YQt=jfV*l`kE6B6xn@%UjOV^@&hwYCre#%Y0-$Kvv>G&;B7Rz{@W~gijuWK6}AE z8lUp1K|bn62Pe66a$3_@JV%e8{_aCyIII%z z7r<7-&moJrM84wzBIt8iw5sa2uAZsL%w34{mwqgs&;G?PFb73tEANpq&R;A%!as`E6_Y7SMy_VB~Sg3{Z(9MK zJ_m(`Z=#2}&d3{vB97za9l<`<796hmX_jT+) z{2_V|eLzP^-ovgvm!VK)z{l5D2muzN(P;i5m&+By*6>I!q^a-))c{z%{)8CRK-qWj zeWWUM*b?E1Gil-dvP zwI5EUgbLXi?G3*%GAMoJ*!9LObobsB@xHtF9qj43iAZ@4f}_-Uc~>`PE?xn-Hi=9> z5Y%|NI1)@Fx|R~0yG#I2g`WNIJ|MZd^HFSLij&D9LQW(FW2TEGq6kE?k-?n+nXJrN zCbJs&LRXp0$wwxuk292gs2VGSACb}OVU0Hv0);H|v4^|N05R%vytd~pyiSqi^`2X3 zYFUTKxO6lvT!#0){4qA|=|y}NB~Y4pCgAN6fg0|`W>$(x;n8J(p~3?@c3sDwy>HWC z?ucX4>@Ijrv_p@|TMYbgtRD)kCqp?__D#HjEN3|Hped1=WNh&BKq4&5Yy$SHeZ+IB zY^TD0ybV%xbHO3*jow?(7uO2Fht6NYJD>jm8(!-cpRE-2R zJK`~!TPd9V0Sur>8Vne`MLPieJcOL=n(;oh`PpRlvP$k zmz$5!C^@pSsD$?N8hUKrzN*i|A`AW;sVIjcrUnEYc1~JY+N!}x(30i7A{*@5c}2+P zZGEB{As=UmeF_h33bYsDEY8Hdd$i!C`zeo|uNZ59X=4nK=j{tc;(hIJ?>&M`cR#}A zcRv;~zjK`+fF+iaA}w8$Szd#>mW8M%NzS9DY^olq>FG>>^^oHW4p9@}C|KDkg|@i{ z;G~Be8UukdcrIYLkg>Fqqttp5%~Lnj*i3<%=B<;FS;4a+z-u?i6?|g_eH{ZcaU9Sme`10<(ICAlt_+FB(y@wD-ej_P4nF(+i za(odHayYw$AR&3W&@O`>3OIw`vi%Z@%R69g9*Bi*=7NBj@rGpnV_$S~{;6xXar)XVoPX;bT)6!nF5G#a$oSv^8TcKax2;-F(<2`7@$sB3 z4&5uD^pPBdA6Bh7K)~;tIfIpiK})i!>!N5y*_Z`jm9H)KL^y-Y6)JLolguJVJ^v+A ztnAg(6ZJKSNy{dat`(YPK<5eg`CISe90{LG-$}<)*Y9BenLd#pu!D@FY2iOD09tK4 zS%CM@(Mh3Dz|+$YTeqJk(3c(n&K4mFgJzU>URo{OntI`_JFJd{g*>bjk-3a*BkoPtc_2A|bUDg~f9b z9+d-I`{(;qEbwfS*Cvjy^#EYkVMZ?%A<00o=v4o8*jzu4Z^W+zAwb5knSW zW?(w`SrCw*ujtYj*9h?4Z=L~zl>qaR=e_jZ)}DjVl~jprP@STOG9d*S1(m36T8c%> zc4O7rW0=$Ws#t!bR6gY~1o&g!#)D)9eFXkNtxMqf$Q@kj0>hpNsJEMf-C>TPlOS>t`XI!1qwR9|(5vdHed!Lfdha9Y$%i6aurbqN9sIA4bROBcgxE z!WPR7S8A!}K9T^Q0{W~*al^*V=Y;kL0_Su7o~5#OEo>*bA1#X-3Y7{Nlh@-TIKvUrFM8HFfIAXkVxe_7a8MHc6Lcq(Z6<)EE5}_QG zrcO@}`3LvmB?8vJat18^K{;?WFvK$Q1Fr_#A=Shf)uzV3rV`g^BqW$xN1NuAx12Ak zorRo=TI@e{0VgTkNuUQFxdJSnK8s8~moyrIwDdf5ywol760THf-SRJ#vM;f)Rryg8 z=T1eOzm;uFgr#kaf)xAcTENRY@{)&l>Kt=Qg$ECw7(DIfl_vTC5_mqARlNjz6G!MK z8w&zfdzwQ#ZYVT+8crk@Fuhi5v5BJ@}zRui6rQ}kW7c02@W$^1>J}o*!-ku2{ z#<0fA96N(-(O_eO(y7LOs+nY@dE5(#XcxJ<>OfJ|qJPGc7E2qNarpe@e((%f0?tPc zgLy=dCOwNZAB%>@H3a;i0ADxbWif53WA*X4sZ@?Vk3U)(`yM+IUbSKHlGIUup9_{0 z6C**ujzAj}kYmi5X!w_+$zxZ$%4Ad<-T$+e8BMh?4b7t3;;1gG^>5nr8psneP&Km! zM=8mXw9UukSKjLXypN^?*Z-=N42tDRWbWI<0xhpIu&{IEx$fz!i+>*2#WQJct>JXLzSEfWi0gp+INed1Ow+I*DI_TT1LD3+`#jL z$)Pke(;OLC`%D5)0VZJOf-Z!NpCEdAOPr?&0=7-F!WvIARG3pklxhT?CQOpk7$f)w zYoH`RO$(QTGdKybq&s{XkW;OLUL zhF`=PAcJS%l5n4(b=F3BO|pVNk+9HlGP?XNg>3b+5VF!`3PPx~^|!TyDoH264+hSl zB|`R|JTJ^%otBHdk~S<^(JO?3a|m9te7|tY9O9S+>RAli@jew%s@VEZT|81St7XRn z;Moe802bZ_=4crRcS958OfkkX=gHXQZHf&ZQ_<=$2`Wzy(q;x47d)tWN#ha$3_iDd zIyAa`RMd6|z>;uZ;=b%Bf7FY)^LL4T0^|VyK)Y6kPII3M@qnAi!zSbuED?p$Z4!M4S3JY@P3 za0V~s-AtC9lM3DeaR`q|p#mjCbZNMCb+qsL0|YQ=c7iNi!WPyyBPpj0vs%0QwakDA ziv(UeHqG9~(?Bev$0s+BswepX0sg^x^W&3e3hyszeJIT{cqW0vQ(;9Lg{=Fnsrc*y zQLM1$4_~<24_?x`1fKs_)-)F>d6j5g{OUvC2LoQ%zPH~37A)x@f3O#gv%0_u8L_UwMvkYiyv?ljc1iCC!)Dc2e`97zx?;>+z(#5|Os9*}nS$;1Xy) zG7;S9sF~A7)n7H*mh8e}GH*%a430xxW$iivn1M<%_%mNyRkvQG#G#SJUyh0ZdnbiY zTw=rDxgpA1S*4ISSo;iq}N(DKUfk zd>N&+ShW0g;p`Y#>%u*>Go)3dx4h4g8?;OUgOoHr@SI7R)v{AW1aJS0dk!v|(Qlpe z_SYSzo!nv*BRip?P5&rTGn=Vxm5%+eYx z?R?{3;jLF}i=o7e%(w({Rn@1obLoc-!5LVOFPU&rr06)EX zi!gmn{EW6I4VFl7pzUzqV~3}Rss4$RTfF;|?s=yFryoDaiP}RM(MxP?-3roeEm#D^nxE!IkV+j-MmF2 z&*u=yQz3y;jk3Bi%@IQLN!+ZX(o3UW&r@T1HRbJDgN2bPDNB8 zb~7$DE;i7Ety%y84q-_|K~#8N?VAa7RMi>B-!e;PGRY*9l{F!dKnMxh6Cl83lFVc! z`@XO2C{P3sXk)F)QbADK(~8RxS!72<1VyA++|a7^C|Hl@s7Nb%tf#G75&8Ok_r8~z zutuAwCl=26pZng+%gz1$zwdtUzB_{;T>p37f$I)jcR*7I96CX8`lCh&Le5ldn*_nN zOppqHFBwaA>dh5L^}Y>n8-hDNFokxWwhZY!6A;$?rpdqPVL_ZSSrF1hO^2sl=gx9L zF4}1d?l@@;U+_h6%qT{p=OpvAcJ0QfVb7AW`0e1>Zji0@ptsh6;8h8-xeBboEf5qw7lw`hB}8Ye zf`qK~kdXTzq?K<4N7Lhw-?1068@J)lRsv=W8q)c>AWR9?aHv{zohHeay3f6W+Q8Ly z1S%H44sCb54;?E{!^|~jVa~eGU^Z%&s&`Ox*=s*#W(0@L0?Ax~nNzY#!@+9N zbylb)q~mMfK{GB3?-~7>2ulVK^c*x`4uj_kPrMEE<`U3*m+#kNlp6Nw80r(+`5)Wx zS-lM4kRGY;F$GlUS@)d9>A($0$X*Acu?R%(n&TP{R*SA3BhY|vf+OZ$GyPcxu=$VX zuw#BsMkMEL071$H$*=LG7NgX#Pe-IBxbxhQsQEnxs1fc}{L~CUXjT}}fSGID2Bem4 z#wS5G=>6-@XgF9cy3UL?1$KNJ7PIJ*47k_;$^duztMHTopMt$%FB;$gqpjf+Ek>zf zpN=?VV8?eOVwYTEK(Fdg8K9&;ncz-;Za_}k0cLp{)qiK2e)r#?3)@a?JAQM9seQ$1wmNKI@e#Bw z{}5X5`iQCJ&JUPe9h3nMF!;9&JOczTmliQ*HOVP=l)e8yIy4{>Uw8B8zXExvTuFUHSa~#%S!tqIOo2^ zl!C9wWB^X5foFi;zXirjSjw9f4)@INC6N*~(n9g5-tXan)sf1R7 zWI+4CGr(vg1J*(o0y-3BA+Tc>p3gjnfX_2!&iErrZRz+JJGW0i2JzD#MFZ?026PNG z1MF!gTQfvWxfkpRXh&euR6L$K9nYs9W#Ci0o`Wf!M-@GH(fLsrU-SqXFcqYMXn;AW z86va)08D5>KJ0v}1N_rM1wj4%1t+a<>Li00B_u!k`LD9SVHPKWK2^BkFB7*j) zUjqcaTxT7l9@0Ch!@t z7koY1jPQD7FP4FVnBu{O4*AgpW0KVz~(RU zQT8n@X>n^CEFsfz+j=JGP)6M9vV=|tpOAJi2R4DuS_7iF93(?A=q;t-WoyLk?uC$C zw;v|7A{+?;Co~^|2~7uCn~rUI(;-M}Bpp=5&r=%?q7Fbz-a}xtlw3ijcwLoxPqA{X z3|mqu7`#gmIty@@8uYf7BZ4s5>na9JG>C?x_hm~J+lZiLs32y8DCdBz%LUm~2Ik;q zunnIH0g;PfNWyI}a^f1C>-R%^$yP|J+QSA;(M=~vYEfwl@PuZ9C)lUheH@g-rqt6l zeon_J_550L-GNKwc|EE2NxY9Msdhi=N#*`0A+hEO2#Na@GXR&<9}8kmSRc~gQ6l-& zohSH^n57V3x`TC21&bH0!#(XJj4YqKZm}pUO2sHMu?RnfI-rOfz~N}{mqOCd2*y*1 zHTw~YL%K!hPcS9c>{G;#!!zy$QOW|@x9(d(m!I7Sc)GstJm;AL6U_0YBf5Ege73L_b%L zqw_c7l*|XoRCYo1u3Xkfc=fi)UXpLkvoaPkFW)Lise6J!tKtRB9cezFx!mcEQKcxe zNOO3q3CY+Oj~JyWfpZWJLjW99J$7H?;3_;_A7A-6YA;^f%Ubm~wrmF&{cAzQ0Lngf z`vf6F|2++$+cQJ-*2Yt!p%ARYX2C=RR>9SjSAo^m6FvpOlW1NdJk8A%glFJNnsP9T z9FHbRg;PPP<&a$Jb@w%b-UD$JyL-t8$18}K`hE@XVMd4i0C?qB#LPIofAeRelI8bYh0!lXba)$%#YL3rAFLS72U!Q(3SUO^l_wtQEQg2&y8@VJNITle6Z-R@^FFK}E5IM?Hq>P!Z(xvoT=3RPT% zI&a;;SAr+tn9^N6a-Z*D;G`%VkI{-n57#O>|EA}0v4gAFe*c%Dlf26|=)9{z?^6M> zrQ3QQZ7l7TXEC+$G|zh;PkSK&qaKfoBwnz{04iD+M|u~FIKiq>rsJ_CJDEI>$ChyL zu_fCfx_BG-48@{{sc#5uJ0psY;r)*8?$B=3nJW*-xa>9g*CW{Oo~WxP#ACF_v*N~6 zK3;*RIqzAl_#E~WkFpBe8M{rakch@_XPI@RijVfW2O-_H(<=P$6$2PRv0p2 z4U4?aTKAn~t?j>}cWoE#Lu5TdZamcZ}@G@ zfbgshAXCvZm*M9I%^L(^l6>uP_v;<@QIe(hV|+&kYuH?66^4;liX26qN1i{UdBmxu z%FR=s;3=Y>k#?s!haX);z}y5n9$oYpMCNbeMNglHso(x0zPFhB6|K*miJ1wKwE-7O zPOwER=&A0M_6gOP`jxwS44^sBt2Qra7e`)Aa~0MNOwe3Wg^xj0!B*T8n2j$vIau^M zPUG8ZU*7QgjP$*4#8>4kTr&Sl#MkD)s3n*QyCD(b6RUQi0Xsc1fWR*gPZ{6|?g>xF z3|x_I>@ED$qJWmKL_=}b_a3kozaWY^WqQAcbF_C5j7#Q}+MSS8y%V4P+yM82#U1&J zQ(c|sSByLwFer63i@fYx3-~m;+Rly^nAhl&_U8QXy<5tJVaeT)TC;i`#$uEI&-M= zcjkcN3%JV+!%|iv__m(4yZTt`^>{;Y_KYvsqG&S&CoV_$98CZE^O8?>oAv|m&%fZ6 zVDJtu-00w;<^X_*Z598dnR##DVy= z`2>T}uVRK6zE&#B7Q^EU~4@oNUoqCdB9ryIftLY zr{S31T+K}2nZQlpqR4Mz@(H^US9(tTK(zTEf}9(t#b|z_J{>lLU(*SlH)evE2cZdf z!59U8H16m`7j1$dw#>yfzJJ|0ovFC=CmN`hf7UTrZ)<)_NAnv~JSeUkP1uau1Vd7n z^R&m^CcU*BKgh@!h()h2=4FK&gIiDPyvy+s=K?=`iyS&(1y+27w-kaYq+*jGr2p9O z_I(+6f8LWd+!)k+N;c6axBNp`gUJa)ql=%Ht;s*pyM2H1^{Fq%2tz>ayRr$N^gZ$&5MeHIg!(${Zp{A}N2bPDNB8 zb~7$DE;i7Ety%y8BgjcaK~#8N?Og|$l-0SOZGfPF#+aCxXksKvOk#>kG)D1;8}KTU z2%+r4c367vz4s=)N)?a}B26&T(GZOyXixzw7C;mgSlDyl_h-J%=gIkJW|xKN%*^wg z=dUxnbKdvs-}xsHh`-`95TAkg48&(3J_GR?h|fTL2I4btv1cGFD=V>S)20>j^75|3 zsEqyln>1-s1^c&RRKorZjT<+vSgl&Mgp2*Z#6SNM%|LE$ZbEi;c6k6?7l2P~)~wlj zjQtoVn>TN6IIw>P<0!^K-19Vu(6fI1`jzgz_uk}MwQ9x5aEY)g(LV#w%K*sx0Q@9? z`a%2l?ah!OL(JsKlg*qtbIh`3%gmZJYs^zmJ!Lj**kCqo+GL)7`f0Ob#R@Ze^k`GN zcI^UyzXzYwJtrsU+7kWe;vaVLW*{RYqdcTO6~J%r+O_L(0={_hVh`B)^XHo}W5$?% z{rZ`1-MX31ojaS39XooXQ>RV__nTh5dYMt9MtSdf{PD+m@7WeDTD*$S%K#Csx_JM2 z{F5(e1^{{~jJqK1Yr1#u{^hJ$v&@rEK53>+o92PqrcE19-BT0v?%mr=m@vUS@x&8m z;lhPx#*7)JZ{NPAZQHh{VZ(+dJw4rY>C(m17Hik8^~iwtoB|Qn!$RXLIMyHLF*zHX}xiFgP|Kgf}SN>({S0Z@>MvId|@yalPJu|9!K0 z^JeqtqmLR$yf;W1eiqL!S+d0R?Ah}){?;gvq(aGli} z-LhrNLf|Rw1pc$nJ~IUc1y11Ylll4i=JnTK_p}5*i$tIXnLd5G*}i?dnKy6VIhc*j zAl@&F^-ss&R5CMwu&y#Z_uWv{1yuR8<0A1LI&|lJ-b$diULT4Z!w3AL`%xThsUSf< zIy!kG_1w~N`{a{PBEhvt_nba`+6x=$SC9nM2qeX>UAxTq@#D`y6Fdr1UU6aHEdK7W zGr(*f?0#oBb*BkF)iS|o*RGxC^`AO*sz|^V<>s?z&ze_WdBrmWLV`Yh`j}^)dB)6~ zIrB8gF%5ZxI0?d{cmX$Hf-6D#Kca&swwa;b?%lf$0lE|~nuLJ^2YSRK5qk9K;f0Hc zK+eKx91l%U@dCbL{H=a7fFw^T5MUZ(bY|-a0PXQV|M|~iJ9@<>%*P*p?1hIU00&9P z@N?0kMKlu=p{3$sVo6guH8u4YNYs2t>8Hx4r~lGRFI{r*g)}Emp7eYUApt|i<;#~d z`Zxzd%#UXdOOOFos#Hm+S+nKPX3+_e$zYg+ zvL!JGG5r|`{i(()oIXhlFih$Bk zp>0t8J4bcOe7i`Q2G0gbgJ}aM;Lu~&K)LpL4+m{}Q3ln&9&9%oJa}-SW5{q8jV1XY z_Hd9Oo+t{%1E^2n-?e}QU>ew#FagPLE5Hem8W;)3AI@EkKii60%vaV8Kb4w~h!8nG$^29I4s-y{1cPMq-G$1TUcefzvJHc7z9fZ0O$HYcG4YNOg2PZYUG z00Q(ub*+GHSoEm5fWrpO1+E`R;Q$n{WUIlHbL=|e(BRtFjvqhn-6KPe*;GP8lLRat zam@lk+|Q6ftd5j%oCG!rP*H0KX*tK1ZxVouJ6MmmffO(_C|W9QVD+&Eiu=5#fg^Y_ z?0b2hT1ke!*S>c2=uyMLo<(Xil7I_SNNPB_2SJD$@szQ}01zM*S|Fd#uL;N`sSLS~TRHdav(FZifWE=jty@Wg1JDG2h`=|F zom*fZD}w-^(+OnjHytRJU;V(;AZjoL7}>f&)d1N5`d!l?%RWOtJwE*KL&IU8r{vQN zP!q7jh?!1&&$p2%imy2kia+$wL&=z+Lkyi5Lz4g`!pkqe?2$kNslnBNYmn^o0*VG) z1L+4I@8Nspy58F0fAGNv#vZ)?$dM!7!WFJS;`bs6xE2AO#;+m!c}MJsd6;hs0*po@ zNP%S4I9Ut{If(?qmTm#ZmN*;iP*UmwmLSS`y|3>Tpb4%Ec%I`m8SlOKp0|iax{BEJ zLQODb%9OvuPl%I%+<+fY6%uibv9mN?&=+7ga3s=7pk06o0W_!@9C?ohRbRJ3*4LQ) zv5$GqHAn)cy6NPy?QPt+ah@iC-}4HKM>T5Hi0$YgEiJ7yCSn;EgY@s;zmNnp37kAX zRjh&alSW%2ZGc^Xxq#*WA@|C49`ig0+sQfPSYP8gE?i|B83|4jFnvrCAX)S=qXW!A zZ1)nt8N3H-@)#F{u;ofL0eb{&>DCgfL9r#-2G&j^BCb9is=&Gh0Y4 zM*{HsF*@MGD^Nu|0uz{l&ghhw^$U{QN4?FFvfUMQ9EtR&Kw!!t2T0gMu^8)l+Z@pz?*aXnm{`Iea zd20_z01ie8Y(K|y3JOM#7_p;q!-j3rYuEmMOlkv|f*NSOKF+)VCx#?oOEzrfe-OY0 zy4Yb2vY%A*ybTnOT~e%p)z>w!Bq;~aX;R2}y=BT+lYm4(XRKL_jOd(+6VJBG$~v6= z;DcFNcia(Mg(MVBk}(+rQB*lYRVmFDOsKG5z?NngxHf<;Np=Cxb2gy**bi*`9s&B$ zp+knlMF5_E@x>Rt$JgX!XPaz1x+Xg{)ilLpY=+|bM)Q#~=wHA7=ULZW)9;Z$;L4cN z2Ji>I%_ZWpP((}tohGJREz z`R7eXJfS4JK?9Rhx30eWq~`|mf8Rjq0URj80(KMcWYQ^Q(SYf$a`ZSY-^ECAai(C^jv96%JX6a_DWp9Ao7YSuKl_uON0 zZ@9rUOing+6!=1drXa-xXoAMc$@~8j2vmhhhz%0J6nqPkzlQk%W(ma~;3Cr3AVpeY zUAEd!ecM2~B-;j5jzyX&(S=eSlyWWYd>R>tzK6&2;psQc%sj95A^Ew#|Gmk+>MGM9 z2z*0q+hTOU$iWaoWG5z?$>qzNW+^F$;TYZ*Gv)x1!S#^-9n1$1cp(9+Yb1dORG7O?!JT7dfx+Z_bn1+b7pZ#@!Vyo#2w8Sr6p;pykptLNGLoV)Kf=@lw?;CC!n z&Mf%h56zC-Z#TQ{xWnxJ?QhLajO9Q2k?D2$<(^5%N=Pu1a6d?J9OmFp{}%{E|5MDW zSFfG`O>i6hfWurrNE1L3u(-k^3xN#feTM>Ht7gA_A%Y8Bo)aQ4LXmxYyB80;m;_&@ z3BtWxf?una$p*-20KFO1{>r0bjOjkt=9ky0mEuB1}E62|k7D?@V-=J(+(-~lG{KYT+4Lk@y zBJ2Y293+6}{lhE>@LKW-`gZsZdMt-I$c8Cko?zy;zfIHd7RKz+iw@RnhXN2Ys>fY{Qmv>&073QNgFt(xk2zV0dOkPxx-=ax5AEl z(k_xu0tEL-fSt7W0Dp%i^&%Z`@DnZB?&H-~#{ES6?+8HVJrcKVtk9c)D3zmatjasa@M- zKw>jtrzd>>`(`V^6|f7{eozDK1S#kb5PUj(wv@}UfG-5l=Vu{0Xo%>bCA7?J`WeZ| zufZJL9rc<3ZB&Wy2kM}6=u3IRC`rJ`VB^M(AxWSC4<+G#*F4}M^?MQKEyDw(TCmHf zeti%8blCYEN+hIn2Y}vr*InlcfFT+{q<#m$-vN8iSYN=^V29e@3X>vZ{598@1|UH@ zkZ$gGzf05b50K#2s3!rmKoXajAys^ujir()WV_XtEn5mhG?&WP;0hr^0WQ}FJ{N<& zj7Qnd!-Jxj;K`=5htzJy%{QB7ki;b@>=1Yld}RE*fql^cRQcPf@+tL}eJAJ|T<+UM zu&;0V`OnQ5m;k1Zdm+ETJVAOOup1e}=>K6XB#Bbs1dc<|=nQ{TKuExzLOylW_TWR= za#8i6wgjIsKC^pyjT(8*UN-9Z>5%v~aQM~%Fp+#AK_MBS1w5$-_}haj-w#}ZD#Hfc zMS#uFJVQ_~APEM71e313vH)r3weSh9j(Sbds8OS<;S?@~KTyD*fswWPd;%GB1b$w; zCPOIDsqQ%h{E^ETZcToD_>}^wy9ZBE^HqR4q zO$fjJr+@lW(-EN|8cED3)D1>~1oaXUCP5QajCvBFo9G5OgL~LWB0Ys90@KIrE)Heu z!+}rWIsT3=p24V0GP}oGe)hfhnp8-AAB;`R)&GaH7*M|a8T1$otQHH2BKQM8#^YJuVd02jp_l`bf&jX_ zcmbahZWBSIo{gM;!w*PwN6%hX(9_QZkZDl0qhN2h(US-GTJ>|E!1LO+pvvDG1l|QO z0VR-H6Ue>|zP`_OZN-m&?4^vU31-15?0@;?U!siMBkHw4aJktdSXp!wk8LX?0K1C# zq)#2n`ANMHL4&^$ze3s>j-@C0fBB0^M>;kG&fYkLU|WOW+xDIWAo!GeR{OM?j|5mD zgbQFf_qU(@>?>M<$1)b6%GfAaJbDb8phxM_CqaVxs3Jyp1rgz45~RN`p5U3UokE%g z{-mtf^Ke^g3`)Kvc-Xv2PoD*yMl8#se$N=6z>AvKCV(oRlD{n&;)&D?ur_!uphMlG z!FCa0^DVb{wF34VG(*Plagd-@QqmC+;Ez$?RRn*4zb3v=o^--O z@f6S&=sn0rjGv7YPd>h^@BG-faqVHj2yvrkouQcK9+|y$fH}BDAFX5#EwWk zf3ajHe=vd%f~3u-vNpkWlhzx!j)jk2bi`ht075RXV`1~R56!HhA`6w4n0)o$q zA{U|1iENCe!mMAJ^1AH&9|KNk3 z~0+NCqMl=yw$m@IHqhCJ*9l2?ksNs+lk$fQl zj|=w!zSw&|0{E%yNY1-})u0ks*Wf*JUf(|zy#r|o59t)H1POW~M*uC*=iX>8A)}Ls ztBvZ~3r%FLKCXF^&!P?`KND)7)it(cZ)OZ1l={NNPEZqUMJ12myMWiK+y%6sD%X-t z09|Tdz-8*!j{tt>HzJ2I65p#XOaU{P%U~K>B`1H1MJF|oCy3rfCjgn{;{|9RE08q? zT$-JomF0n-8(y0`@UA%r-I)d{*=*`3Utg zF)|w)obae>i47`DO~~I4%KY%{hT>1p)NIVOK>D=UlW6p?neZkUkfeQ z8re*)Mq*3ZOk_1v6B0HdGWc#(lK}aF7U&;1(;rQx9{60E4V#~dm^l@|v%6+Cojzvq zn8T;~4~BT#g5XPR9}avwJ`V-7w%J8h>vDf6zU#g2iOGMtKeZPo<38$l5ulM zceohc&#BYW>qmf4HeUnlA_A{(fQFMH_fJA22~9yKeD9SgBDF4E`U^OP*;sWHo&G?* zdi9dfwY#tv(!#@0;K_w8ZwOV$${7hT8{R(wmq8LRt-B>yvkwKnEB+4U#mhAtFq;73 zY`ROj^?L+t7XjA66!e8Zz$DRFL_ABN{ooHAgHu>3YPCSlBab}N_<;vbPeygG844zp z0D{l$OsGPUdYS-g1A6*?d3-JLE{|P%@_r^jOSbLUg#*`h-B$H30+0-Heignm{hlnC z0_F2;2z3 z5B23L-QbfsNCIZcRw8%qfe*E>!Hy(1FJ>STr_Ppk+nE#KT*T1e*>*jY%GbWYdVEhA z{0uaXc&2ay$bfnQBZLF+2coxVgfDkLp273}V5mPXu%IU3pcFh4jPYF+xo{ag8+;cT zLfQRD)VfW8a8jCTy zy4PAjUt0}_upLYyA4ahhjV~R`l*z~Zz+y)63mvm%U=E(_90(M&1N-FxP0R@pFd;!W z@coK1I(P5q)koskg_CYk=USq}kwIUV_fJPSNG&iF52s@37(%fDa}wRZhzgef08ZgH zYJpZ@KNnaqDj0#uuxs@$BDiwynh@c_IXh9~0^62!Tj~j*2H$1t1!R3M-^1gzNCa^_ z1* zAK5YH$Vq}M3@*ivB-VE&azc^7PxAf1cWD6^$Z}sO0=R%LGy~`&CIJQ^A`0e8@btPE zd4UAKf!cewFEjzOV1s04BdO#Z1!Cpp^*^4BW4<-G6Ub>d(P~_0y zy41g1r@gnq=e1SPc=Q3%L4XM$1DwJ&e~k7;C7K9Tz;LEAVL zp0Z7XNL0U{28hJrv%&RK`7U5XofAS(^>cqA+Qf26cshX~J0CWIcCqN~6bh%>K!Q>r zL0f2oGySLqSUH4r%txH8r8^V>LaF{p!4K!qg;MMKnoS0q0JBgF$zTW!0*nF~-~`SJ zH%C!_9VDPR$c833-3ODyIGL05I7o0IlJ9ctY(j(z*|bM*d-X0`@ACY4j?yoK-9cPM z)Ep!qh%zx8;9gM=a3o(4Ie}!1c1;3-PkLi=Xb$oqC44%UuFFT_=*c~iCTl`DeYOPK zHr|g2`hA)Jz2N|o06h@_b;S3C2Ebwb<;?&HPzs|%UP8jjJ^)`xFdt16t~$L2+RoJ% zC9Ly{?R7}!QuDTSyU3uy=RPH$W{&nB(a$L)f}*!ausFO10a7rUfdprS1WXw(vdlp^ zO%Tf4w~I7>aeYyx+Xh=7^RpJf{*%<%7^6@chUo8v28ho7z~X=}?@=T;NprvukyW(0 z&;;TWgmUg8k^XSryte0&NVdMmj|juDXq3{=AFb+Nwk#hvHyj~g^#4LhamYXtKs~l^ znvif@97E>M=fEe>1sOjgxUzkA!bX>A!vSuSKtOic`X|xwA=hPp1rk6VVE0LYJ|IAc zQl(DA0erAHa}zV~!SDB^Ktl2w2LdM8TmdorU^uU)(u~x%WX6B)}xp&I<(IA_=@i z3N*n4G+GisJDppUT)rkiIHym%{-Q`f@0|y-vII;53;_WU-o6g?A3MKVS`v)qgBGX> zK!Srb2P6SAhGXDZiMo#@sS{59yBs*bm_D59C-|$;0o)(b?}fDZe}^LfkNt5m@q0ui z0lfVga18H(IXKKU2h;*gstiL_Z4JV#Q0d%AynfrUi^Q|n&YnyC&q2C3I~d6f2N7}- z5)MK7Z@CzA6BD0_$xFbv4H?6|L(y537xb*zUbOrRkgn6RpPjkhF7bLWH!I!z>V$V&?d_FY6tyo#{97)g&5=JMBk8hoakc&_1u!}ja zie9L6uAh3>QtndwyuJYW3g#_H%&y4#bxlq_0n#Fb0N^CY(M2 zNMRmDcahZKBk}J2vVE?Y-X?}E{mYTI?#!+q{2wjwKVf-XKFB$+M8A0a!~Q)3&;-|^ z!E{yE#Kf~$g>=5L1dbPN?g~7ZL1+Bz>|Z#q-!HEBJI|Icdi~5-kcdOhJAMn1^oibe zfL{kPB09JZ61S*JAdt@mC?tUA7eErJj*F@d{A|B%=PCU%2>wVc`|^@iBp^%^^8PQO z*C8JBUkZ|7qRYe1PUw)Fe0B($EhvE`0b8&};h5lsis`i(2q*a(cm zhU9m_a{^=LM<*`@z>)k7Xo4iz+YT*~lRp^>=L?A=j|2pzHJ76yE)SK-3m4Z*az_(j z8EO+$`vjj}e_#CFZi$IU;PKb`-&k7o5eYz-;vP7Hr7+S^cYmh`qJp*no@&{v#bbW} z5=W22ED%JO51@-UHd%xKlz0xB7cP92^fW7dJrff@0^u4Ug&i;TUJAfne}kF;B=`e> z*xw-`p@34!Mht2Kuc}B%1rg>WWL&Mvx8XuOk^JSzH;jY5XZY#$D_{)AarcyzFJXq# zYQ@rOpZ^xfk^EhdfMMcnc;crALQ;FeLDWQ`X6OVECn0R4MEk|{LX4G&Dkh_x+dimO z`2KE?`qB8@mPtvB_0tiW#xs49fODztfi@@yzaST29YAWfU^4pg#=~Lj47*Lqm5>bp zn*IQDGOCPoP{CV(u?S;61|R#%nnN4hLjrMWcQ3sEQAj=2KKc}1#NT)T;79k5M_nq= zO8W1B1c}fFl~{>`Hh8c5WtW|s3=+(RM9)IvhJ+XdGtmWLw!z>NKD%Lb=RQKo4$S3a zj0WISVE4JK3)-Xr6~3b|DHAbnMujhSR{54RK$r0I5+JF!0kEDJdk`X?Z3}6J?e=~H zXegwA7&OFiNc;$lAvo?2(3xB40s^#PjE_g&!0zwE7y?4!SLNfcZ`=$(8zg`LNdWMA zY^wpxCK!V-Mq!M{n1bTXB!rO@nxc6VrlKRxHN^NM2y_ibGC$)R_r>G?aC`>hGZ3GF 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 3c725986457eb147f0e2b8d38c32a5aadcc139a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 7 May 2014 00:50:57 +0200 Subject: [PATCH 021/234] Readding core plugin that was missing because of a hgignore entry. --HG-- branch : gsoc2014-dfighter --- .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 zcmV;%3_0_OP)N2bPDNB8 zb~7$DE;i7Ety%y83`0poK~#8N?OS3v(F?m$xJdyhRME=5Ft^*7RW;O03n1W zglr@sAsZwiku9Jggvcf+RVgl2i)f|QS{G0;C|0dIF7>z^Yiez4&+%ygsXcZ*e*L~T zxi5EKW`h1P(=!}$&hOlN-+OuQ{(j$bm-mLTD}PrMxT1j16)0svteh=FY-5Yqe#8;P zu+%PRU5I)_1uJ7&tb|3e*-Y*8KKbndMa-VoXZbjLPZZ?ux5L7N5m0*631v6OKJIWp(&8JKMJz&c?U<{&@>c475D-;8cY}J?!N}^`Jz+8PyXBicmJtf!d-t{4|jgv zCYN{op%n-xK3fNQLun`g3w!~bjls`V9#4Z~AJ@C#mXGQ{#LXYp;&gc&`TLSD4*{ZE zOczRzq`=|dR=eTQd#k{Om2mJ~7pP9hs9tbmA~>7S0}2B?2Vfk3ls}vR``@mTaO1^g zGKSx(1aBxl81G7g0WClQ3w1PW|221491Oi#0Yh)Nu=n*PlVZSV$87ql6At6DA3K5z4w^#d?NM6`4+Y!GkJ;l&k6H^B9*7#4 zzc=!gnL8}snJQI~vDpE;UMYj?UoMq#-Ag4f8J6Cf2F3~%6diW_rSxdrXz@*PqeX{e zM+*-`kLC|g8O_-nF`B(QY;?|b*3qm%>*&?ntfMoowT-54vW}+qSU*ka4*fK_%kn{D zN6;JbZH5bp9ol+@ZEQ5}1ag|aV5!ImoM{KjUW}*ls%tmu>^Kuo~R%;*( zT{i&<a?K zKkjx)tBF?O9T$nwG5Q}W#ST-QgP+^XV`Gsd@5wx)0_#4DDbVUX#5F(D~?W zIabNdIbrVFVhqYIOXLyWtVd*(788jLJVV4?&%4JQCo5V|tWU7oQ{$vL2~T8*7$sj$ zP}!z)8^_L5eZ!NpVIzX-J@~(t6(~SQ@HZ$xq-Oz&8LFD=mYF$eF?P92bBhl=J06ot z(nMCYo{}K7d(XPiCzUR1QinNNi2#u!LSrQ-Cmj<&$2UAN3%U_f9l`6?Y851Q>c2z* z%w7fPJDW3M_~F@D%)m;w=B~?2C24P#qw9Lk%taDN@<|tYBE&l{)msbu+;;_QWd$KmSxXZFGLL$h5lJ#V(B4NpOiTGT! z-Z*)YBqt`4?R;z|5ID(8we9tKNbL!|=y4(>S&AFFSs94G^eJW&5L7OC<-j>0C^!5t6zr&rB*n&zbpd z6A$HZHCd)sCMVg-NSIqw>BiLVdfeS@y%7{iiUgHpi7?0dUuMdJq--$b^jv-a&=z9WknbEWIfT6oERM=a-1L?SGL<8$$+&#OM{yGlA!92By@ip z*w*Ndc^9CBVIsQlt!bpYO6e+EXAFeyhKYYU0Ad%)l-m=WrYR|OEkDXQG*5vsE~{r z$(SnC_*|W|aEqu{IT*A_gIB?$V^avwvSsBKl$5MyDhc|1at*mJ31h(hx4#z~~%G4sfSz2^s`x=u( zICP~%@;kKNw|M_AWrT7> z^XcjGup|yoMAj2|@&FPbwMTv47ya_vJ)KSF5krLrR%7;7j?LWq+~tWhVcjpLO9-zq zLRzokjNdxziw8wDm_|&MYFKtWUKT)fb5G=H$Rm&kr1ytD?2CT+?Vk2J{YWtGGtzf~ zqQ$ug-0Gs`We=z|K>DWeQ-15LFCG+DqZz@kM4;ecjGWviBTtqm0jPAWHPGbdZeR4v zZ}$wXW+MpvN;Fy)K(soqbGPSZ^XYV)lStnR-sZQ?`r<+66>P*-!ytFqT>$Rp+}ff5 zM4smFvFmjZ(ZFu-Sq{eexjuSURf7G(iAm(rbEX8i=SpIThkM^dvyLPx|Gzo0hQ$qneDcV94p_ z0m`Ju$@2tQb6+yVw&Mp9W%y%?fc`6I_eSD)zF?nIn&uLSJa>I6i9C;es?!KiaeFih zfP0i>Y{Na8wz==TC;0WE-P5jz&KR^?FuZhbBS z5$DL*YDEDofCA%H7m*fF60$Kp| zVm9E!Uw-6{3Bco@$k(1s#+}*(TqignV{0fx;Fg>YKdDjUD{R8FejEnNmGAHZOb!&F zj>hw8{Z^Q>D-6ve;MS&{{1egN<15hx}#q25-oB#j-07*qoM6N<$ 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 zcmVN2bPDNB8 zb~7$DE;i7Ety%y88DmLAK~#8N?OO+UjpyHf-g8cd6+433RH;#Itx^OZ zEkzMssJ&P1T9FX3g&>GXh>>B7Q7a*fNFsZk`@4VdIY(3d_urD}_w~BIT-Wb<$2sSD zpZosp=Y68o|NlKX2Hd|>rh<;XY@{+Q{YDuJI?n&f@3&4;l?(ddZ4*_Q%@b7FH6xXM zLC5+>f4_aQs<>mSTDoo0qfOj(cJII~&d)JEk&Vhn{buO~jnx-m-gok{RJRm!1d3VUWNoZO@#!bjo4cFi2& zYskBDz>xQAfFbX8u)!P?YCzm6BN9#z#5(5q_Hi8y_3;gY=joSB5 zeDa0yfW33ofQ!4d%zg6}sC9zTuzQXXzOyv!nxWt~S7HA`$|4O1e&%rj@69*h*!m)f z@OMGX#YV_VeF?~G4Rda5oZnkkC*fv*cK@W8dbTj;_(aB_32OxO@#WnrXU`mky>ktS zI$a&+?B)R40_JAOO=*Jru}zQ=)fo3~H9<;T6PUA}=jW{{?I;~6T_~?o+EZMSo6(%s zV8nhB8Xuzh@0#*|FeA{fwZP?S@RdC(Tg=yQo&jlbjjW&q*q;fB5po`gE6-n{bhVNp z*X@yXs{wpxXgJ}n%t>dpAx}huk2~nQs$rMJ1Ai?#Hb|>is9+u*Y}E*5+{6NeAnlmT z9hkBlw@g${Jg>#n)s8`KQp64wb9}7=Kf|FF4oJNtW-n$d@-SGrw)pjLnwRS#lm(O( zhzV_p(;JF00Di^m9#%{EJqecsD`Pj^Eb^dscg!aOTF7Wad7Uz!;*R)}uOf7{hO2(h@Ol|# zI7MQCScuIEECfaza>h<(m`l4<%9Y*P$6F^np}@$B%!Oc61C}T-x9flv+{|WH;Q2K!=QiMC$~GXPO`AsLJMU533vu^sPaS;7Dy1KzLxr4al(($EwZ#Lg z1<^$=1y_Rmwzc1%=Sp}WPw#cJQ-Uo2)Gw8jA`u?^{?tsc_04ZJPd z3wQx46SooYN1q1zA~LX+4*bN*-{i7ybv{GfVmf80l?Vxpzjuc#K~I71h!Y+f?wmGc zvshYB7cJbfnHv8hgnrIgfP`yx@&UJjZTrwYOX{+iy_l~|T=IH1>$%km%fM_GFuF=PZR)JFXL zMIl)OYxbHa)~FmIAnjhghcy2%_}?P7g#?+bkRaOcMnGM0FRBTWZ#PER_OkFA&q|T0 z^WyHxI7TZAbvGgT))zW>z!UN3d(k>HTs!m}Nf^U>5;MA6$(3h|tF%GfWo8FfoHEBl zbk}nmRi4ijHD~RpLLh;ez%k5I-HYF3bB`~@cYmHHfHWy)VlUN5^jaG;OAp0ZLOd`;!%WIM0W{F-kU&rUj(du3hTzw z0z4EpPgJ!Fg#Z>n%YxaPUkfeCht;OkvPw-JZ6f#hnYjVZ?X84~JrzE$qtLggLRY0Q z^Cf$Pk0^(bA?0xF%Q9Hdt{6I#m>;?r5PL;P5JGDqJGC~Bu#FZA2w7#oWglnO7~k@< zPbs|#bTsZpbi{=n&bS@+0Ig3DfGFurFseA%=p zdOB$sUC)S5s~B|f&k1;g!fUjImOKt_Y9S#qq_}n53OtslNbKo{i0$Qm7aKxXn{bOJ zpPMeRKmxJ2QGM)P<^a!eB<2^jt-u6q`biaI8jP068h23$5Wp@JnVd{aj=avUh>%Ie z@qS5#VK12wFzY>JA6rUUhNvAAF|AKM3~5mu9cc+K5V&aG)ltLpRwiufWQQ4zj5--Z zUs4G3DMD=usq&n1lrofVxPIi>2Lyz<+aWdjZQhsq;A2V;q{X*J=DijO-&z`Lzh~vT z(r|sn$O10Svk+<|3lR*2NV{9w3R-}Rh<0Rx6>vYKEEaY!p*J-5y&IgV0RkIRk&zR7d1WazI!Mmdo-u#`Hs{x->qE+zsKfS5p-c631!)N62 z8RoLc$*6);Ud40*Bum`8EGf{9GLrHQWfZO*tb;3lRdMZb1AXc3=o&+==lBA4jI7i~ za8;MRzCvD>XhHznfS0upk>QNfQ;Xt*VhV2(n54ZgpR>pGcj_Tw-)y8GUV^m4i*aY~ zEX?cw0={Zm9BoL#a1!O!-hg#&G+ zz(rgs_NI&E4dSzZ@77aE@GAd zJkUzODBL~Y)@mKUHC2)+&TQ6l(k|JxeXLkO^Y6e$D3?dvIxQJMEWjpohg@1hMp*>R zD2g}ezaP^71HUpM)XffoLrfT0S;Mf_PFOpvBa-~*>jb0(E=2sEnIxe(K5tSCE$kHD zDXY-Gyg~z-KU+C8;8^u}Y*$=i{veV=f8NekJS)C9Qg1lIoK6CArT!R3OBhCX=zy@b zc7Gs1GR5v$>9q}v) z?CHctiDRu~VYG%W;pwU{{#k|Y%p7CrCRYwR0x2XQl>{*ENOgGQNP|BRaPP8Zsm+}G z0YWzv*9q`qT0FAakmvWaTD|r=Rp!5vK<(SJ`8gB7fFtIA>7bnjv<|!^&5o1ErDT=H z-lY!cMGNR$O2fW^CioB3uz!HU;`WU61jUt0^dLF?SqYBp;EWA!-I1_=j!rwZ=O&>~#``RV4w<7#G@b(w(TiZX}_h!mG3rx8{ug5d@!1xnGP$Pjj5#TIzQM zob+_yeF>0^4|#17%Gkw@7TzRb%T$e)V2X7AR?Yl*h$``?BzTWkUHD!uPr$PdK+IV( zpGWgE6SNMV=ee9jwiDvcI>GG|Cp=Td8N(O|x4ps1cT{M@ASU2@ms0qJRo;>p4H*5r zBSyA&rX_U4U1o>7`{(Lp#P6Mn6<@T$J2mZfi}}7L{l2ZjhR#$#54vD4S{UO?Hxe|o zKGzL4*mK#;0l^*yeVI-&gZR71DQ_;SntL*Z)<ds2QGqMiXE*W1>tDJ6 z37B$XwFSILQX~VQfX)%$lN3Y}a`>Puo~M^Vd_--$_gZPxwbSrXMTIWZxCF81skQm^ z<>hRD#jlq(GhxJYMKG$P3pS4Ffq2#iLc(2=5aT;tj|tt&8_|eBzkiwpbfMPRRIQ>V zbYrmW!ZF|En4i}osl(_ZKPs%F9Qwt8!>kRYSd$}CSW4eF;pApbcVS7NXEvzwd};I7 z;1>;64(rFNrpH&SSTP-u`_TkXZ6imH1fESoH2a6Yz^<%r z5PeF5M_MewXGqj10itmsA(Oc{gRwyuo~M<7Ii?DB|KN;P^ndZ?-i+!(fPi1Xf@eNc zTxUjfu2P^gQ{HD*65PM;h-kV%ED4BZP`ti*JSM+U4=)zcP*W;H%I3aY>grE(evdT) zWfrT)zO;yibOpq44g`&4l96n{&BGSc=dxII&@%OSZ;+TO9Qb}eMhHm0N$_b*gXuy9 z3DC8kkAQUgTpF*FOCsl5HEift6fd*NlWy-bYDx!BpZ2XhGf+nRCE=`?*C0qOR< zrle6)sfmO#NC|hr>K-ON6G+qZ2783Qw1%f?`qivyaUQ|XrA()f_pfS?(XUj(Ql`Tj z+a~HRAtYQ}{~gA(uZ9K;d{QO8Pclc=!M zTE;cOg1sp5nXSBhI9U7{f=*`Hd!J=610K?>79g4z@EO))D(i)0l5nRCQcpT#T^~E0 z1aSw^x_}pLe(OT;1Tx1eQ%SqKq3i9ViR;< ztbq>|lTQ=i1g*P(SOCvcc}${(#Fs|Kh4R??sUzCb-z6}L?>8in84Qjy=mN8u?}dcf zB;Ygl1Fu(d#OO|yG5doixUg=Fo)vD9gi|YrxES#jv=lk(x<5j8CQh>3wSwl z8H`<_%3}ni9viZ5#c8$#?n&=NG1U(d}ykT02^?EPZI*zHQwhjK}aZt z+-nuEf2y*vqdQl|q+WFq_RCN` zD@0Nb&l`yMY8H8rVd~o(uxc6?XJYs)A%K#3-O@3#fs-Qc(IfxEjIprz;n+G2m-ew2 zNFi_`Ac-!(GF12XRBB$dF50(QK#CB+?Fa_z&Sg-~pn-M@ zmS~{Eq7O@Gaf|7U5fd2cJ3E;$yp1#5I#t3Lk?AGRRW=F#QPu zy$h&+rAWZ&P`1Q7^}Roqnpz$p8=-bFJ4mCkgU!fMKJe~2f)&%ZffoWqq(Het65?n< zBmq%na3`!P2KIGE?aD5wYBcBs$h(8dbcv~ShiMFu(@8)(F0H*)g>`~!c{Wky@ICtt z_mNeRdYtbBV@R@qkF!cFeV@wGU*ofaB>`U+m;eqk>NwW}Wl+hj@|v7`^)8?GQr^ec ztCci0U#6TpvSujcNb`{$ZzbXZ0TQ8kFJ4Gs+=!+%M3zR(@fvvlO}az1il}KcVsv>; zj|Y<|5+p~lkC2GphVC({xhDbTl7MWo$!OYGRw}nhb{cDzYfI_}#J!Fka5BF4=C#a}^h02F(iA4%z1th?g z%ga}pTi;?&{a?4N^ShNu)Lu3o`tHxHTLdoz=pg}f(71LP^lV)O!9P17-ros%kwP5Dh#`rw7R{$!w(c^W%T{-zx*51c z4d5JPlXVqJEABF{z_z}0fe2tOb*2>kyMxG%GA>8&JU{{h*+}JziHi26O0!mKh$n~` zW``)ogc~K1d&LDwr)%LHH%HC;(HYZ6*kRjz6Yhj?#pgOTEx@g&Zu9r-8wv-x2;xt< z=%cpF2JF8($4C0!>LHK5`-=Iu9CwtQk(d$T`yU99oE=LNZqW)N1*8+qH)su!BqWM} zBPme~aM1)#|JKD8=y)_ov)uKP-Ke_e*YLfi<0FCkC%();)Plh=PqM`QOZl{KEmsjI zS`~mcu>uva1c;b?*ESNY$H)LnKtAK8_U@kXe-OM7>^+VzRF|uDvR_Ajx~GptxXL@Ymk|1R=*(t3wBv6)x}ntzNfTK<+JWyF0D$>pne@>HisW zZmVpDw%ofJ$n7)76@#I|?IZHf7M9JLNBMHp|7X?bpO}AvpFv;!JdD+uMC&}!B3&St zK7N$|C5UZj{+2i)|6dR&yFFxSo13DzDNEn?C!a}CV-vZS%9N>=yKepke=JZc(_gb> z;um)C{o-K@8B#vWjuY-X$l~WG!#8Rx`4(yd-{y`W_-{$VjMLuAm#aGQEWjR+p%cI& zhh+8t7r-=;7H3V?- z9aylK*`i)&NzG;c$NSqgUD{kXsRmiO@#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/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 e6569049e9ac2eaab30ad546aadfa0a94972e093 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 7 May 2014 00:53:07 +0200 Subject: [PATCH 022/234] Same as before... --HG-- branch : gsoc2014-dfighter --- .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 3440c7081b697bf4d89134012f8f8939878f8b42 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 18 May 2014 21:47:31 +0200 Subject: [PATCH 023/234] Renamed ovqt and ovqt plugin binaries. --HG-- branch : gsoc2014-dfighter --- 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 0974142bccea49cd1de9863c4c328e102f3d568c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 19 May 2014 01:45:19 +0200 Subject: [PATCH 024/234] Renamed the plugin XML files. --HG-- branch : gsoc2014-dfighter --- 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 eeb4e48d38514578b57b0845e99b3da39e519977 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 19 May 2014 02:08:03 +0200 Subject: [PATCH 025/234] Renames. --HG-- branch : gsoc2014-dfighter --- 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 ef7a39641fcde8fce34420097d4ce9a36935ac35 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 22 May 2014 15:06:40 +0200 Subject: [PATCH 026/234] Rename. --HG-- branch : gsoc2014-dfighter --- 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 79348c8e93a0bb8be4d1565a40907f02f52930ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 22 May 2014 15:56:38 +0200 Subject: [PATCH 027/234] More renames. --HG-- branch : gsoc2014-dfighter --- 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 4adbb6dbd9211ce4e8082b94ca196312acfd22f9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 23 May 2014 02:26:31 +0200 Subject: [PATCH 028/234] Moved plugin menu items to their own sub-menu into the menubar. --HG-- branch : gsoc2014-dfighter --- 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 1306853697e32638ee27f458e3f0e97c1de4f3a4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 25 May 2014 22:45:34 +0200 Subject: [PATCH 029/234] More renames. --HG-- branch : gsoc2014-dfighter --- 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 883c0d4462ec5c5ec83974cbafb6ced5f8774b22 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 26 May 2014 21:04:05 +0200 Subject: [PATCH 030/234] Settings dialog on first startup. --HG-- branch : gsoc2014-dfighter --- 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 1d23a092c13e1886a57619e7a57de21e69a782b9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 26 May 2014 21:07:39 +0200 Subject: [PATCH 031/234] rename. --HG-- branch : gsoc2014-dfighter --- 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 c15eebaadfb41e6a87755508d0d5b619993687b4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 4 Jun 2014 22:09:11 +0200 Subject: [PATCH 032/234] First iteration of the new splash screen. --HG-- branch : gsoc2014-dfighter --- 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 cfa12b6d81c23a559144f56062108a8ffa461932 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 4 Jun 2014 22:30:32 +0200 Subject: [PATCH 033/234] Somehow I always forget the banners... --HG-- branch : gsoc2014-dfighter --- 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 91463f9fa244c26cf24862b100a8ea2e41365b46 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 5 Jun 2014 01:57:13 +0200 Subject: [PATCH 034/234] The splash screen will now inform the user about what's happening. --HG-- branch : gsoc2014-dfighter --- 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 2ce11cc2f9e54faba63839ffc562e1e5e9108901 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 16:41:39 +0200 Subject: [PATCH 035/234] Line endings... --HG-- branch : gsoc2014-dfighter --- 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 f177a49a9e381939c7c33f3902dc891435903095 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 16:56:10 +0200 Subject: [PATCH 036/234] Instead of drawing the progressbar on the splash image, draw it below it. Also move the status text closer to the progress bar. --HG-- branch : gsoc2014-dfighter --- 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 f0a312a6e5653dfb9206998e32273ba8a4f193e2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 17:23:06 +0200 Subject: [PATCH 037/234] Progress bar will now actually show progress. --HG-- branch : gsoc2014-dfighter --- .../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 c2a951fd6ceb34db9b07329d6deea38299a855b9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 18:10:43 +0200 Subject: [PATCH 038/234] Progressbar should look nicer on the splash screen now. --HG-- branch : gsoc2014-dfighter --- 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 732b24b9859807ace94e7e3192cf99115ebfaf6a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 20:04:15 +0200 Subject: [PATCH 039/234] Updated qrc location. --HG-- branch : gsoc2014-dfighter --- 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 eb41278369e55b5ca8df329ffe697c86adbbae97 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 7 Jun 2014 21:07:46 +0200 Subject: [PATCH 040/234] GUI for plugin loading / unloading in the plugin dialog. --HG-- branch : gsoc2014-dfighter --- .../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 d7536332a68ab948953e21363607fd0738fb62b6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:17:24 +0200 Subject: [PATCH 041/234] Implemented plugin unload. --HG-- branch : gsoc2014-dfighter --- .../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 fb4dc15fe7abaff49269034340c920a148d6955e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:30:09 +0200 Subject: [PATCH 042/234] Remove GUI Editor menu when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../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 828f31a2a4383a812acb1e76508736b34f7bd22d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:45:13 +0200 Subject: [PATCH 043/234] Remove translation manager menu when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../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 3fc289e7fa0429b1455c5a94c31e7b67ef75a2d2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 18:56:40 +0200 Subject: [PATCH 044/234] Remove sheet builder action when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../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 b9bbe802d4e9a54959b79f7c79ee80fe6a874e00 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:27:03 +0200 Subject: [PATCH 045/234] Remove display sheet id action when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- .../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 9ad71881dc26d50fb4f9d6ebf1ee7bb4d02d4e74 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:28:19 +0200 Subject: [PATCH 046/234] Line endings... --HG-- branch : gsoc2014-dfighter --- .../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 0096ad1204dd885a9201826c41f1a29471026e9d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 19:39:58 +0200 Subject: [PATCH 047/234] Remove Object Viewer menus when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- 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 c45b6a17f4c54f9d37af598949180960fc6e83f3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 8 Jun 2014 21:56:31 +0200 Subject: [PATCH 048/234] Don't crash when removing the plugin of the first tab. --HG-- branch : gsoc2014-dfighter --- 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 f060adbed7eef79980322a89636ae1ce8dd8b1f7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 01:14:13 +0200 Subject: [PATCH 049/234] Plugin loading, with issues.. --HG-- branch : gsoc2014-dfighter --- .../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 d4ee31ed63dd2ea99886ac10659e87d0ee042ea3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:40:06 +0200 Subject: [PATCH 050/234] Destroy context when unloading plugins. --HG-- branch : gsoc2014-dfighter --- 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 a86605f8d871e292b8cb83d615ca976af3f05f56 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:55:45 +0200 Subject: [PATCH 051/234] Move the log trigger menu item into it's own menu, and remove the menu when unloading the plugin. --HG-- branch : gsoc2014-dfighter --- 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 92cb5eea3af9c1d9f0c03401e0997716e0f5a7f6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 17:58:07 +0200 Subject: [PATCH 052/234] Updated qrc location. --HG-- branch : gsoc2014-dfighter --- 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 fe7c3e4edfa1b750e029e92234355ff60a0e953c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jun 2014 18:01:14 +0200 Subject: [PATCH 053/234] Rename log menu item. --HG-- branch : gsoc2014-dfighter --- 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 c692b168d70fb362ad4877d6102ddb49cb5fc808 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 17:28:33 +0200 Subject: [PATCH 054/234] Split Nel3DWidget and NelGUIWidget. --HG-- branch : gsoc2014-dfighter --- .../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 9d9cd463b08a2fc40f8ba0dd34a81385c81374ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:31:50 +0200 Subject: [PATCH 055/234] GUI Editor main window will now send the show/hide events to NelGUIWidget. --HG-- branch : gsoc2014-dfighter --- .../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 1457469dfe5f196d794cbb128bdb883451fbf70d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:32:27 +0200 Subject: [PATCH 056/234] TimerId should be set to 0 when hiding. --HG-- branch : gsoc2014-dfighter --- 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 676587559b5c33f6fb68111119734eae3ab399f4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 18:44:57 +0200 Subject: [PATCH 057/234] Renamed NelGUIWidget to NelGUICtrl, and changed it's base class from QWidget to QObject. --HG-- branch : gsoc2014-dfighter --- .../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 59b4735d96e4cdab5e5f533403a56824d28fd33d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 14 Jun 2014 19:37:42 +0200 Subject: [PATCH 058/234] Renamed nelgui_widget.* to nelgui_ctrl.* --HG-- branch : gsoc2014-dfighter --- 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 3cbe37d700c6d71c90dd0da378d130f28003b738 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 18:41:54 +0200 Subject: [PATCH 059/234] Fixed build error that was caused by two widgets having the same filenames. --HG-- branch : gsoc2014-dfighter --- 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 f8505429ee44e5ee189d66f2d5fc4631c65cc1b8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:16:52 +0200 Subject: [PATCH 060/234] Moved the event listener from the 3d widget to the gui control class. --HG-- branch : gsoc2014-dfighter --- .../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 e5921ffd64d45ee89371c0f14f0ce14b1cfa16f3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:28:57 +0200 Subject: [PATCH 061/234] Activate the driver when getting a show event, and clear the GUI Editor display widget when there's no GUI loaded. --HG-- branch : gsoc2014-dfighter --- 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 81908eea0122a47a3ef0b1cc9d4ce294d9b6f75f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:42:41 +0200 Subject: [PATCH 062/234] Set some windows attributes. --HG-- branch : gsoc2014-dfighter --- 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 dde63ceb319ec76aa1f821383ab879de2c08b8c8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 19:52:04 +0200 Subject: [PATCH 063/234] Nel3DWidget is no longer in the GUI Editor namespace. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/gui_editor/nel3d_widget.cpp | 201 +++++++++--------- .../src/plugins/gui_editor/nel3d_widget.h | 54 +++-- .../src/plugins/gui_editor/nelgui_ctrl.h | 2 +- 3 files changed, 124 insertions(+), 133 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 ); - } + 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() +Nel3DWidget::~Nel3DWidget() +{ + if( driver != NULL ) { - if( driver != NULL ) + if( textContext != NULL ) { - if( textContext != NULL ) - { - driver->deleteTextContext( textContext ); - textContext = NULL; - } - - driver->release(); - delete driver; - driver = NULL; + driver->deleteTextContext( textContext ); + textContext = 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 ) ); + driver->release(); + delete driver; + driver = NULL; } +} - void Nel3DWidget::createTextContext( std::string fontFile ) - { - if( driver == NULL ) - return; - - std::string font; +void Nel3DWidget::init() +{ + nlassert( driver == NULL ); - try - { - font = NLMISC::CPath::lookup( fontFile ); - } - catch( ... ) - { - nlinfo( "Font %s cannot be found, cannot create textcontext!", fontFile.c_str() ); - exit( EXIT_FAILURE ); - } + driver = NL3D::UDriver::createDriver( 0, false, 0 ); + driver->setMatrixMode2D11(); + driver->setDisplay( winId(), NL3D::UDriver::CMode( width(), height(), 32, true ) ); +} - if( textContext != NULL ) - { - driver->deleteTextContext( textContext ); - textContext = NULL; - } +void Nel3DWidget::createTextContext( std::string fontFile ) +{ + if( driver == NULL ) + return; + + std::string font; - textContext = driver->createTextContext( font ); + try + { + font = NLMISC::CPath::lookup( fontFile ); } - - void Nel3DWidget::clear() + catch( ... ) { - if( driver == NULL ) - return; - driver->clearBuffers( NLMISC::CRGBA::Black ); - driver->swapBuffers(); + nlinfo( "Font %s cannot be found, cannot create textcontext!", fontFile.c_str() ); + exit( EXIT_FAILURE ); } - void Nel3DWidget::showEvent( QShowEvent *evnt ) + if( textContext != NULL ) { - QWidget::showEvent( evnt ); - - if( driver != NULL ) - driver->activate(); + 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 ) - { - if( caller ) - nlerror( "You are using QtCarbon! Only QtCocoa supported, please upgrade Qt" ); +bool Nel3DWidget::macEvent( EventHandlerCallRef caller, EventRef event ) +{ + if( caller ) + nlerror( "You are using QtCarbon! Only QtCocoa supported, please upgrade Qt" ); - 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 ) - { - 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; } -#endif + 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 b4eac44a9d8d76c37a96bdaae5a9bb762c75c095 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 15 Jun 2014 22:22:01 +0200 Subject: [PATCH 064/234] Moved the Nel 3d widget into it's own library. --HG-- branch : gsoc2014-dfighter --- 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 d74d1d1663d4ebe7dca543a3e58642ee009b6c41 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 16 Jun 2014 15:30:35 +0200 Subject: [PATCH 065/234] 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. --HG-- branch : gsoc2014-dfighter --- 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 ca78ce10a0e0c76d2203963378011328e7d41c4f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 16 Jun 2014 16:22:52 +0200 Subject: [PATCH 066/234] Object Viewer plugin will now use the Nel3DWidget in the Core plugin. --HG-- branch : gsoc2014-dfighter --- .../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()); -} - -#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; + Modules::objView().setSizeViewport( width, height ); } -#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 4341ac31390cb5599b20d7b4a2d8259704017b89 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 01:15:39 +0200 Subject: [PATCH 067/234] Unload plugins when killing them. --HG-- branch : gsoc2014-dfighter --- .../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 a80053083d13faf7604b0109307c443342cdaa1f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 01:20:37 +0200 Subject: [PATCH 068/234] Crashfix: If the status info widget isn't removed it miraclously crashes the app on shutdown. TODO: investigate why. --HG-- branch : gsoc2014-dfighter --- 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 3d48a01170652f68c420dbe714a18c31329240c0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:41:58 +0200 Subject: [PATCH 069/234] Wrong slash... --HG-- branch : gsoc2014-dfighter --- 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 d64b499284ee0dcd735fb53fa1dddaa83820d072 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:51:53 +0200 Subject: [PATCH 070/234] Making master Dnk happy. --HG-- branch : gsoc2014-dfighter --- 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 0a26a5a1c6788f7af42b48148c94d171180103c0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 02:53:39 +0200 Subject: [PATCH 071/234] Why did I make these public in the first place? --HG-- branch : gsoc2014-dfighter --- 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 f1ff5e7d2c058f9b57b114f0cac553afb7d44351 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 18 Jun 2014 16:48:33 +0200 Subject: [PATCH 072/234] Added color picking support to the GUI Editor. TODO: change all the widget definitions. --HG-- branch : gsoc2014-dfighter --- .../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 bb7fa7987b59cc8cb5f9cb2d252c4df7309cf957 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 19 Jun 2014 17:21:11 +0200 Subject: [PATCH 073/234] More widgets can use the color picker now. --HG-- branch : gsoc2014-dfighter --- .../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 1ce333bb00bfd55e06890403808b31288b88c8cd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 19 Jun 2014 18:40:50 +0200 Subject: [PATCH 074/234] As Object Viewer no longer uses the QtOpenGL widget this is not needed. --HG-- branch : gsoc2014-dfighter --- 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 49002d0250255498c261cf8ef1756629328f6893 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 15:09:13 +0200 Subject: [PATCH 075/234] Line endings... --HG-- branch : gsoc2014-dfighter --- 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 25df3c8afe18c5e1788e971cc8c7a4546cb53911 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 16:22:07 +0200 Subject: [PATCH 076/234] Button types can now be set using an enum property editor. --HG-- branch : gsoc2014-dfighter --- .../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 9e36082ff0f403139f405a3a04813e6893711e9d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 16:26:10 +0200 Subject: [PATCH 077/234] A little refactoring --HG-- branch : gsoc2014-dfighter --- .../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 1afe2d4a17cd7b3b36dd70c2bee072c6252f5fe5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 20 Jun 2014 17:07:27 +0200 Subject: [PATCH 078/234] Text justification can now be set using an enum property editor. --HG-- branch : gsoc2014-dfighter --- .../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 250cd6efc159c0d8f79c7ffbfc96d1036b2b87c8 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Jun 2014 18:25:14 +0200 Subject: [PATCH 079/234] Posref can now be set as an enum, instead of a string in the property editor. --HG-- branch : gsoc2014-dfighter --- 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 ec86d0381be90009cbd129e28e3a74b82593f435 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 21 Jun 2014 22:55:10 +0200 Subject: [PATCH 080/234] Some refactoring. --HG-- branch : gsoc2014-dfighter --- .../gui_editor/property_browser_ctrl.cpp | 141 ++++++++++++------ 1 file changed, 93 insertions(+), 48 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,24 +101,98 @@ namespace } }; -} -namespace GUIEditor -{ - enum NELButtonTypes + class NelButtonType { - BUTTON_TYPE_PUSH = 0, - BUTTON_TYPE_TOGGLE = 1, - BUTTON_TYPE_RADIO = 2 + 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; + } + }; - enum NELTxtJustification + class NelTxtJustification { - TEXT_CLIPWORD, - TEXT_DONTCLIPWORD, - TEXT_JUSTIFIED + 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 +{ + CPropBrowserCtrl::CPropBrowserCtrl() { browser = NULL; @@ -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 e182e25e078e00329940fd053bf94a5aa40230eb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:07:44 +0200 Subject: [PATCH 081/234] text posref is now an enum too. --HG-- branch : gsoc2014-dfighter --- 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 0c4e0e63cc65bfdd28efa70c1de4fae6bb37b26f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:24:31 +0200 Subject: [PATCH 082/234] The proper enum type is now determined by type not name. --HG-- branch : gsoc2014-dfighter --- .../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 b88e53c685c3b4388e6ee4eb885d7e84d4c1d398 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:47:29 +0200 Subject: [PATCH 083/234] Got rid of a memleak. --HG-- branch : gsoc2014-dfighter --- .../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 809fcab9e21e7ad3e572ef9eaf18c5887a2a6a02 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 27 Jun 2014 00:49:31 +0200 Subject: [PATCH 084/234] Forgot the widget settings... --HG-- branch : gsoc2014-dfighter --- .../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 842ca366ded53e77b291e1c922afbcfc64887145 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 01:44:06 +0200 Subject: [PATCH 085/234] Tooltip posrefs are now enums in the GUI Editor. --HG-- branch : gsoc2014-dfighter --- 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 7f5973e4623b20ed240237d78943ffd5358f4124 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 02:53:33 +0200 Subject: [PATCH 086/234] tooltip parent is now changable using an enum. --HG-- branch : gsoc2014-dfighter --- 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 27fe95904a99b4681c59bd3f97bfe9e09627bc62 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 29 Jun 2014 03:01:43 +0200 Subject: [PATCH 087/234] Quelled some compiler compliants. --HG-- branch : gsoc2014-dfighter --- 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 c6312db22238faf8305b68bbdaaf609a74ea3af5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 1 Jul 2014 01:51:41 +0200 Subject: [PATCH 088/234] Bitmap alignment can now be set as an enum. --HG-- branch : gsoc2014-dfighter --- .../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 471c3a0dc556edcef87c88713cb60f74d211ebde Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 1 Jul 2014 01:54:55 +0200 Subject: [PATCH 089/234] Changed some property types. --HG-- branch : gsoc2014-dfighter --- 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 0d9022226cae0dfe3a0db2606a80f03ae2fac1f4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 2 Jul 2014 20:44:46 +0200 Subject: [PATCH 090/234] Line endings... --HG-- branch : gsoc2014-dfighter --- 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 085c1b41b9de1843d2993a72a289a97b17c958c2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 2 Jul 2014 22:27:04 +0200 Subject: [PATCH 091/234] Added facilities for viewing the loaded actions. --HG-- branch : gsoc2014-dfighter --- 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 e4e2a57b65e51a19c12ec905fccc24ff11c73d33 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 3 Jul 2014 00:44:38 +0200 Subject: [PATCH 092/234] ActionList dialog can now select an action, and is used with the proc editor. --HG-- branch : gsoc2014-dfighter --- .../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 1e6dc1cc37574af4bad6b175826d1267153f41bb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 02:55:46 +0200 Subject: [PATCH 093/234] Prototype of the texture chooser. --HG-- branch : gsoc2014-dfighter --- .../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 1dee9d232bb46049a6247d2a00ffa6a7ddd03ad7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 03:13:01 +0200 Subject: [PATCH 094/234] No need to store the loaded image data after passing it to the label. --HG-- branch : gsoc2014-dfighter --- .../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 6119f2c4802cccdaaff765d08a27c114a8b9256f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 5 Jul 2014 03:31:21 +0200 Subject: [PATCH 095/234] Make sure to always convert to plain bitmap. --HG-- branch : gsoc2014-dfighter --- 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 fe58435bb5354b27d279389dcdb199f6fe114372 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 6 Jul 2014 23:21:25 +0200 Subject: [PATCH 096/234] CPath can now return the file list with a path filter. --HG-- branch : gsoc2014-dfighter --- 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 396a3c2db2ae58ac30d8279ca00d4bdfc433bb85 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 7 Jul 2014 19:19:03 +0200 Subject: [PATCH 097/234] Allow TextureChooser's texture selection to be queried. --HG-- branch : gsoc2014-dfighter --- .../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 7cbc82fe8f8246178a109cb5d9d0f1258eb0f327 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 8 Jul 2014 18:26:20 +0200 Subject: [PATCH 098/234] Added action property editor, editor factory, manager. Actions can now be edited using the editor widget in the property tree. --HG-- branch : gsoc2014-dfighter --- .../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 a1b0f9d7e21221fe0674b2bfd2e3c610ae6bf226 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 8 Jul 2014 18:59:30 +0200 Subject: [PATCH 099/234] Added texture property editor, editor factory, manager. Textures can now be selected using these in the property tree browser. --HG-- branch : gsoc2014-dfighter --- .../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 012ad9680603863fc50ce4f6090e625a29e90708 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 21:07:12 +0200 Subject: [PATCH 100/234] Texture chooser now supports atlas textures as well. --HG-- branch : gsoc2014-dfighter --- 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 d850a07e9e870c1e2ad35575b31e33613487ebad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 21:13:57 +0200 Subject: [PATCH 101/234] Copyright banner + line endings... I always mess this up somehow.. --HG-- branch : gsoc2014-dfighter --- .../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 094210a079445fc59cc71fd205e518bdc9417583 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 9 Jul 2014 23:20:50 +0200 Subject: [PATCH 102/234] Workaround related to the unknown statusbar crash. --HG-- branch : gsoc2014-dfighter --- .../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 a222e44eaab12ab0a259bdd89b52c42abfe6a912 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:35:05 +0200 Subject: [PATCH 103/234] Implemented const_string_array editor. --HG-- branch : gsoc2014-dfighter --- .../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 8ff5317f011dbbc7a65c0ade61b186f8a2500616 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:37:32 +0200 Subject: [PATCH 104/234] Identation --HG-- branch : gsoc2014-dfighter --- .../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 aa82655ee77d49ecb4978941089cb19a1a215f8d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:41:15 +0200 Subject: [PATCH 105/234] Use \n instead of ; as a separator. --HG-- branch : gsoc2014-dfighter --- .../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 820b6bc8cab8c13ff24071088fa327afc470cc6b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 11 Jul 2014 20:47:24 +0200 Subject: [PATCH 106/234] Changed property to p, property is a reserved word in VS. --HG-- branch : gsoc2014-dfighter --- .../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 8f8b4fae65c6fc316a8e90571bce1c471a316b4d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 00:01:17 +0200 Subject: [PATCH 107/234] Store QtProperty, IPrimitive pairs and look the primitive up when the property changes. --HG-- branch : gsoc2014-dfighter --- .../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 3ad5ffee15d86cfb308ca1edc90b5812ca60792a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 00:38:35 +0200 Subject: [PATCH 108/234] Block only the propertychanged signal in the const_string_array property manager. --HG-- branch : gsoc2014-dfighter --- .../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 351728352610d9586d75b6e9052df211ac1ea1df Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 12 Jul 2014 01:54:45 +0200 Subject: [PATCH 109/234] Apply property changes. --HG-- branch : gsoc2014-dfighter --- .../world_editor/property_editor_widget.cpp | 133 +++++++++++++++++- .../world_editor/property_editor_widget.h | 9 ++ 2 files changed, 138 insertions(+), 4 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,19 +241,114 @@ void PropertyEditorWidget::updateSelection(Node *node) void PropertyEditorWidget::propertyChanged(QtProperty *p) { nlinfo(QString("property %1 changed").arg(p->propertyName()).toUtf8().constData()); - +} + +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 ) + 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::resetProperty(QtProperty *property) +void PropertyEditorWidget::onBoolValueChanged( QtProperty *p, bool v ) { - nlinfo(QString("property %1 reset").arg(property->propertyName()).toUtf8().constData()); + 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 2d865a85671f248c4bee1e73dbf8cc8952a31cb7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 13 Jul 2014 21:38:14 +0200 Subject: [PATCH 110/234] Trying to load an invalid world editor file shouldn't crash the application, and an error messagebox should inform the user. --HG-- branch : gsoc2014-dfighter --- .../world_editor/world_editor_misc.cpp | 93 ++++++++++++------- .../plugins/world_editor/world_editor_misc.h | 2 + .../world_editor/world_editor_window.cpp | 7 +- 3 files changed, 65 insertions(+), 37 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, ...) -{ - 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); -} +std::string lastError; -bool getPropertyString(std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName) +std::string getLastError() { - // 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 61b8a4ef820d6288417f89262f056f890200e749 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 01:30:30 +0200 Subject: [PATCH 111/234] Save world editor files. --HG-- branch : gsoc2014-dfighter --- .../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 56a4c3ea7d259270a9601e5e946b16d3d334d869 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 18:51:06 +0200 Subject: [PATCH 112/234] When changing a property make sure to set default to false, so it's actually saved! --HG-- branch : gsoc2014-dfighter --- .../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 1cbcca259c8a8e11712b88c6ab23f492f14a414a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 20:19:53 +0200 Subject: [PATCH 113/234] 'Fixed' the Mission Compiler crash. --HG-- branch : gsoc2014-dfighter --- .../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 63b6a03f85afbb944f5baa0c6da8d436aa0e6cec Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 20:29:57 +0200 Subject: [PATCH 114/234] Fixed another crash. --HG-- branch : gsoc2014-dfighter --- .../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 d30e9ad226c60ebdd63ee2bc1a73981666e835e6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 21:41:11 +0200 Subject: [PATCH 115/234] Initialize the undostack to NULL, so we get a proper crash instead of a dangled pointer crash. --HG-- branch : gsoc2014-dfighter --- .../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 28c30b70f15f72139c0bb585580c1517fd8e5500 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 15 Jul 2014 21:46:16 +0200 Subject: [PATCH 116/234] Set the undostack so we won't crash... --HG-- branch : gsoc2014-dfighter --- .../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 f60f761b7abbc81029a9dcb5957b2fa8ed56d631 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 16 Jul 2014 02:52:17 +0200 Subject: [PATCH 117/234] I don't really know what to write here. --HG-- branch : gsoc2014-dfighter --- .../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 d33fb9345e07caf756e1c4c4ee179934cc5c5d80 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 17 Jul 2014 19:08:29 +0200 Subject: [PATCH 118/234] UXT Editor widget --HG-- branch : gsoc2014-dfighter --- .../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 0de5152aa928b8f89c7a866450aeff096ff686a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 17 Jul 2014 19:17:02 +0200 Subject: [PATCH 119/234] Set header texts. --HG-- branch : gsoc2014-dfighter --- .../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 fbc1632d040861a6f52e28fe10e181b8989f5ef4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:27:05 +0200 Subject: [PATCH 120/234] Apply table changes to the loaded data, and offer to save when closing the changed table. --HG-- branch : gsoc2014-dfighter --- .../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 05216897f0e96e63feea777c1cc8ac5b0e5bd9b0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:50:40 +0200 Subject: [PATCH 121/234] Implemented saving. --HG-- branch : gsoc2014-dfighter --- .../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 9bda0bd1e7c81e92437ecb4cc83fec5b6484f683 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 00:53:36 +0200 Subject: [PATCH 122/234] Added copyright headers to the new files. --HG-- branch : gsoc2014-dfighter --- .../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 3e188334fe8ce8900e9144c457e3c7b29feef6af Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:08:31 +0200 Subject: [PATCH 123/234] Allow only 1 instance of the uxt editor. --HG-- branch : gsoc2014-dfighter --- .../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 485ee77406f367c2453fd5e476cba14666e0dd0e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:18:41 +0200 Subject: [PATCH 124/234] Use the QWidget modified property instead of the UXTEditor's own. --HG-- branch : gsoc2014-dfighter --- .../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 d9c2620e6e08f2e110ab6c4a6df638148b51539c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 18 Jul 2014 01:52:23 +0200 Subject: [PATCH 125/234] Implemented row deletion / insertion. --HG-- branch : gsoc2014-dfighter --- .../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 62a6b408a26534426964445b737148bd14e1c1d1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 19 Jul 2014 17:23:53 +0200 Subject: [PATCH 126/234] Show insert / delete row in context menu. --HG-- branch : gsoc2014-dfighter --- .../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 fbcfa4ee6f2dbb854ac00db7a0ec23a8993bfccc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 19 Jul 2014 17:26:59 +0200 Subject: [PATCH 127/234] Ask for confirmation before deleting a row. --HG-- branch : gsoc2014-dfighter --- .../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 2c812e90abac322b6c612dd4c670cfed404bb8e0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 17:24:04 +0200 Subject: [PATCH 128/234] Work with translated files, instead of work files. --HG-- branch : gsoc2014-dfighter --- .../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 76d3e0df20505b1107e9cfbaae9706ea6afa28ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 19:52:23 +0200 Subject: [PATCH 129/234] Set header text according to the language. --HG-- branch : gsoc2014-dfighter --- .../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 0bd4b565898443aca4cb9cbac7e65e730e119935 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 20 Jul 2014 20:03:16 +0200 Subject: [PATCH 130/234] Save to the right file. --HG-- branch : gsoc2014-dfighter --- .../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 2fea6f45f56445ba0dfb09ab070e1e9615c5b9f1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 03:24:18 +0200 Subject: [PATCH 131/234] Make sure a correct hash is not used for untranslated strings. --HG-- branch : gsoc2014-dfighter --- .../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 e92a07db33dc46af13976ba3c8ef70f53a8d7ba3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 03:51:03 +0200 Subject: [PATCH 132/234] New context menu options: mark / unmark translated. --HG-- branch : gsoc2014-dfighter --- .../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 26b120f664ed58ac6fd9ad8ac55239dd1786f5df Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 04:11:53 +0200 Subject: [PATCH 133/234] Mark translated item with green, untranslated ones with red. --HG-- branch : gsoc2014-dfighter --- .../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 ed44cc4823d5c629c367ab107af8c618c79366f0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 17:46:01 +0200 Subject: [PATCH 134/234] Shouldn't crash when adding a new row. --HG-- branch : gsoc2014-dfighter --- .../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 32172e0e77bee1ae5ea781602c050feeb7896745 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 23:08:05 +0200 Subject: [PATCH 135/234] Added save and save as items to the context menu. --HG-- branch : gsoc2014-dfighter --- .../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 3940e656e3d334842ef4269ac9fb972f768e3dc5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 21 Jul 2014 23:25:35 +0200 Subject: [PATCH 136/234] Error message when files can't be opened. --HG-- branch : gsoc2014-dfighter --- .../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 dcc072ba189093135b5cff89b24fea8c69ba90c0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 14:44:31 +0200 Subject: [PATCH 137/234] Update qrc location. --HG-- branch : gsoc2014-dfighter --- .../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 4d6de3f737114238a1c3c9a86361e33954c94e45 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 15:35:14 +0200 Subject: [PATCH 138/234] Don't allow 2 tilesets to have the same name. --HG-- branch : gsoc2014-dfighter --- .../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 5301b00e58abddc2fc52510c20d3c38367a7e56b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 22 Jul 2014 15:38:26 +0200 Subject: [PATCH 139/234] Don't try to delete the same items more than once! --HG-- branch : gsoc2014-dfighter --- 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 71fc4a098b3498b3d997ce472883a32a59bbc2d6 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Jul 2014 18:35:26 +0200 Subject: [PATCH 140/234] Implemented tileset removal. --HG-- branch : gsoc2014-dfighter --- .../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 9d1fec6ce19bec727ff352928cbef17554562693 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 Jul 2014 21:53:09 +0200 Subject: [PATCH 141/234] Implemented tileset rename. --HG-- branch : gsoc2014-dfighter --- .../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 c7ca20c748a69f8a11287af3b36cadc16846d55b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 02:28:19 +0200 Subject: [PATCH 142/234] Implemented tileset move up and move down. --HG-- branch : gsoc2014-dfighter --- .../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 e9e42701b94e223c2132c11dd007e91117db242b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:09:58 +0200 Subject: [PATCH 143/234] Renamed land related widgets. --HG-- branch : gsoc2014-dfighter --- .../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 02ccd3b1c16d63ce15ea617176e04810fa502f0c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:18:01 +0200 Subject: [PATCH 144/234] Implemented land adding. --HG-- branch : gsoc2014-dfighter --- .../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 9519c4f0f5c5114e3c738ecb69c59070167319a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:20:44 +0200 Subject: [PATCH 145/234] Implemented land removal. --HG-- branch : gsoc2014-dfighter --- .../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 947782a2c57a5fc37e0f8d76344907685a16e07d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 16:25:28 +0200 Subject: [PATCH 146/234] Implemented land name changing. --HG-- branch : gsoc2014-dfighter --- .../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 9b403212c04bdc085b5a0e8ff812862878ee1e38 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:31:07 +0200 Subject: [PATCH 147/234] Each land has it's own TilesetModel now. When changing the land the model also changes. --HG-- branch : gsoc2014-dfighter --- .../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 f66c1e837e5383439e7d344b86ca92a76419e762 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:39:34 +0200 Subject: [PATCH 148/234] Connect the selection model so the widgets are updated. --HG-- branch : gsoc2014-dfighter --- .../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 2993c88a5d3b6056f894149305805142340ccf23 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 18:44:00 +0200 Subject: [PATCH 149/234] When selecting another land, select the first tile set, if it exists. --HG-- branch : gsoc2014-dfighter --- .../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 df7307583b46383f51ad1d8e9924be9329c0d06e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 23:31:37 +0200 Subject: [PATCH 150/234] Implemented choosing / resetting vegetset for tile sets. --HG-- branch : gsoc2014-dfighter --- .../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 78f465406372cef8014dbe2df15017f73d7cfcbb Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 24 Jul 2014 23:41:42 +0200 Subject: [PATCH 151/234] Implemented tilebank texture path setting. --HG-- branch : gsoc2014-dfighter --- .../tile_editor/tile_editor_main_window.cpp | 23 ++++++++++++++++ .../tile_editor/tile_editor_main_window.h | 4 +++ .../tile_editor/tile_editor_main_window.ui | 27 +++++++------------ 3 files changed, 37 insertions(+), 17 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,6 +541,16 @@ + + + + Tile Bank Texture Path + + + + + + @@ -550,25 +560,8 @@ - - - - ... - - - - - - - Tile Bank Texture Path - - - - - - From d2a414edb41dd70646e60f20e9c58487e5fbce96 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 00:29:37 +0200 Subject: [PATCH 152/234] Implemented Tile addition. --HG-- branch : gsoc2014-dfighter --- .../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 d31dfdb6e4c21199dcd12b8e4454205b42ce716d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 00:32:42 +0200 Subject: [PATCH 153/234] I must be blind... --HG-- branch : gsoc2014-dfighter --- .../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 f0a67d0c2e648e92328d1a73b8fdfa7f8583f028 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 01:57:50 +0200 Subject: [PATCH 154/234] Implemented tile deletion. --HG-- branch : gsoc2014-dfighter --- .../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 e06858f2dfb84f4c4364354dda23dce944437339 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:05:21 +0200 Subject: [PATCH 155/234] Reindex tile item nodes after deleting a node. --HG-- branch : gsoc2014-dfighter --- .../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 599ba19de21e6a944fc94606f1c64f1a80897c14 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:11:02 +0200 Subject: [PATCH 156/234] A little refactoring. --HG-- branch : gsoc2014-dfighter --- .../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 5866a61cff2bc114a6ab06002f21df0e3961cb1b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:19:13 +0200 Subject: [PATCH 157/234] Implemented tile image deletion. --HG-- branch : gsoc2014-dfighter --- .../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 4326ca1df8250b95c9f09e03756d03734cf9755e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 26 Jul 2014 02:24:32 +0200 Subject: [PATCH 158/234] Implemented tile image replace. --HG-- branch : gsoc2014-dfighter --- .../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 b004bb9d01566fd51711e0098bb7b591b3441a99 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 27 Jul 2014 18:23:25 +0200 Subject: [PATCH 159/234] 128x128 tab should be shown by default. --HG-- branch : gsoc2014-dfighter --- 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 8a704b7f5fbe647f9e560a3a08eda8dbbbcb81f3 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 27 Jul 2014 20:38:08 +0200 Subject: [PATCH 160/234] Implemented the GUI part of saving... --HG-- branch : gsoc2014-dfighter --- .../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 89c618014467f8a9a001b812ea3e2b69b808cc80 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 28 Jul 2014 17:05:51 +0200 Subject: [PATCH 161/234] As it turns out, tilesets can be assigned to multiple lands... --HG-- branch : gsoc2014-dfighter --- .../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 | 159 +++++++++--------- .../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, 300 insertions(+), 89 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 ) - { - 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 ); - m_ui->listViewTransition->setModel( NULL ); - m_ui->listViewDisplacement->setModel( NULL ); - } - else + 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( 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 ] ); + TileSetNode *n = reinterpret_cast< TileSetNode* >( idx.internalPointer() ); + ts.push_back( n->getTileSetName() ); + } + + int r = m_ui->landLW->currentRow(); + Land &l = m_lands[ r ]; - connect( m_ui->tileSetLV->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), - this, SLOT( changeActiveTileSet( const QModelIndex &, const QModelIndex & ) ) ); + LandEditDialog d; + d.setTileSets( ts ); + int result = d.exec(); - if( m_ui->tileSetLV->model()->rowCount() != 0 ) - { - QModelIndex idx = m_ui->tileSetLV->model()->index( 0, 0 ); - m_ui->tileSetLV->setCurrentIndex( idx ); - } - } + if( result != QDialog::Accepted ) + return; - 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 95b67026bfa3b0e9967bf4200b52af96872bf322 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 01:29:17 +0200 Subject: [PATCH 162/234] Implemented saving of the currently stored tilebank data. --HG-- branch : gsoc2014-dfighter --- 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 ); + + // 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 false; + 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 ddc7961e9ba52122e8b9bde6de379112e640fe92 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 01:50:01 +0200 Subject: [PATCH 163/234] Connected the oriented combobox and now saving it's value to the tilebank. --HG-- branch : gsoc2014-dfighter --- .../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 c8914248db02721dcbbc621c0de13f907943920d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 07:43:02 +0200 Subject: [PATCH 164/234] Add the already selected tilesets to the land when editing. --HG-- branch : gsoc2014-dfighter --- .../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 431178321f6853087dc73eb015dbebf4f632b032 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 10:54:08 +0200 Subject: [PATCH 165/234] TileBank loading. --HG-- branch : gsoc2014-dfighter --- 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 0f5e475d1c49d9c3c8ecf67e1541010eb17a195f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 10:58:37 +0200 Subject: [PATCH 166/234] Save and load the veget set filename. --HG-- branch : gsoc2014-dfighter --- 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 3e2addc057a1e38a2f85fa53e9f6b5d0860baddc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:10:15 +0200 Subject: [PATCH 167/234] Save and load the tilebank texture path. --HG-- branch : gsoc2014-dfighter --- .../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 ac73999f07511a44124479e203cba825cb2cb820 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:14:41 +0200 Subject: [PATCH 168/234] Set teh current selection to row 0 --HG-- branch : gsoc2014-dfighter --- .../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 ddd687325f1329f39d0fa16c7a0ae25effcd1eb0 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:15:14 +0200 Subject: [PATCH 169/234] Close the loaded file and return true... --HG-- branch : gsoc2014-dfighter --- 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 4d54cca6a01a14587cdb76b40b210ad3260a1756 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 11:20:29 +0200 Subject: [PATCH 170/234] Copyright headers... --HG-- branch : gsoc2014-dfighter --- 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 7b1ee54427e53cc8c658d884028a67206d99fece Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 14:28:17 +0200 Subject: [PATCH 171/234] Show the image that belongs to the channel that is selected. --HG-- branch : gsoc2014-dfighter --- .../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 4bff87ca367e46ad6006982c6d769343871550ad Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 14:39:19 +0200 Subject: [PATCH 172/234] Replace and delete image should be applied to the correct channel now. --HG-- branch : gsoc2014-dfighter --- .../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 eee43ad1ea6a4e88e03372414454fb05c7da691c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:29:50 +0200 Subject: [PATCH 173/234] 128 and 256 tiles don't have alpha, so no need to load/save them. --HG-- branch : gsoc2014-dfighter --- 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 ac643d2bb91009a7ad0587935e0e20ab42d0e16f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:40:02 +0200 Subject: [PATCH 174/234] Should only add 1 tile here... --HG-- branch : gsoc2014-dfighter --- 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 0cef115a74b67eca03f31382472803d8d64ba6ff Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:44:02 +0200 Subject: [PATCH 175/234] Should store the filename after opening.. --HG-- branch : gsoc2014-dfighter --- 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 a994f23948ebc21c20b6a83ce09bbdfadd3898da Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 30 Jul 2014 15:55:09 +0200 Subject: [PATCH 176/234] When hitting 'save as' ask for a filename even if one is set. --HG-- branch : gsoc2014-dfighter --- .../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 1265d6b064ed1d1ed925d4aad2ae2d16c6ae98f9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Thu, 31 Jul 2014 23:23:52 +0200 Subject: [PATCH 177/234] Line endings... --HG-- branch : gsoc2014-dfighter --- 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 851afcf955e71db35eb2ae2b42bb9623e8fa3283 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 1 Aug 2014 02:34:57 +0200 Subject: [PATCH 178/234] Don't reload the pixmaps every time they are displayed... -.- --HG-- branch : gsoc2014-dfighter --- .../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 1a49f9fedb30ac1aad8b80567678ec5cdae805d2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 1 Aug 2014 02:38:04 +0200 Subject: [PATCH 179/234] Apply the current zoom factor! --HG-- branch : gsoc2014-dfighter --- 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 175af2fa749284da560c5b3becd18180800c82d4 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 04:15:12 +0200 Subject: [PATCH 180/234] Added checks. Yes it's horrible and needs to be refactored. --HG-- branch : gsoc2014-dfighter --- .../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 49deedad7d32395d50c8f3220abc9fe1aa7776fd Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 17:58:02 +0200 Subject: [PATCH 181/234] Save the tile border, etc data when saving. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_item.cpp | 23 +++-- .../src/plugins/tile_editor/tile_item.h | 9 +- .../plugins/tile_editor/tilebank_saver.cpp | 89 ++++++++++++++++--- 3 files changed, 101 insertions(+), 20 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 pvt->borderFirst( channel ); +} + +const NL3D::CTileBorder& TileItemNode::border( TileModel::TTileChannel channel ) const { - return false; + 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; + // Diffuse, Additive + for( int i = TileModel::TileDiffuse; i < TileModel::TileAlpha; i++ ) + { + 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 ); + } - for( int i = TileModel::TileDiffuse; i <= TileModel::TileAlpha; i++ ) + // Alpha { - QString fn = node->getTileFilename( TileModel::TTileChannel( i ) ); - tile->setFileName( channelToTBitmap( TileModel::TTileChannel( i ) ), fn.toUtf8().constData() ); + 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 299629860b20deead987a6c1a56d9bc3c5729919 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 19:04:34 +0200 Subject: [PATCH 182/234] Rotation can now be set. --HG-- branch : gsoc2014-dfighter --- .../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 30bae94ac3c6fe78104a87a9cf8079ce3c12352c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 3 Aug 2014 21:33:13 +0200 Subject: [PATCH 183/234] 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. --HG-- branch : gsoc2014-dfighter --- 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 | 28 ++--- .../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, 348 insertions(+), 136 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; } + QVariant pixmap( TileConstants::TTileChannel channel ) const; + private: - QMap m_tileFilename; - QMap m_tileWidget; + QMap m_tileFilename; + QMap m_tileWidget; - static TileModel::TTileChannel s_displayChannel; + 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 caf76f09c875c3fe476ef660a9786d33a717e4b7 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:22:44 +0200 Subject: [PATCH 184/234] Most of the functionality works with the new code. --HG-- branch : gsoc2014-dfighter --- .../src/plugins/tile_editor/tile_bank.cpp | 367 ++++++++++++++++-- .../src/plugins/tile_editor/tile_bank.h | 28 +- .../tile_editor/tile_editor_main_window.cpp | 158 +++----- .../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, 511 insertions(+), 873 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 removeTileSet( int idx ); + void renameTileSet( int idx, const QString &newName ); + void addLand( const QString &name ); + void removeLand( int idx ); void setLandSets( int idx, const QStringList &l ); - - bool addTileToSet( int idx, const QString &name, const QVariant &pixmap, TileConstants::TTileChannel channel, TileConstants::TNodeTileType type ); + 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 ) { - 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(); - error += "\nContinue?"; + if( m_tileModel->hasError() ) + error = m_tileModel->getLastError(); int reply = QMessageBox::question( this, tr( "Error adding tile" ), - error, + error + "\nContinue?", 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 parent = idx.parent(); - lv->model()->removeRow( row, parent ); + QModelIndex tsidx = m_ui->tileSetLV->currentIndex(); + if( !tsidx.isValid() ) + return; + int ts = tsidx.row(); + int tile = idx.row(); - //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 ); -} - -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 ); - } -} + int tile = n->id(); -void TileEditorMainWindow::onTileSetRenamed( const QString &oldname, const QString &newname ) -{ - 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 ]; - 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 688f6de0909cdd8c07ed7a683d4628d8c1bf7917 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:33:11 +0200 Subject: [PATCH 185/234] Vegetation set stuff. --HG-- branch : gsoc2014-dfighter --- .../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 55c046252f47eee82e29e571c5dbfe1175e412ec Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:41:33 +0200 Subject: [PATCH 186/234] Oriented stuff. --HG-- branch : gsoc2014-dfighter --- .../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 bdedd145e4b88567fbf9b8c03934c1845dddfb1e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:53:22 +0200 Subject: [PATCH 187/234] Surface data. --HG-- branch : gsoc2014-dfighter --- .../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 92e850d296155eded085a56c4fa1dbf762f61faf Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 21:59:05 +0200 Subject: [PATCH 188/234] Texture path. --HG-- branch : gsoc2014-dfighter --- 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 8bead3f3fdbe2d9b7ab44ad18e45691f690d5f02 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 4 Aug 2014 22:14:39 +0200 Subject: [PATCH 189/234] Saving tilebank --HG-- branch : gsoc2014-dfighter --- 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 d21aa2b678a0da9dd92340fbb20aca364f2b098d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 02:58:31 +0200 Subject: [PATCH 190/234] Tile loading more or less works. TODO: investigate why displacement map lookup causes crashes. --HG-- branch : gsoc2014-dfighter --- 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 2a55904b3e77ef10c0d1250249fea234f176bd7e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:17:29 +0200 Subject: [PATCH 191/234] Makes no sense, but doesn't seem to be crashing anymore o.O --HG-- branch : gsoc2014-dfighter --- 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 84fc5f27b61e537b730e7bc00e4eade1e85a3099 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:20:30 +0200 Subject: [PATCH 192/234] Clear before loading the model data. --HG-- branch : gsoc2014-dfighter --- 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 e2a579c03e994420d13dd6c120f3de2aa6365bb5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 03:35:10 +0200 Subject: [PATCH 193/234] Set all images by default. --HG-- branch : gsoc2014-dfighter --- .../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 99bcb6cf79f66ca8c3e08f0e12f2f454d31bb36e Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 13:18:41 +0200 Subject: [PATCH 194/234] Line endings and copyright headers... --HG-- branch : gsoc2014-dfighter --- .../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 f25d152f4fff5d2bbf3c23bfc0243b9aaeb748d5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 13:42:56 +0200 Subject: [PATCH 195/234] Rotation is now set in the tilebank wrapper and applied when replacing a tile. --HG-- branch : gsoc2014-dfighter --- .../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 04d17b7a05a094f08106fdd2490dfc7b49def19d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 15:16:25 +0200 Subject: [PATCH 196/234] Save the last directoy where we loaded a tilebank from. --HG-- branch : gsoc2014-dfighter --- .../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 edf1da1294baf0641122327732d9f106a2789c35 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 15:34:29 +0200 Subject: [PATCH 197/234] Save the last directory where we loaded a tile image from. --HG-- branch : gsoc2014-dfighter --- .../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 613643b033a5785a20dc97b4e3cfd543dad63740 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 5 Aug 2014 16:01:45 +0200 Subject: [PATCH 198/234] Repaint immediately when the display channel is changed. --HG-- branch : gsoc2014-dfighter --- .../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 e7ded1f82c25ea3ac775844daa51457b82e31f31 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:01:44 +0200 Subject: [PATCH 199/234] Removed unused variable. --HG-- branch : gsoc2014-dfighter --- 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 669c15eda90966c51ae11735c5fe7edfbefbc6fc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:04:30 +0200 Subject: [PATCH 200/234] Removed yet another unused variable. --HG-- branch : gsoc2014-dfighter --- 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 9bb62a3ada3719c18aca589dacb50ba4efadf8b9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 13:25:50 +0200 Subject: [PATCH 201/234] 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. --HG-- branch : gsoc2014-dfighter --- .../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 20edb57761c9c9de84eaf3172345ec9f2a0e381a Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 17:14:59 +0200 Subject: [PATCH 202/234] If I add a 256x256 tile, maybe I should remove it as 256x256, not 128x128... --HG-- branch : gsoc2014-dfighter --- 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 50b90f97745de60946ef63afd250445140ab5cf5 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 17:40:39 +0200 Subject: [PATCH 203/234] Update the tile list right away if the image is replaced. --HG-- branch : gsoc2014-dfighter --- 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 48bd3cb38307813e0bc75733913f04eadfd885ff Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 19:54:01 +0200 Subject: [PATCH 204/234] Fixed qrc path. --HG-- branch : gsoc2014-dfighter --- 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 475c0201ea04b8fcf0ab887896384a024c3df153 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:10:11 +0200 Subject: [PATCH 205/234] GUI Editor Linux build fix --HG-- branch : gsoc2014-dfighter --- 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 7f6608b897425f25488e71c77fc616c703464a8d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:12:46 +0200 Subject: [PATCH 206/234] World Editor plugin Linux build fix. --HG-- branch : gsoc2014-dfighter --- 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 033c86e92cb5b009bec080469d321bd5ea53e490 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 6 Aug 2014 22:59:58 +0200 Subject: [PATCH 207/234] Add the property browser library to the CPack archive when generated. --HG-- branch : gsoc2014-dfighter --- 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 9315b7229eda1abe0b67f8acb8d66357374188a9 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sun, 10 Aug 2014 15:25:59 +0200 Subject: [PATCH 208/234] Don't enter edit mode in the treeview. --HG-- branch : gsoc2014-dfighter --- .../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 a43c2f0a5ee60aff752faf2dc95995ef000bf77d Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 19:26:55 +0200 Subject: [PATCH 209/234] First iteration of the property browser. --HG-- branch : gsoc2014-dfighter --- .../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 1b7b081c60a13ff22c22858b8eea95060c590564 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 20:17:10 +0200 Subject: [PATCH 210/234] Shown properties can now be edited. --HG-- branch : gsoc2014-dfighter --- .../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 aa95cc3c4ba056b3f0b1b7f542f44ea9eb43ec40 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Tue, 12 Aug 2014 21:00:33 +0200 Subject: [PATCH 211/234] Apply changes. --HG-- branch : gsoc2014-dfighter --- .../plugins/georges_editor/browser_ctrl.cpp | 42 +++++++++++++++++++ .../src/plugins/georges_editor/browser_ctrl.h | 10 ++++- 2 files changed, 51 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 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 Q_SLOTS: + void onValueChanged( QtProperty *p, const QVariant &value ); + private: - BrowserCtrlPvt *m_pvt; + void enableMgrConnections(); + void disableMgrConnections(); + + BrowserCtrlPvt *m_pvt; NLGEORGES::UForm *m_form; }; From c740d5a7730fa2ae375234d083c5905c1d7eb8b2 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Fri, 15 Aug 2014 23:49:12 +0200 Subject: [PATCH 212/234] 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. --HG-- branch : gsoc2014-dfighter --- .../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 5812058ea650234f12e49e00f8c849f2403e8adc Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:01:07 +0200 Subject: [PATCH 213/234] Only add atoms to the property browser. --HG-- branch : gsoc2014-dfighter --- .../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 99502a1bfc7057fd294ba27a6acae4995ed4390c Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:47:29 +0200 Subject: [PATCH 214/234] Handle selected arrays too ( show size, changing it isn't implemented yet ). --HG-- branch : gsoc2014-dfighter --- .../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 2a0af6cabf1810208145cc9f2a84c5a4b0fafd61 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 02:51:30 +0200 Subject: [PATCH 215/234] Only add atoms to the property browser.. --HG-- branch : gsoc2014-dfighter --- 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 6d074bc618376a150757aaf1bf2754ca79040837 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 03:10:50 +0200 Subject: [PATCH 216/234] Only add atoms to the property browser.. --HG-- branch : gsoc2014-dfighter --- 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 fb5ce7baacb77b75427f3df8015587fa09efae41 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Sat, 16 Aug 2014 03:46:52 +0200 Subject: [PATCH 217/234] Use the string 'array size' as the name for the property holding the array size. --HG-- branch : gsoc2014-dfighter --- 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 41f6e70dc93f6e7a894c0c8ed022f4c7fbd646c3 Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 17 Aug 2014 15:39:30 +0200 Subject: [PATCH 218/234] Fixed #172 XML floating point serialization not using neutral culture --- code/nel/include/nel/misc/i_xml.h | 3 +++ code/nel/src/misc/i_xml.cpp | 43 +++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/code/nel/include/nel/misc/i_xml.h b/code/nel/include/nel/misc/i_xml.h index a9452e341..cf2527e21 100644 --- a/code/nel/include/nel/misc/i_xml.h +++ b/code/nel/include/nel/misc/i_xml.h @@ -232,6 +232,9 @@ private: // If not NULL, binary mode detected, use this stream in serials IStream *_BinaryStream; + + // System dependant structure for locale + void* _Locale; }; diff --git a/code/nel/src/misc/i_xml.cpp b/code/nel/src/misc/i_xml.cpp index d8925ddef..3b7f0f9e2 100644 --- a/code/nel/src/misc/i_xml.cpp +++ b/code/nel/src/misc/i_xml.cpp @@ -24,6 +24,11 @@ // Include from libxml2 #include +#if defined(NL_OS_WINDOWS) && defined(NL_COMP_VC_VERSION) && NL_COMP_VC_VERSION >= 80 +#define USE_LOCALE_ATOF +#include +#endif + using namespace std; #define NLMISC_READ_BUFFER_SIZE 1024 @@ -46,6 +51,22 @@ const char SEPARATOR = ' '; serialSeparatedBufferIn( number_as_string ); \ dest = (thetype)convfunc( number_as_string.c_str() ); +#ifdef USE_LOCALE_ATOF + +#define readnumberlocale(dest,thetype,digits,convfunc) \ + string number_as_string; \ + serialSeparatedBufferIn( number_as_string ); \ + dest = (thetype)convfunc( number_as_string.c_str(), (_locale_t)_Locale ); + +#define nl_atof _atof_l + +#else + +#define readnumberlocale(dest,thetype,digits,convfunc) readnumber(dest,thetype,digits,convfunc) +#define nl_atof atof + +#endif + // *************************************************************************** inline void CIXml::flushContentString () @@ -70,6 +91,13 @@ CIXml::CIXml () : IStream (true /* Input mode */) _ErrorString = ""; _TryBinaryMode = false; _BinaryStream = NULL; + +#ifdef USE_LOCALE_ATOF + // create C numeric locale + _Locale = _create_locale(LC_NUMERIC, "C"); +#else + _Locale = NULL; +#endif } // *************************************************************************** @@ -85,6 +113,13 @@ CIXml::CIXml (bool tryBinaryMode) : IStream (true /* Input mode */) _ErrorString = ""; _TryBinaryMode = tryBinaryMode; _BinaryStream = NULL; + +#ifdef USE_LOCALE_ATOF + // create C numeric locale + _Locale = _create_locale(LC_NUMERIC, "C"); +#else + _Locale = NULL; +#endif } // *************************************************************************** @@ -119,6 +154,10 @@ void CIXml::release () _ErrorString = ""; resetPtrTable(); + +#ifdef USE_LOCALE_ATOF + if (_Locale) _free_locale((_locale_t)_Locale); +#endif } // *************************************************************************** @@ -546,7 +585,7 @@ void CIXml::serial(float &b) } else { - readnumber( b, float, 128, atof ); + readnumberlocale( b, float, 128, nl_atof ); } } @@ -560,7 +599,7 @@ void CIXml::serial(double &b) } else { - readnumber( b, double, 128, atof ); + readnumberlocale( b, double, 128, nl_atof ); } } From 75e28415193e7923a18f5bc813107d42f40acbdb Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 15:58:42 +0200 Subject: [PATCH 219/234] Fix continent path bug --- code/nel/tools/3d/zone_lighter/zone_lighter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp index 9b6df0900..1add65a9d 100644 --- a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp +++ b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp @@ -202,7 +202,7 @@ static void loadIGFromContinent(NLMISC::CConfigFile ¶meter, std::list Date: Sun, 17 Aug 2014 16:02:51 +0200 Subject: [PATCH 220/234] Additional fix #172 set _Locale to NULL after release --- code/nel/src/misc/i_xml.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/nel/src/misc/i_xml.cpp b/code/nel/src/misc/i_xml.cpp index 3b7f0f9e2..8a624dd5f 100644 --- a/code/nel/src/misc/i_xml.cpp +++ b/code/nel/src/misc/i_xml.cpp @@ -157,6 +157,7 @@ void CIXml::release () #ifdef USE_LOCALE_ATOF if (_Locale) _free_locale((_locale_t)_Locale); + _Locale = NULL; #endif } From 31e9934ba7a23d865f1c27c4d02bb3d71b945d01 Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 17 Aug 2014 16:05:51 +0200 Subject: [PATCH 221/234] Changed #172 XML floating point serialization not using neutral culture --- code/nel/src/misc/i_xml.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/nel/src/misc/i_xml.cpp b/code/nel/src/misc/i_xml.cpp index 3b7f0f9e2..ee3f39a89 100644 --- a/code/nel/src/misc/i_xml.cpp +++ b/code/nel/src/misc/i_xml.cpp @@ -128,6 +128,10 @@ CIXml::~CIXml () { // Release release (); + +#ifdef USE_LOCALE_ATOF + if (_Locale) _free_locale((_locale_t)_Locale); +#endif } // *************************************************************************** @@ -154,10 +158,6 @@ void CIXml::release () _ErrorString = ""; resetPtrTable(); - -#ifdef USE_LOCALE_ATOF - if (_Locale) _free_locale((_locale_t)_Locale); -#endif } // *************************************************************************** From e0e1953f4144d8b26cb811f6b259159db0328076 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 16:22:56 +0200 Subject: [PATCH 222/234] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/zone_lighter/zone_lighter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp index 1add65a9d..b3c6807c1 100644 --- a/code/nel/tools/3d/zone_lighter/zone_lighter.cpp +++ b/code/nel/tools/3d/zone_lighter/zone_lighter.cpp @@ -699,6 +699,12 @@ int main(int argc, char* argv[]) if(group->getInstance(instance).DontCastShadow || group->getInstance(instance).DontCastShadowForExterior) continue; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // PS ? if (toLower (CFile::getExtension (name)) == "ps") continue; From 8f7931d6a833acd290ce52548c2b11db6a242fe4 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 16:41:09 +0200 Subject: [PATCH 223/234] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp b/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp index 0010d5179..a6636730f 100644 --- a/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp +++ b/code/nel/tools/3d/zone_ig_lighter/zone_ig_lighter.cpp @@ -410,6 +410,12 @@ int main(int argc, char* argv[]) if(group->getInstance(instance).DontCastShadow || group->getInstance(instance).DontCastShadowForExterior) continue; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // Add a .shape at the end ? if (!name.empty()) { From d4b7a3cf8acdff5e756196f563cc13ad9002abfb Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 16:48:51 +0200 Subject: [PATCH 224/234] Crashfix in case pacs_prim are exported into .ig --- code/nel/src/3d/instance_lighter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/src/3d/instance_lighter.cpp b/code/nel/src/3d/instance_lighter.cpp index f754ebb8b..d21f80e4e 100644 --- a/code/nel/src/3d/instance_lighter.cpp +++ b/code/nel/src/3d/instance_lighter.cpp @@ -408,6 +408,12 @@ void CInstanceLighter::light (const CInstanceGroup &igIn, CInstanceGroup &igOut, string name= _Instances[i].Name; bool shapeFound= true; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // Try to find the shape in the UseShapeMap. std::map::const_iterator iteMap= lightDesc.UserShapeMap.find (name); From 9a19f2041b4d5e83a855374a26ff2ff7481a62b6 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 19:37:20 +0200 Subject: [PATCH 225/234] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp b/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp index 4365eab9b..8286a10e6 100644 --- a/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp +++ b/code/nel/tools/3d/ig_lighter_lib/ig_lighter_lib.cpp @@ -167,6 +167,12 @@ void CIgLighterLib::lightIg(CInstanceLighter &instanceLighter, string name= igIn.getShapeName(i); bool shapeFound= true; + if (toLower (CFile::getExtension (name)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", name.c_str()); + continue; + } + // Try to find the shape in the UseShapeMap. std::map::const_iterator iteMap= lightDesc.UserShapeMap.find (name); From 0e0de8ec52698c7aae3bf829bfb88058e596ae5e Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 17 Aug 2014 19:40:43 +0200 Subject: [PATCH 226/234] Fix shape lightmap optimize --- code/nel/tools/build_gamedata/processes/shape/0_setup.py | 1 + code/nel/tools/build_gamedata/processes/shape/2_build.py | 7 +++++-- code/nel/tools/build_gamedata/processes/shape/3_install.py | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/code/nel/tools/build_gamedata/processes/shape/0_setup.py b/code/nel/tools/build_gamedata/processes/shape/0_setup.py index 71dfd097e..941d07531 100755 --- a/code/nel/tools/build_gamedata/processes/shape/0_setup.py +++ b/code/nel/tools/build_gamedata/processes/shape/0_setup.py @@ -69,6 +69,7 @@ if BuildShadowSkinEnabled: printLog(log, ">>> Setup build directories <<<") mkPath(log, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory) mkPath(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory) +mkPath(log, ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory) mkPath(log, ExportBuildDirectory + "/" + ShapeLightmapBuildDirectory) mkPath(log, ExportBuildDirectory + "/" + ShapeLightmap16BitsBuildDirectory) diff --git a/code/nel/tools/build_gamedata/processes/shape/2_build.py b/code/nel/tools/build_gamedata/processes/shape/2_build.py index 48a658378..1a9f668f8 100755 --- a/code/nel/tools/build_gamedata/processes/shape/2_build.py +++ b/code/nel/tools/build_gamedata/processes/shape/2_build.py @@ -77,16 +77,19 @@ else: # copy lightmap_not_optimized to lightmap printLog(log, ">>> Optimize lightmaps <<<") loPathLightmapsOriginal = ExportBuildDirectory + "/" + ShapeLightmapNotOptimizedExportDirectory +loPathShapesOriginal = ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory mkPath(log, loPathLightmapsOriginal) loPathLightmaps = ExportBuildDirectory + "/" + ShapeLightmapBuildDirectory -loPathShapes = ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory +loPathShapes = ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory loPathTags = ExportBuildDirectory + "/" + ShapeTagExportDirectory mkPath(log, loPathLightmaps) mkPath(log, loPathShapes) mkPath(log, loPathTags) -if needUpdateDirByTagLog(log, loPathLightmapsOriginal, ".txt", loPathLightmaps, ".txt") or needUpdateDirNoSubdir(log, loPathLightmapsOriginal, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathShapes, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathTags, loPathLightmaps): +if needUpdateDirByTagLog(log, loPathLightmapsOriginal, ".txt", loPathLightmaps, ".txt") or needUpdateDirNoSubdir(log, loPathLightmapsOriginal, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathShapesOriginal, loPathShapes) or needUpdateDirNoSubdir(log, loPathShapes, loPathLightmaps) or needUpdateDirNoSubdir(log, loPathTags, loPathLightmaps): removeFilesRecursive(log, loPathLightmaps) copyFiles(log, loPathLightmapsOriginal, loPathLightmaps) + removeFilesRecursive(log, loPathShapes) + copyFiles(log, loPathShapesOriginal, loPathShapes) # Optimize lightmaps if any. Additionnaly, output a file indicating which lightmaps are 8 bits # lightmap_optimizer [path_tags] [path_flag8bit] subprocess.call([ LightmapOptimizer, loPathLightmaps, loPathShapes, loPathTags, ExportBuildDirectory + "/" + ShapeLightmapBuildDirectory + "/list_lm_8bit.txt" ]) diff --git a/code/nel/tools/build_gamedata/processes/shape/3_install.py b/code/nel/tools/build_gamedata/processes/shape/3_install.py index cb93a443b..f6265a1a6 100755 --- a/code/nel/tools/build_gamedata/processes/shape/3_install.py +++ b/code/nel/tools/build_gamedata/processes/shape/3_install.py @@ -46,8 +46,8 @@ printLog(log, "") printLog(log, ">>> Install shape <<<") installPath = InstallDirectory + "/" + ShapeInstallDirectory mkPath(log, installPath) -mkPath(log, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory) -copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeClodtexBuildDirectory, installPath, ".shape") +mkPath(log, ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory) +copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeOptimizedBuildDirectory, installPath, ".shape") mkPath(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory) copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory, installPath, ".shape") copyFilesExtNoTreeIfNeeded(log, ExportBuildDirectory + "/" + ShapeWithCoarseMeshBuildDirectory, installPath, ".dds") From 6000fe187f15932076b7c67a73dbfa5126856ce1 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 18 Aug 2014 01:50:07 +0200 Subject: [PATCH 227/234] Moved BrowserCtrlPvt to it's own files. --HG-- branch : gsoc2014-dfighter --- .../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 c9f54c38061a6b2a5b0c4679c58387b1c11805b9 Mon Sep 17 00:00:00 2001 From: shubham_meena Date: Mon, 18 Aug 2014 07:13:15 +0530 Subject: [PATCH 228/234] Improved documentation with doxygen generated doc --- code/web/private_php/ams/autoload/dblayer.php | 97 ++++++++++++------- .../private_php/ams/autoload/plugincache.php | 26 +++-- .../web/private_php/ams/autoload/rest_api.php | 8 +- .../private_php/ams/autoload/ticket_log.php | 2 +- .../ams/plugins/API_key_management/.info | 2 +- .../public_php/ams/func/activate_plugin.php | 8 +- .../public_php/ams/func/deactivate_plugin.php | 10 +- .../web/public_php/ams/func/delete_plugin.php | 8 +- .../public_php/ams/func/install_plugin.php | 41 ++++++-- .../web/public_php/ams/func/update_plugin.php | 6 +- .../web/public_php/ams/inc/plugins_update.php | 2 +- 11 files changed, 146 insertions(+), 64 deletions(-) diff --git a/code/web/private_php/ams/autoload/dblayer.php b/code/web/private_php/ams/autoload/dblayer.php index 43282789e..7c4c5435c 100644 --- a/code/web/private_php/ams/autoload/dblayer.php +++ b/code/web/private_php/ams/autoload/dblayer.php @@ -3,13 +3,36 @@ * Handles the database connections. It uses PDO to connect to the different databases. It will use the argument of the constructor to setup a connection to the database * with the matching entry in the $cfg global variable. * + * --> First create an object of dblayer --> $db = new DBLayer('short database name used in config') + * + * --> Insert --> $db->insert( $tb_name, $data ) + * $tb_name = table name in which we want to insert data + * $data = array of data that needs to be inserted in format('fieldname' => $value) where fieldname must be a field in that table. + * + * --> select --> $db->select( $tb_name, $data, $where ) + * $tb_name = table name which we want to select + * $data = array of data which is then required in WHERE clause in format array('fieldname'=>$value) fieldname must be a field in that table. + * $where = string in format ('fieldname=:fieldname') where :fieldname takes it's value from $data array. + * + * --> update --> $db->update( $tb_name, $data, $where ) + * $tb_name = table name which we want to update + * $data = array of data which contains the filelds that need to be updated with their values in the format('fieldname' => $value,...) where fieldname must be a field in that table. + * $where = string contains the filename with a value at that field in the format ('fieldname = $value') where fieldname must be a field in that table and $value is value respect to that field. + * + * --> delete --> $db->delete( $tb_name, $data, $where ) + * $tb_name = table name where we want to delete. + * $data = array of data which is then required in WHERE clause in format array('fieldname'=> $value) where fieldname must be a field in that table. + * $where = string in format ('fieldname=:fieldname') where :fieldname takes it's value from $data array. + * + * * @author Daan Janssens, mentored by Matthew Lagoe + * */ class DBLayer { private $PDO; /** - * *< The PDO object, instantiated by the constructor + * The PDO object, instantiated by the constructor */ /** @@ -17,6 +40,7 @@ class DBLayer { * Instantiates the PDO object attribute by connecting to the arguments matching database(the db info is stored in the $cfg global var) * * @param $db String, the name of the databases entry in the $cfg global var. + * @param $dbn String, the name of the databases entry in the $cfg global var if $db referenced to an action(install etc). */ function __construct( $db, $dbn = null ) { @@ -49,10 +73,10 @@ class DBLayer { } /** - * execute a query that doesn't have any parameters + * Execute a query that doesn't have any parameters. * - * @param $query the mysql query - * @return returns a PDOStatement object + * @param $query the mysql query. + * @return returns a PDOStatement object. */ public function executeWithoutParams( $query ) { $statement = $this -> PDO -> prepare( $query ); @@ -61,11 +85,11 @@ class DBLayer { } /** - * execute a query that has parameters + * Execute a query that has parameters. * - * @param $query the mysql query - * @param $params the parameters that are being used by the query - * @return returns a PDOStatement object + * @param $query the mysql query. + * @param $params the parameters that are being used by the query. + * @return returns a PDOStatement object. */ public function execute( $query, $params ) { $statement = $this -> PDO -> prepare( $query ); @@ -74,10 +98,10 @@ class DBLayer { } /** - * execute a query (an insertion query) that has parameters and return the id of it's insertion + * Insert function which returns id of the inserting field. * - * @param $query the mysql query - * @param $params the parameters that are being used by the query + * @param $tb_name table name where we want to insert data. + * @param $data the parameters that are being inserted into table. * @return returns the id of the last inserted element. */ public function executeReturnId( $tb_name, $data ) { @@ -104,12 +128,14 @@ class DBLayer { } /** - * Select function using prepared statement + * Select function using prepared statement. + * For selecting particular fields. * - * @param string $tb_name Table Name to Select - * @param array $data Associative array - * @param string $where where to select - * @return statement object + * @param string $param field to select, can be multiple fields. + * @param string $tb_name Table Name to Select. + * @param array $data array of data to be used in WHERE clause in format('fieldname'=>$value). 'fieldname' must be a field in that table. + * @param string $where where to select. + * @return statement object. */ public function selectWithParameter( $param, $tb_name, $data, $where ) { @@ -129,12 +155,13 @@ class DBLayer { } /** - * Select function using prepared statement + * Select function using prepared statement. + * For selecting all fields in a table. * - * @param string $tb_name Table Name to Select - * @param array $data Associative array - * @param string $where where to select - * @return statement object + * @param string $tb_name Table Name to Select. + * @param array $data array of data to be used with WHERE part in format('fieldname'=>$value,...). 'fieldname' must be a field in that table. + * @param string $where where to select in format('fieldname=:fieldname' AND ...). + * @return statement object. */ public function select( $tb_name, $data , $where ) { @@ -154,12 +181,12 @@ class DBLayer { } /** - * Update function with prepared statement + * Update function with prepared statement. * - * @param string $tb_name name of the table - * @param array $data associative array with values - * @param string $where where part - * @throws Exception error in updating + * @param string $tb_name name of the table on which operation to be performed. + * @param array $data array of data in format('fieldname' => $value,...).Here, only those fields must be stored which needs to be updated. + * @param string $where where part in format ('fieldname'= $value AND ...). 'fieldname' must be a field in that table. + * @throws Exception error in updating. */ public function update( $tb_name, $data, $where ) { @@ -190,10 +217,11 @@ class DBLayer { } /** - * insert function using prepared statements + * insert function using prepared statements. * - * @param string $tb_name Name of the table to insert in - * @param array $data Associative array of data to insert + * @param string $tb_name Name of the table on which operation to be performed. + * @param array $data array of data to insert in format('fieldname' => $value,....). 'fieldname' must be a field in that table. + * @throws error in inserting. */ public function insert( $tb_name, $data ) { @@ -216,16 +244,17 @@ class DBLayer { { // for rolling back the changes during transaction $this -> PDO -> rollBack(); - throw new Exception( "error in inseting" ); + throw new Exception( "error in inserting" ); } } /** - * Delete database entery using prepared statement + * Delete database entery using prepared statement. * - * @param string $tb_name - * @param string $where - * @throws error in deleting + * @param string $tb_name table name on which operations to be performed. + * @param $data array with values in the format('fieldname'=> $value,...). 'fieldname' must be a field in that table. + * @param string $where condition based on $data array in the format('fieldname=:fieldname' AND ...). + * @throws error in deleting. */ public function delete( $tb_name, $data, $where ) { diff --git a/code/web/private_php/ams/autoload/plugincache.php b/code/web/private_php/ams/autoload/plugincache.php index c90665bc1..8ff258513 100644 --- a/code/web/private_php/ams/autoload/plugincache.php +++ b/code/web/private_php/ams/autoload/plugincache.php @@ -2,7 +2,7 @@ /** * API for loading and interacting with plugins - * contains getters and setters + * contains getters and setters. * * @author shubham meena mentored by Matthew Lagoe */ @@ -14,11 +14,11 @@ class Plugincache { private $plugin_status; private $plugin_info = array(); private $update_info = array(); + /** * A constructor. * Empty constructor */ - public function __construct() { } @@ -207,10 +207,12 @@ class Plugincache { } /** - * returns plugin information with respect to the id + * Returns plugin information with respect to the id. * - * @param id $ plugin id - * @return field info for the plugin + * @param $id plugin id. + * @param $fieldName string plugin field to return + * + * @return info field from the db. */ public static function pluginInfoUsingId( $id, $fieldName ) { @@ -221,9 +223,9 @@ class Plugincache { } /** - * function provides list of active plugins + * Function provides list of active plugins * - * @return $ac_plugins list of active plugins + * @return list of active plugins */ public static function activePlugins() { @@ -235,9 +237,15 @@ class Plugincache { /** * function to load hooks for the active plugins - * and return the contents in the hooks in an array + * and return the contents get from them. + * + * -->Get the list of active plugins then call the global + * hooks exists in the plugins hook file ($pluginName.php). + * -->Collect the contents from the hooks and associate within + * array with key referenced plugin name. + * -->return the content to use with smarty template loader * - * @return $content content available in hooks + * @return $content content get from hooks */ public static function loadHooks() { diff --git a/code/web/private_php/ams/autoload/rest_api.php b/code/web/private_php/ams/autoload/rest_api.php index 74281c6f6..e35586042 100644 --- a/code/web/private_php/ams/autoload/rest_api.php +++ b/code/web/private_php/ams/autoload/rest_api.php @@ -5,7 +5,7 @@ * * Request for the given url using cURL * and send the AccessToken for authentication - * to make public access for the user + * to make public access for the user. * * @author Shubham Meena, mentored by Matthew Lagoe */ @@ -13,12 +13,14 @@ class Rest_Api { /** - * Makes a request using cURL with authentication headers and returns the response. + * Makes a request using cURL with authentication headers , data to post and returns the response. * * @param $url where request is to be sent * @param $applicationKey user generated key * @param $host host for the website - * @return URL response. + * @param $data data to send using POST request + * + * @return $response URL response. */ public function request( $url , $applicationKey, $host , $data ) { diff --git a/code/web/private_php/ams/autoload/ticket_log.php b/code/web/private_php/ams/autoload/ticket_log.php index 6693fe3ce..f83d4b29e 100644 --- a/code/web/private_php/ams/autoload/ticket_log.php +++ b/code/web/private_php/ams/autoload/ticket_log.php @@ -143,7 +143,7 @@ class Ticket_Log{ /** * loads the object's attributes. * loads the object's attributes by giving a ticket_log entries ID (TLogId). - * @param id the id of the ticket_log entry that should be loaded + * @param $id the id of the ticket_log entry that should be loaded */ public function load_With_TLogId( $id) { $dbl = new DBLayer("lib"); diff --git a/code/web/private_php/ams/plugins/API_key_management/.info b/code/web/private_php/ams/plugins/API_key_management/.info index b185a31db..1da25516e 100644 --- a/code/web/private_php/ams/plugins/API_key_management/.info +++ b/code/web/private_php/ams/plugins/API_key_management/.info @@ -1,7 +1,7 @@ PluginName = API Key Management Description = Provides public access to the API's by generating access tokens. Version = 1.0.0 -Type = automatic +Type = Manual TemplatePath = ../../../ams_lib/plugins/API_key_management/templates/index.tpl diff --git a/code/web/public_php/ams/func/activate_plugin.php b/code/web/public_php/ams/func/activate_plugin.php index 930ed15f1..0a331f284 100644 --- a/code/web/public_php/ams/func/activate_plugin.php +++ b/code/web/public_php/ams/func/activate_plugin.php @@ -1,6 +1,9 @@ update( "plugins", array( 'Status' => '1' ), "Id = $id" ); if ( $result ) { + // if result is successfull it redirects and shows success message header( "Location: index.php?page=plugins&result=3" ); exit; } else { + //if result is unsuccessfull it redirects and throws error header( "Location: index.php?page=plugins&result=4" ); exit; } } else { + //if $_GET variable is not set it redirects and shows error header( "Location: index.php?page=plugins&result=4" ); exit; } diff --git a/code/web/public_php/ams/func/deactivate_plugin.php b/code/web/public_php/ams/func/deactivate_plugin.php index a4b6120b1..91986bb50 100644 --- a/code/web/public_php/ams/func/deactivate_plugin.php +++ b/code/web/public_php/ams/func/deactivate_plugin.php @@ -1,6 +1,9 @@ update( "plugins", array( 'Status' => '0' ), "Id = $id" ); if ( $result ) - { + { + // if result is successfull it redirects and shows success message header( "Location: index.php?page=plugins&result=5" ); exit; } else { + // if result is unsuccessfull it redirects and shows success message header( "Location: index.php?page=plugins&result=6" ); exit; @@ -30,6 +35,7 @@ function deactivate_plugin() { } else { + //if $_GET variable is not set it redirects and shows error header( "Location: index.php?page=plugins&result=6" ); exit; } diff --git a/code/web/public_php/ams/func/delete_plugin.php b/code/web/public_php/ams/func/delete_plugin.php index f3dc0311a..d85ed34b9 100644 --- a/code/web/public_php/ams/func/delete_plugin.php +++ b/code/web/public_php/ams/func/delete_plugin.php @@ -1,8 +1,9 @@ delete( 'plugins', array( 'id' => $id ), "Id=:id" ); + //if result successfull redirect and show success message header( "Location: index.php?page=plugins&result=2" ); exit; } else { + // if result unsuccessfull redirect and show error message header( "Location: index.php?page=plugins&result=0" ); exit; } @@ -40,6 +43,7 @@ function delete_plugin() { } else { + // if result unsuccessfull redirect and show error message header( "Location: index.php?page=plugins&result=0" ); exit; } diff --git a/code/web/public_php/ams/func/install_plugin.php b/code/web/public_php/ams/func/install_plugin.php index 052d4f14b..1ad7154d2 100644 --- a/code/web/public_php/ams/func/install_plugin.php +++ b/code/web/public_php/ams/func/install_plugin.php @@ -1,10 +1,32 @@ Check if the file type is .zip. + * --> Extract it to a temp folder. + * --> Check for the .info file. If not exists throw error + * --> Extract the information from the .info file. + * --> Check for the plugin name already exists or not. + * --> if Plugin Name exists it compare the version of .info and version of plugin stored in db. + * --> if same throw error and if different it checks for UpdateInfo field in .info file. + * --> if UpdateInfo not found throw error. + * --> if UpdateInfo found add the update to the ryzom_ams_lib.updates table. + * --> if it's not an update and plugin with same name already exists throw error. + * --> if plugin with same name not present provide option to install plugin + * + * @author Shubham Meena, mentored by Matthew Lagoe + * + */ + + /** - * This function is used in installing plugins - * It performs validation check for the compressed plugin - * then extract in plugin folder to get the info + * This function is used in installing plugins or adding updates + * for previously installed plugins. * - * @author Shubham Meena, mentored by Matthew Lagoe */ function install_plugin() { @@ -165,13 +187,14 @@ function zipExtraction( $target_path, $destination ) * PluginName = Name of the plugin * Version = version of the plugin * Type = type of the plugin + * TemplatePath = path to the template * Description = Description of the plugin ,it's functionality * ----------------------------------------------------------- * * reads only files with name .info * * @param $fileName file to read - * @param $targetPath path to the folder containing .info file + * @param $target_path path to the folder containing .info file * @return array containing above information in array(value => key) */ function readPluginFile( $fileName, $target_path ) @@ -190,8 +213,8 @@ function readPluginFile( $fileName, $target_path ) /** * function to check for updates or * if the same plugin already exists - * also, if the update founds ,check for the update info in the .info file. - * Update is saved in the temp direcotry with pluginName_version.zip + * also, if the update founds ,check for the UpdateInfo in the .info file. + * Update is saved in the temp directory with pluginName_version.zip * * @param $fileName file which is uploaded in .zip extension * @param $findPath where we have to look for the installed plugins @@ -286,8 +309,8 @@ function checkForUpdate( $fileName, $findPath, $tempFile, $tempPath ) * * @param $pluginId id of the plugin for which update is available * @param $updatePath path of the new update - * @return boolean if update for a plugin already exists or - * if update of same version is uploading + * @return boolean True if update already exists else False + * */ function PluginUpdateExists( $pluginId, $updatePath ) { diff --git a/code/web/public_php/ams/func/update_plugin.php b/code/web/public_php/ams/func/update_plugin.php index 1420572b1..cacc5f119 100644 --- a/code/web/public_php/ams/func/update_plugin.php +++ b/code/web/public_php/ams/func/update_plugin.php @@ -1,6 +1,9 @@ executeWithoutParams( "SELECT * FROM plugins INNER JOIN updates ON plugins.Id=updates.PluginId Where plugins.Id=$id" ); @@ -26,6 +29,7 @@ function update_plugin() { // deleting the previous update $db -> delete( "updates", array( 'id' => $row['s.no'] ), "s.no=:id" ); + // if update is installed succesffully redirect to show success message header( "Location: index.php?page=plugins&result=8" ); exit; diff --git a/code/web/public_php/ams/inc/plugins_update.php b/code/web/public_php/ams/inc/plugins_update.php index 89d547860..e08869f98 100644 --- a/code/web/public_php/ams/inc/plugins_update.php +++ b/code/web/public_php/ams/inc/plugins_update.php @@ -1,7 +1,7 @@ Date: Mon, 18 Aug 2014 18:03:48 +0200 Subject: [PATCH 229/234] Array resize. --HG-- branch : gsoc2014-dfighter --- .../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 0b44c8a7a0c7025e35a7e86d8ee840b13d98d054 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 18 Aug 2014 19:49:32 +0200 Subject: [PATCH 230/234] Save changes. --HG-- branch : gsoc2014-dfighter --- .../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() From 683a0adc6081fea5289c64598bbf76942f8c8b7c Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 18 Aug 2014 20:23:27 +0200 Subject: [PATCH 231/234] Crashfix in case pacs_prim are exported into .ig --- code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp b/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp index 7d958d81c..b109c2db2 100644 --- a/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp +++ b/code/nel/tools/3d/zone_dependencies/zone_dependencies.cpp @@ -607,11 +607,15 @@ static void computeIGBBox(const NL3D::CInstanceGroup &ig, CLightingBBox &result, std::string toLoad = it->Name; if (getExt(toLoad).empty()) toLoad += ".shape"; shapePathName = NLMISC::CPath::lookup(toLoad, false, false); - + if (shapePathName.empty()) { nlwarning("Unable to find shape '%s'", it->Name.c_str()); } + else if (toLower (CFile::getExtension (shapePathName)) == "pacs_prim") + { + nlwarning("EXPORT BUG: Can't read %s (not a shape), should not be part of .ig!", shapePathName.c_str()); + } else { CIFile shapeInputFile; From 8fab3ccce1f5682f4baefea81bc573bc73d923f2 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 19 Aug 2014 15:37:31 +0200 Subject: [PATCH 232/234] EOL --- code/studio/src/settings_dialog.cpp | 472 ++++++++++++++-------------- code/studio/src/settings_dialog.h | 124 ++++---- code/studio/src/splash_screen.cpp | 218 ++++++------- code/studio/src/splash_screen.h | 120 +++---- 4 files changed, 467 insertions(+), 467 deletions(-) diff --git a/code/studio/src/settings_dialog.cpp b/code/studio/src/settings_dialog.cpp index 6824b0f56..78773a666 100644 --- a/code/studio/src/settings_dialog.cpp +++ b/code/studio/src/settings_dialog.cpp @@ -1,236 +1,236 @@ -// 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 "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() ) ); -} - +// 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 "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 index c6e7cc93a..173ba37d4 100644 --- a/code/studio/src/settings_dialog.h +++ b/code/studio/src/settings_dialog.h @@ -1,62 +1,62 @@ -// 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 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 +// 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 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/splash_screen.cpp b/code/studio/src/splash_screen.cpp index 252472e8d..36f7b3bc0 100644 --- a/code/studio/src/splash_screen.cpp +++ b/code/studio/src/splash_screen.cpp @@ -1,109 +1,109 @@ -// 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 -#include -#include - -SplashScreen::SplashScreen() : -QSplashScreen() -{ - progress = 0; - textX = 5; - textY = 20; - pbLeft = 2; - 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() - 4; - - if( this->pixmap().height() > 0 ) - pbTop = this->pixmap().height() - pbHeight - 2; - - textY = pbTop - pbHeight / 2; -} - -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::advanceProgress( 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( pbLeft, 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 ); - } -} - - +// 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 +#include +#include + +SplashScreen::SplashScreen() : +QSplashScreen() +{ + progress = 0; + textX = 5; + textY = 20; + pbLeft = 2; + 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() - 4; + + if( this->pixmap().height() > 0 ) + pbTop = this->pixmap().height() - pbHeight - 2; + + textY = pbTop - pbHeight / 2; +} + +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::advanceProgress( 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( pbLeft, 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 index ec6cd3da8..c4ba0f648 100644 --- a/code/studio/src/splash_screen.h +++ b/code/studio/src/splash_screen.h @@ -1,60 +1,60 @@ -// 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 - - -#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 advanceProgress( 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 - +// 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 + + +#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 advanceProgress( 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 02e8f6e95629ca88820a01e4f62f336b61001214 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 19 Aug 2014 15:38:16 +0200 Subject: [PATCH 233/234] EOL --- .../src/plugins/tile_editor/CMakeLists.txt | 100 +- .../plugins/tile_editor/land_edit_dialog.cpp | 210 +-- .../plugins/tile_editor/land_edit_dialog.h | 102 +- .../tile_editor/studio_plugin_tile_editor.xml | 18 +- .../src/plugins/tile_editor/tile_bank.cpp | 1284 ++++++++--------- .../src/plugins/tile_editor/tile_bank.h | 204 +-- .../src/plugins/tile_editor/tile_constants.h | 86 +- .../src/plugins/tile_editor/tile_images.h | 80 +- .../tile_editor/tile_item_delegate.cpp | 242 ++-- .../plugins/tile_editor/tilebank_loader.cpp | 84 +- .../src/plugins/tile_editor/tilebank_loader.h | 70 +- .../plugins/tile_editor/tilebank_saver.cpp | 96 +- .../src/plugins/tile_editor/tilebank_saver.h | 78 +- .../translation_manager/uxt_editor.cpp | 944 ++++++------ 14 files changed, 1799 insertions(+), 1799 deletions(-) diff --git a/code/studio/src/plugins/tile_editor/CMakeLists.txt b/code/studio/src/plugins/tile_editor/CMakeLists.txt index 396522235..78cc5ef49 100644 --- a/code/studio/src/plugins/tile_editor/CMakeLists.txt +++ b/code/studio/src/plugins/tile_editor/CMakeLists.txt @@ -1,50 +1,50 @@ -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 - land_edit_dialog.h) - -SET(OVQT_TILE_EDITOR_PLUGIN_UIS - tile_editor_main_window.ui - land_edit_dialog.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(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(studio_plugin_tile_editor studio_plugin_core nelmisc ${QT_LIBRARIES}) - -IF(WITH_STLPORT) - TARGET_LINK_LIBRARIES(studio_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) -ENDIF(WITH_STLPORT) - -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 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) +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 + land_edit_dialog.h) + +SET(OVQT_TILE_EDITOR_PLUGIN_UIS + tile_editor_main_window.ui + land_edit_dialog.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(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(studio_plugin_tile_editor studio_plugin_core nelmisc ${QT_LIBRARIES}) + +IF(WITH_STLPORT) + TARGET_LINK_LIBRARIES(studio_plugin_tile_editor ${CMAKE_THREAD_LIBS_INIT}) +ENDIF(WITH_STLPORT) + +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 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/land_edit_dialog.cpp b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp index 40fbf3024..025e55730 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.cpp @@ -1,105 +1,105 @@ -// 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 ) : -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::setSelectedTileSets( QStringList &l ) -{ - tilesetLV->clear(); - - QStringListIterator itr( l ); - while( itr.hasNext() ) - { - tilesetLV->addItem( itr.next() ); - } -} - -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; -} - +// 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 ) : +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::setSelectedTileSets( QStringList &l ) +{ + tilesetLV->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + tilesetLV->addItem( itr.next() ); + } +} + +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 index ac3762b46..3873c6df5 100644 --- a/code/studio/src/plugins/tile_editor/land_edit_dialog.h +++ b/code/studio/src/plugins/tile_editor/land_edit_dialog.h @@ -1,51 +1,51 @@ -// 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 - - -#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 setSelectedTileSets( QStringList &l ); - - void setTileSets( const QStringList &l ); - -private: - void setupConnections(); - - -private Q_SLOTS: - void onOkClicked(); - void onCancelClicked(); - void onAddClicked(); - void onRemoveClicked(); - -}; - - -#endif - +// 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 + + +#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 setSelectedTileSets( QStringList &l ); + + 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/studio_plugin_tile_editor.xml b/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml index d69201f9b..0e5727896 100644 --- a/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml +++ b/code/studio/src/plugins/tile_editor/studio_plugin_tile_editor.xml @@ -1,10 +1,10 @@ - - studio_plugin_tile_editor - TileEditor - 1.0 - Ryzom Core - Tile bank editing plugin. - - - + + studio_plugin_tile_editor + TileEditor + 1.0 + Ryzom Core + Tile bank editing plugin. + + + \ No newline at end of file diff --git a/code/studio/src/plugins/tile_editor/tile_bank.cpp b/code/studio/src/plugins/tile_editor/tile_bank.cpp index 8e4d8f511..8e3578eeb 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.cpp +++ b/code/studio/src/plugins/tile_editor/tile_bank.cpp @@ -1,642 +1,642 @@ -// 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" - -#include - -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 ) ); - } - - -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -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; -}; - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -TileBank::TileBank() -{ - m_pvt = new TileBankPvt(); - resetError(); - m_rotation = 0; -} - -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::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::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() ); -} - -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 ); - land->clear(); - - QStringListIterator itr( l ); - while( itr.hasNext() ) - { - land->addTileSet( itr.next().toUtf8().constData() ); - } -} - -void TileBank::getLandSets( int idx, QStringList &l ) -{ - 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->removeTile256( 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; - } - - if( !m_pvt->checkSize( type, channel, pm.width(), pm.height() ) ) - { - m_hasError = true; - m_lastError = "Invalid image size."; - return false; - } - - 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 ); - - // 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, m_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; - } - -} - -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 ) -{ - 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(); -} - -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(); -} - - -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; -} - -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(); -} - -void TileBank::setRotation( int rotation ) -{ - m_rotation = rotation; -} - -void TileBank::serial( NLMISC::IStream &f ) -{ - m_pvt->m_bank.serial( f ); -} - - +// 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" + +#include + +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 ) ); + } + + +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +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; +}; + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TileBank::TileBank() +{ + m_pvt = new TileBankPvt(); + resetError(); + m_rotation = 0; +} + +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::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::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() ); +} + +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 ); + land->clear(); + + QStringListIterator itr( l ); + while( itr.hasNext() ) + { + land->addTileSet( itr.next().toUtf8().constData() ); + } +} + +void TileBank::getLandSets( int idx, QStringList &l ) +{ + 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->removeTile256( 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; + } + + if( !m_pvt->checkSize( type, channel, pm.width(), pm.height() ) ) + { + m_hasError = true; + m_lastError = "Invalid image size."; + return false; + } + + 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 ); + + // 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, m_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; + } + +} + +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 ) +{ + 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(); +} + +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(); +} + + +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; +} + +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(); +} + +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 a4620ad41..9d765b8ae 100644 --- a/code/studio/src/plugins/tile_editor/tile_bank.h +++ b/code/studio/src/plugins/tile_editor/tile_bank.h @@ -1,102 +1,102 @@ -// 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 - -#include -#include -#include -#include - -#include "tile_constants.h" -#include "tile_images.h" - -namespace NLMISC -{ - class IStream; -} - -class TileBankPvt; - -class TileBank -{ -public: - TileBank(); - ~TileBank(); - - 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 ); - - 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 ); - - - 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; - - void setOriented( int tileSet, bool b ); - bool getOriented( int tileSet ) const; - - void setSurfaceData( int tileSet, unsigned long data ); - unsigned long getSurfaceData( int tileSet ) const; - - void setTexturePath( const QString &path ); - QString getTexturePath() const; - - void setRotation( int rotation ); - - void serial( NLMISC::IStream &f ); - - 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; - int m_rotation; -}; - -#endif - +// 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 + +#include +#include +#include +#include + +#include "tile_constants.h" +#include "tile_images.h" + +namespace NLMISC +{ + class IStream; +} + +class TileBankPvt; + +class TileBank +{ +public: + TileBank(); + ~TileBank(); + + 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 ); + + 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 ); + + + 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; + + void setOriented( int tileSet, bool b ); + bool getOriented( int tileSet ) const; + + void setSurfaceData( int tileSet, unsigned long data ); + unsigned long getSurfaceData( int tileSet ) const; + + void setTexturePath( const QString &path ); + QString getTexturePath() const; + + void setRotation( int rotation ); + + void serial( NLMISC::IStream &f ); + + 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; + int m_rotation; +}; + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tile_constants.h b/code/studio/src/plugins/tile_editor/tile_constants.h index bf09f21a5..56748cb58 100644 --- a/code/studio/src/plugins/tile_editor/tile_constants.h +++ b/code/studio/src/plugins/tile_editor/tile_constants.h @@ -1,43 +1,43 @@ -// 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 - }; -} - - -#endif +// 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 + }; +} + + +#endif diff --git a/code/studio/src/plugins/tile_editor/tile_images.h b/code/studio/src/plugins/tile_editor/tile_images.h index e17267001..280e0a126 100644 --- a/code/studio/src/plugins/tile_editor/tile_images.h +++ b/code/studio/src/plugins/tile_editor/tile_images.h @@ -1,40 +1,40 @@ -// 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 - -#include - -struct TileImages -{ - QString diffuse; - QString additive; - QString alpha; - - void clear() - { - diffuse.clear(); - additive.clear(); - alpha.clear(); - } -}; - - - -#endif - +// 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 + +#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_delegate.cpp b/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp index 43751d612..6f9479354 100644 --- a/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp +++ b/code/studio/src/plugins/tile_editor/tile_item_delegate.cpp @@ -1,122 +1,122 @@ -// 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; - m_imageHint = 128; -} - -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(); - - //font.setBold(true); - //SubFont.setWeight(SubFont.weight()-2); - QFontMetrics fm(font); - - QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); - 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 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; - - painter->drawPixmap(rect.adjusted(iconPosModX, iconPosModY, iconPosModX, iconPosModY).topLeft(), tile); - - - - //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->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(); - QFont font = QApplication::font(); - QFontMetrics fm(font); - - return(QSize(tileSize.width()+(2*PIXMAP_MARGIN), tileSize.height()+fm.height()+(2*PIXMAP_MARGIN))); -} - -TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() -{ - return m_zoomFactor; -} - -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; - } +// 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; + m_imageHint = 128; +} + +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(); + + //font.setBold(true); + //SubFont.setWeight(SubFont.weight()-2); + QFontMetrics fm(font); + + QPixmap tile = qvariant_cast(index.data(TileModel::TilePixmapRole)); + 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 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; + + painter->drawPixmap(rect.adjusted(iconPosModX, iconPosModY, iconPosModX, iconPosModY).topLeft(), tile); + + + + //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->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(); + QFont font = QApplication::font(); + QFontMetrics fm(font); + + return(QSize(tileSize.width()+(2*PIXMAP_MARGIN), tileSize.height()+fm.height()+(2*PIXMAP_MARGIN))); +} + +TileItemDelegate::TZoomFactor TileItemDelegate::getZoomFactor() +{ + return m_zoomFactor; +} + +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/studio/src/plugins/tile_editor/tilebank_loader.cpp b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp index 1aaa055f0..ceae137cc 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.cpp @@ -1,42 +1,42 @@ -// 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" -#include "nel/misc/file.h" - -TileBankLoader::TileBankLoader() -{ -} - -TileBankLoader::~TileBankLoader() -{ -} - -bool TileBankLoader::load( const char *filename, TileModel *model ) -{ - NLMISC::CIFile file; - if( !file.open( filename, false ) ) - return false; - - model->serial( file ); - - file.close(); - - return true; -} +// 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" +#include "nel/misc/file.h" + +TileBankLoader::TileBankLoader() +{ +} + +TileBankLoader::~TileBankLoader() +{ +} + +bool TileBankLoader::load( const char *filename, TileModel *model ) +{ + NLMISC::CIFile file; + if( !file.open( filename, false ) ) + return false; + + model->serial( file ); + + file.close(); + + return true; +} diff --git a/code/studio/src/plugins/tile_editor/tilebank_loader.h b/code/studio/src/plugins/tile_editor/tilebank_loader.h index 643cab67f..6f41234ba 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_loader.h +++ b/code/studio/src/plugins/tile_editor/tilebank_loader.h @@ -1,35 +1,35 @@ -// 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 - -class TileModel; - -class TileBankLoader -{ -public: - TileBankLoader(); - ~TileBankLoader(); - - bool load( const char *filename, TileModel *model ); - -private: -}; - - -#endif - +// 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 + +class TileModel; + +class TileBankLoader +{ +public: + TileBankLoader(); + ~TileBankLoader(); + + bool load( const char *filename, TileModel *model ); + +private: +}; + + +#endif + diff --git a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp index 3f087c979..85c96ee94 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.cpp +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.cpp @@ -1,48 +1,48 @@ -// 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 "tile_item.h" - -#include "nel/3d/tile_bank.h" -#include "nel/misc/file.h" - -TileBankSaver::TileBankSaver() -{ -} - -TileBankSaver::~TileBankSaver() -{ -} - -bool TileBankSaver::save( const char *fileName, TileModel* model ) -{ - // Save to file - NLMISC::COFile f; - bool b = f.open( fileName, false, false, false ); - if( !b ) - return false; - - model->serial( f ); - - f.flush(); - f.close(); - - return true; -} - +// 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 "tile_item.h" + +#include "nel/3d/tile_bank.h" +#include "nel/misc/file.h" + +TileBankSaver::TileBankSaver() +{ +} + +TileBankSaver::~TileBankSaver() +{ +} + +bool TileBankSaver::save( const char *fileName, TileModel* model ) +{ + // Save to file + NLMISC::COFile f; + bool b = f.open( fileName, false, false, false ); + if( !b ) + return false; + + model->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 0f8983157..ba9c3c7fd 100644 --- a/code/studio/src/plugins/tile_editor/tilebank_saver.h +++ b/code/studio/src/plugins/tile_editor/tilebank_saver.h @@ -1,39 +1,39 @@ -// 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, TileModel* model ); - -private: - -}; - -#endif - +// 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, TileModel* model ); + +private: + +}; + +#endif + diff --git a/code/studio/src/plugins/translation_manager/uxt_editor.cpp b/code/studio/src/plugins/translation_manager/uxt_editor.cpp index 99b0b200c..06e6f98b4 100644 --- a/code/studio/src/plugins/translation_manager/uxt_editor.cpp +++ b/code/studio/src/plugins/translation_manager/uxt_editor.cpp @@ -1,472 +1,472 @@ -// 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" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#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 -{ - -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: - - UXTEditorPvt() - { - t = new QTableWidget(); - loadedFromWK = false; - } - - QTableWidget *t; - std::vector< STRING_MANAGER::TStringInfo > infos; - bool loadedFromWK; -}; - - -UXTEditor::UXTEditor( QMdiArea *parent ) : -CEditor( parent ) -{ - editor_type = Constants::ED_UXT; - setAttribute( Qt::WA_DeleteOnClose ); - - d_ptr = new UXTEditorPvt(); - - blockTableSignals( false ); -} - -UXTEditor::~UXTEditor() -{ - delete d_ptr; - d_ptr = NULL; -} - -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, false ); - - if( d_ptr->infos.size() == 0 ) - { - // 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; - } - - int l = filename.lastIndexOf( "/" ); - if( l == -1 ) - return; - - QString fn = filename.left( l ); - fn += "/wk.uxt"; - - // 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; - } - - blockTableSignals( true ); - - d_ptr->t->clear(); - d_ptr->t->setColumnCount( 2 ); - d_ptr->t->setRowCount( infos.size() ); - - setHeaderText( "Id", lang.toUpper() + " Text" ); - - 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 ); - - if( ( info.HashValue != 0 ) && !d_ptr->loadedFromWK ) - { - markItemTranslated( name ); - markItemTranslated( text1 ); - } - else - { - markItemUntranslated( name ); - markItemUntranslated( text1 ); - } - - ++itr; - i++; - } - - d_ptr->t->resizeColumnsToContents(); - - blockTableSignals( false ); - - setWidget( d_ptr->t ); - - current_file = filename; - setWindowTitle( filename + "[*]" ); - setWindowFilePath( filename ); -} - -void UXTEditor::save() -{ - saveAs( current_file ); -} - -void UXTEditor::saveAs( QString filename ) -{ - QFile f( filename ); - if( !f.open( QIODevice::WriteOnly ) ) - return; - - QTextStream out( &f ); - - int idx = 0; - 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( hash ).c_str() ).toUpper(); - hashLine += "\r\n"; - - QString idxLine = "// INDEX "; - idxLine += QString::number( idx ); - idxLine += "\r\n"; - - - QString trLine = ""; - trLine += itr->Identifier.c_str(); - trLine += "\t"; - trLine += "["; - - if( itr->Text2.empty() ) - trLine += itr->Text.toUtf8().c_str(); - else - trLine += itr->Text2.toUtf8().c_str(); - - trLine += "]"; - trLine += "\r\n"; - - QString newLine = "\r\n"; - - out << hashLine; - out << idxLine; - out << trLine; - out << newLine; - - ++itr; - idx++; - } - - f.close(); - - setWindowModified( false ); -} - -void UXTEditor::activateWindow() -{ - showMaximized(); -} - - -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 ); -} - - -void UXTEditor::deleteRow() -{ - int r = d_ptr->t->currentRow(); - 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 ); - - d_ptr->t->removeRow( r ); - - setWindowModified( true ); -} - -void UXTEditor::closeEvent( QCloseEvent *e ) -{ - if( isWindowModified() ) - { - 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::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 ); - 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() ); -} - -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.Text2 = item->text().toUtf8().constData(); - - setWindowModified( true ); - - markRowTranslated( row ); -} - -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 ); - - markRowTranslated( r ); -} - -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 ); - - 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 ); - 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 ); -} - -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 ) ) ); -} - -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 ); -} - -} +// 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" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 +{ + +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: + + UXTEditorPvt() + { + t = new QTableWidget(); + loadedFromWK = false; + } + + QTableWidget *t; + std::vector< STRING_MANAGER::TStringInfo > infos; + bool loadedFromWK; +}; + + +UXTEditor::UXTEditor( QMdiArea *parent ) : +CEditor( parent ) +{ + editor_type = Constants::ED_UXT; + setAttribute( Qt::WA_DeleteOnClose ); + + d_ptr = new UXTEditorPvt(); + + blockTableSignals( false ); +} + +UXTEditor::~UXTEditor() +{ + delete d_ptr; + d_ptr = NULL; +} + +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, false ); + + if( d_ptr->infos.size() == 0 ) + { + // 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; + } + + int l = filename.lastIndexOf( "/" ); + if( l == -1 ) + return; + + QString fn = filename.left( l ); + fn += "/wk.uxt"; + + // 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; + } + + blockTableSignals( true ); + + d_ptr->t->clear(); + d_ptr->t->setColumnCount( 2 ); + d_ptr->t->setRowCount( infos.size() ); + + setHeaderText( "Id", lang.toUpper() + " Text" ); + + 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 ); + + if( ( info.HashValue != 0 ) && !d_ptr->loadedFromWK ) + { + markItemTranslated( name ); + markItemTranslated( text1 ); + } + else + { + markItemUntranslated( name ); + markItemUntranslated( text1 ); + } + + ++itr; + i++; + } + + d_ptr->t->resizeColumnsToContents(); + + blockTableSignals( false ); + + setWidget( d_ptr->t ); + + current_file = filename; + setWindowTitle( filename + "[*]" ); + setWindowFilePath( filename ); +} + +void UXTEditor::save() +{ + saveAs( current_file ); +} + +void UXTEditor::saveAs( QString filename ) +{ + QFile f( filename ); + if( !f.open( QIODevice::WriteOnly ) ) + return; + + QTextStream out( &f ); + + int idx = 0; + 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( hash ).c_str() ).toUpper(); + hashLine += "\r\n"; + + QString idxLine = "// INDEX "; + idxLine += QString::number( idx ); + idxLine += "\r\n"; + + + QString trLine = ""; + trLine += itr->Identifier.c_str(); + trLine += "\t"; + trLine += "["; + + if( itr->Text2.empty() ) + trLine += itr->Text.toUtf8().c_str(); + else + trLine += itr->Text2.toUtf8().c_str(); + + trLine += "]"; + trLine += "\r\n"; + + QString newLine = "\r\n"; + + out << hashLine; + out << idxLine; + out << trLine; + out << newLine; + + ++itr; + idx++; + } + + f.close(); + + setWindowModified( false ); +} + +void UXTEditor::activateWindow() +{ + showMaximized(); +} + + +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 ); +} + + +void UXTEditor::deleteRow() +{ + int r = d_ptr->t->currentRow(); + 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 ); + + d_ptr->t->removeRow( r ); + + setWindowModified( true ); +} + +void UXTEditor::closeEvent( QCloseEvent *e ) +{ + if( isWindowModified() ) + { + 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::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 ); + 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() ); +} + +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.Text2 = item->text().toUtf8().constData(); + + setWindowModified( true ); + + markRowTranslated( row ); +} + +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 ); + + markRowTranslated( r ); +} + +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 ); + + 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 ); + 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 ); +} + +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 ) ) ); +} + +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 ); +} + +} From 46aa5cef294bad0df41535330e1e288ab50a8ad1 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 19 Aug 2014 15:42:42 +0200 Subject: [PATCH 234/234] EOL --- .../src/plugins/georges_editor/actions.cpp | 100 ++--- .../plugins/georges_editor/browser_ctrl.cpp | 130 +++--- .../georges_editor/browser_ctrl_pvt.cpp | 394 +++++++++--------- .../georges_editor/georgesform_model.h | 6 +- .../tile_editor/tile_editor_plugin.cpp | 154 +++---- 5 files changed, 392 insertions(+), 392 deletions(-) diff --git a/code/studio/src/plugins/georges_editor/actions.cpp b/code/studio/src/plugins/georges_editor/actions.cpp index c96bca95c..08196f79b 100644 --- a/code/studio/src/plugins/georges_editor/actions.cpp +++ b/code/studio/src/plugins/georges_editor/actions.cpp @@ -31,7 +31,7 @@ #include #include -namespace GeorgesQt +namespace GeorgesQt { CUndoFormArrayRenameCommand::CUndoFormArrayRenameCommand(CGeorgesFormModel *model, CFormItem *item, const QVariant &value, QUndoCommand *parent) @@ -41,63 +41,63 @@ namespace GeorgesQt } void CUndoFormArrayRenameCommand::redo() - { + { update(true); } void CUndoFormArrayRenameCommand::undo() - { + { update(false); } void CUndoFormArrayRenameCommand::update(bool 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->Elements); - - 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); - - NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); - - // 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_item->structId()].Name.empty()) - { - m_oldValue.append("#"); - m_oldValue.append(QString("%1").arg(m_item->structId())); - } - else - { - m_oldValue = QString(array->Elements[m_item->structId()].Name.c_str()); - } - } - - QString value; - if(redo) - value = m_newValue; - else - value = m_oldValue; - - - 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)); + { + // 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->Elements); + + 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); + + NLGEORGES::CFormElmArray* array = static_cast (node->getParent ()); + + // 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_item->structId()].Name.empty()) + { + m_oldValue.append("#"); + m_oldValue.append(QString("%1").arg(m_item->structId())); + } + else + { + m_oldValue = QString(array->Elements[m_item->structId()].Name.c_str()); + } + } + + QString value; + if(redo) + value = m_newValue; + else + value = m_oldValue; + + + 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)); } } } \ No newline at end of file diff --git a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp index aa431b45c..5c4d2a499 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl.cpp @@ -1,31 +1,31 @@ -#include "browser_ctrl.h" -#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" -#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" -#include - -#include "nel/georges/form.h" - -#include "formitem.h" - -#include "browser_ctrl_pvt.h" - -BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : -QObject( browser ) -{ - m_pvt = new BrowserCtrlPvt(); - 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() -{ - delete m_pvt; - m_pvt = NULL; -} - -void BrowserCtrl::clicked( const QModelIndex &idx ) +#include "browser_ctrl.h" +#include "3rdparty/qtpropertybrowser/qttreepropertybrowser.h" +#include "3rdparty/qtpropertybrowser/qtvariantproperty.h" +#include + +#include "nel/georges/form.h" + +#include "formitem.h" + +#include "browser_ctrl_pvt.h" + +BrowserCtrl::BrowserCtrl( QtTreePropertyBrowser *browser ) : +QObject( browser ) +{ + m_pvt = new BrowserCtrlPvt(); + 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() +{ + delete m_pvt; + m_pvt = NULL; +} + +void BrowserCtrl::clicked( const QModelIndex &idx ) { disableMgrConnections(); m_pvt->clear(); @@ -42,40 +42,40 @@ void BrowserCtrl::clicked( const QModelIndex &idx ) if( !b || ( node == NULL ) ) return; - m_pvt->setupNode( node ); - - enableMgrConnections(); - -} - -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::onModified() -{ - Q_EMIT modified(); -} - -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 & ) ) ); -} - + m_pvt->setupNode( node ); + + enableMgrConnections(); + +} + +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::onModified() +{ + Q_EMIT modified(); +} + +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_pvt.cpp b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp index 0e22765da..d5026ef71 100644 --- a/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp +++ b/code/studio/src/plugins/georges_editor/browser_ctrl_pvt.cpp @@ -1,205 +1,205 @@ -#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 ) -{ +#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 ); - + 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 ); - - Q_EMIT modified(); -} - -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 ); - Q_EMIT modified(); -} - -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 ); -} - - + 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 ); + + Q_EMIT modified(); +} + +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 ); + Q_EMIT modified(); +} + +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/georgesform_model.h b/code/studio/src/plugins/georges_editor/georgesform_model.h index 4ca91398b..d133b5ec6 100644 --- a/code/studio/src/plugins/georges_editor/georgesform_model.h +++ b/code/studio/src/plugins/georges_editor/georgesform_model.h @@ -70,9 +70,9 @@ 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); + void emitDataChanged(const QModelIndex &index) + { + Q_EMIT dataChanged(index, index); } void arrayResized( const QString &name, int size ); 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 33a617cc1..b10eb6074 100644 --- a/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp +++ b/code/studio/src/plugins/tile_editor/tile_editor_plugin.cpp @@ -1,78 +1,78 @@ -// 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(); - +// 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(); + delete m_LibContext; - m_LibContext = NULL; -} - -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) + m_LibContext = NULL; +} + +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)