From a2ad5e1364dc5f32a9cec145b07b1b608b4da190 Mon Sep 17 00:00:00 2001 From: mkr Date: Thu, 12 Jan 2012 16:36:50 +0000 Subject: [PATCH] Fix for PAL21179: 1) draw outlines (borders) of the shapes, 2) material properties. --- configure.ac | 1 + doc/salome/gui/GEOM/images/material_OCC.png | Bin 0 -> 21395 bytes doc/salome/gui/GEOM/images/material_VTK.png | Bin 0 -> 25134 bytes doc/salome/gui/GEOM/images/material_back.png | Bin 0 -> 37898 bytes doc/salome/gui/GEOM/images/material_front.png | Bin 0 -> 37505 bytes doc/salome/gui/GEOM/input/material.doc | 56 + .../gui/GEOM/input/viewing_geom_obj.doc | 2 + resources/SalomeApp.xml.in | 3 + src/DisplayGUI/DisplayGUI.cxx | 112 +- src/GEOMGUI/GEOMGUI_Selection.cxx | 8 + src/GEOMGUI/GEOM_Displayer.cxx | 191 ++- src/GEOMGUI/GEOM_msg_en.ts | 99 ++ src/GEOMGUI/GEOM_msg_fr.ts | 99 ++ src/GEOMGUI/GeometryGUI.cxx | 329 +++-- src/GEOMGUI/GeometryGUI.h | 18 - src/GEOMGUI/GeometryGUI_Operations.h | 264 ++-- src/GEOMGUI/Makefile.am | 2 + src/GEOMToolsGUI/GEOMToolsGUI.cxx | 3 + src/GEOMToolsGUI/GEOMToolsGUI.h | 1 + src/GEOMToolsGUI/GEOMToolsGUI_1.cxx | 19 +- .../GEOMToolsGUI_DeflectionDlg.cxx | 1 + src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx | 1 + .../GEOMToolsGUI_MaterialPropertiesDlg.cxx | 1254 +++++++++++++++++ .../GEOMToolsGUI_MaterialPropertiesDlg.h | 163 +++ .../GEOMToolsGUI_TransparencyDlg.cxx | 1 + src/GEOMToolsGUI/Makefile.am | 11 +- src/Makefile.am | 2 +- src/Material/Makefile.am | 51 + src/Material/Material.h | 36 + src/Material/Material_Model.cxx | 682 +++++++++ src/Material/Material_Model.h | 108 ++ src/Material/Material_ResourceMgr.cxx | 407 ++++++ src/Material/Material_ResourceMgr.h | 49 + src/Material/resources/SalomeMaterial.xml | 187 +++ src/OBJECT/GEOM_AISShape.cxx | 164 ++- src/OBJECT/GEOM_AISShape.hxx | 30 + src/OBJECT/GEOM_Actor.cxx | 239 +++- src/OBJECT/GEOM_Actor.h | 28 +- src/OBJECT/GEOM_Constants.h | 49 + src/OBJECT/GEOM_DeviceActor.cxx | 14 + src/OBJECT/GEOM_DeviceActor.h | 3 + src/OBJECT/GEOM_PainterPolyDataMapper.cxx | 24 + src/OBJECT/GEOM_PainterPolyDataMapper.h | 44 + src/OBJECT/GEOM_SmartPtr.h | 6 +- src/OBJECT/Makefile.am | 2 + 45 files changed, 4387 insertions(+), 376 deletions(-) create mode 100644 doc/salome/gui/GEOM/images/material_OCC.png create mode 100644 doc/salome/gui/GEOM/images/material_VTK.png create mode 100644 doc/salome/gui/GEOM/images/material_back.png create mode 100644 doc/salome/gui/GEOM/images/material_front.png create mode 100644 doc/salome/gui/GEOM/input/material.doc create mode 100644 src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.cxx create mode 100644 src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.h create mode 100644 src/Material/Makefile.am create mode 100644 src/Material/Material.h create mode 100644 src/Material/Material_Model.cxx create mode 100644 src/Material/Material_Model.h create mode 100644 src/Material/Material_ResourceMgr.cxx create mode 100644 src/Material/Material_ResourceMgr.h create mode 100644 src/Material/resources/SalomeMaterial.xml create mode 100644 src/OBJECT/GEOM_Constants.h create mode 100644 src/OBJECT/GEOM_PainterPolyDataMapper.cxx create mode 100644 src/OBJECT/GEOM_PainterPolyDataMapper.h diff --git a/configure.ac b/configure.ac index 729d02fa1..8e0abd9f0 100644 --- a/configure.ac +++ b/configure.ac @@ -448,6 +448,7 @@ AC_OUTPUT([ \ src/GEOMBase/Makefile \ src/GEOMClient/Makefile \ src/GEOMFiltersSelection/Makefile \ + src/Material/Makefile \ src/GEOMGUI/Makefile \ src/GEOMImpl/Makefile \ src/GEOMToolsGUI/Makefile \ diff --git a/doc/salome/gui/GEOM/images/material_OCC.png b/doc/salome/gui/GEOM/images/material_OCC.png new file mode 100644 index 0000000000000000000000000000000000000000..6f23268a5c611e410a7d4916916724a416014120 GIT binary patch literal 21395 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 WH;b_A`5Sxy($UreKP}g=3Hu*Vt~UYz literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/material_VTK.png b/doc/salome/gui/GEOM/images/material_VTK.png new file mode 100644 index 0000000000000000000000000000000000000000..b409c73d144b50169a2996577f2f1823cc31be33 GIT binary patch literal 25134 zcmaHSWmKC@)NODN?oM%cf>WfpYg?drakt_Wm*DR1mf{qb1oyTSD{iGY6z8Vz_uU`& z&z&q5ES@|wXU@pkXV0D(Ee%B+ObSc@0Dz;cB(DPiAo#<7q|g!J|Jfd62?GG=0Lt>O z^?dV=dp>n@zJ1Ho)!XxmeNTZHQt_{bwoKgJ$C7nz$v~pRug<^YuiP;}caDuYe&-PrlOGTt~ottK(Du;N!y; z{NztFS^IhZH#Jq=$!-h+uP&|Xn!n%o_8?XLe@n;w>xV!9@dFCm>30`d1%(lQy3AkY zB_$;mB3g$P@L$SRp1KgntS70E*nfqCR)0h97^wy-`ndzoP@aqUe@hhY>95m&ZGmJv zT<=WS*>3C%w8$&r z16N{Es14SKH)5X$cl&NJKl~Z|>2oPXZS0yNym!RJ6L4Ss8_ZawQ2RP|Z}R`@=EO~R zWB*rxm^F}^CH4QBfJo>;;YPrRRi+ABWAWqvZE4G__+O>3|ErXk7!CN(Z-_Pj-Y}wp zyYFA2lGn4;hv@!qZG!(M8}S3ur&F$=2%7uHC&`po5%BH`qbQ;4|&Qrj)=XNNYdt^kS4^qFd? zyn4GiZ#=eKb z$ey>P`s(F&cN z#UBQwLCt=BE8jIF0Jx6lhonHNLp^CPUU={NH??M`a0@>bc>r7w32*14Ht$J(towv0 zRnAZS=OZTz6Trq6%Pd|3xrFQIF==YL`JXg3kYxuwsHhQ$6A`UH63`#<&~#xdagUnU z<~vLDH^}ovxe_xkEFNwEdQ`MCz>ybV+!3x?C?f|F8fnF$@phEP#Z7kxO8n~*VLqV$ z9{V@#$PR+td#4jceT~lytWn@~AXtfa^R+z_=^=MsQiz zmMh_H9a$c4$MV*uDx1k4l(of2-^BlEoDb&q`5LPUHftIdGg3AX3;$rm{m$Vi=4!Ga z)h7Qa?dFRD1fUw7L30gg{b9@ZD0RQ0#)Ps823y9~kFo}ySa|)F#lC4$bL&BWicr~i zotyQGCthDJffC2;)HE!Y&E|{B={yY3e+VDkFe|LY@IZBBM~ec-EQ0!l0=az>$e1{0|dI;{P%e%VvI zCYF#d>yMf0z`NETDF?GfhG7enO>d-)z@**6@`7GIXPQ37KKFBfeLvFnT6_5zf5HG- zy~ND82YSXj64Gc#*j~s>+}gsf4<&5rcZ&mpoHmhZUxsmbf}WNSJe&*S3h&1EySEN` zszs+wLvEm&pY)(_*&7%`k=RP|elj^4%d{u7DR@w&>Sj%EAmfCEvTbIC66QJ2BFqGB z9ew*TtuK}-IcQBVg)eB}|E{n$zFESU+;f{62mk5n$J&NTI*(yF>qkFC@6U%qS?h5) zQP4pzTXYz@03u<-mxFhYLs2dr&${huVy#lGKa|eZr`+IiYlJPPvMl&AT|`AKA#f%Z zK)F9xA10nf;*FAOX=`JPofm2;2>1SRRLHx4W#r($i6RoW_fG88@NEulmQ&7OPAuIm zBOHmzmBe+N*+l(ITI``|h9*6-`^RBL38fAFqErZXR_) z(4}gICLWq?=1wscHESe@4Kw?URDrDMidq?xy-`a0b#u7VapAqbWvj;{omq%~#B|XIud{WY zBuv6a6!iK+SSHr`e)C++=C@gBet#P;7X=|HqHflnh3o-3^=8??(F;q zLsbETpo?t|xxH0vfUg-5NVQq7D!#cAq;*}b?f8Df%8&^UK@~mm*UjQLMh}U#C6Xz| zaM<^LObX=n^H3n6##_)p7*xd&O>v|9&$P()q2~H&=@N=<*ITKhrSqOaVl@#Z<1mZ! z72PyTmL|d_wqv62{S<EDFX|Oi$GgvOzr5JErapl;(tY z_Lw^%wtuccMQEE5s3My1k?OQQht2W5FNdZ`kX`Ad9hqCE!39 z05=$4G0Iu+OEyI~%o+6u09qocvyACptzr;O&)%kgmBpARJpN&I7@YQ7(JL#IZ$EPQsoGRlCEXC5GQz$ zpr#TEEmd?csdOt#6BWopT@0ZRRNli=V}D1_kstHLP#4pXu=fR-GWS)!echY$4!+RK zj`P63a9Hh)pa^!B5bQfZ>@1oA@xI>kbtxB`);es7^$ZA?V3H^ri9j;w5|f9HYwrH- z80Ak~k?wj8cVE6)7WpqPn`-$Ea(otFc>p^dzGH>*MM-) z%ZbZ`+8J)26dY;&6xVVY#AH)~2_ym&dm#LFkS28+GvcnK69xvwVY#W-1*Y z;=mDX7whD;N0r_Qe6N1xSP_Fn{?5MsKr!p^` zuiM+Zt_7tvM0$E8fxiuuQ7(!C+M`rNFy1brhhrX@|6s`<7OIG_GZ!|)NEocACkwq* zQ#4EZh-DR8C5kk%(S=HyadyK1%g4 zF5EZW8NG5--=L;R(m>iaW8}=BLzbf_w)oH=3jx*|W>fI?qyOOfMMkv)sNG91i+$>bs9n6yRhWDEEjxo>q zEZMMdJNM>e##fGunjQb}aZv7{IT0vMboWd67iDai{uOl7Ny ztq2&TJKq4|i3GQ>OThD!zUKP-Ao8NDwA9Isjqr?sk$u}3)t}wfd*ZhHaa}x9Q%n*m{T%`V`euVb z?S}yGKdV!YO9OlMw$k*%}{+|C|7b()+_ACTEn=fN$(nCK%ATRhneB;`SmV#?#L_c>C zI~gIR-MN{<6;}qKp4eGKw(|=lv?hLsH59c|Mf}s~J3Z}y{s-rgO?)<0VFSGcQq6;N z4I0JuYtpYN6FZ%r`Xr<36j}+r?H8qzZ}p;p=CWop;;5CB0XxT{9yVBIx+v2G@W>`b z-)wbt5o?^kLAP6V^X5j zvK%BasOICt7{LV^Zqhmol33GC*;JM`|V_15-M^BjSj7~+WC|Ha#B1C9)xNu^$u$?hW^5{ zMs{xm{#hZ`(+c|ht#P8Cp=wphA44r4;uk&^>g*-)8)SQ;Goy+T5-RQQzx-a-_ikjy zu3N&k_j=@~W55?R28*ipZ}qj8HemKzjL^fByBE~>4;k0Zf8~~r@8m)C@fn4Y?-B5N ztxn3p1(LAFmLOi_Pz1X8uKRLH63|!it<6|`5S+J*9qw&GsuVpdbs9$t7C`OPz8h7h%q z^ZVb6F9Kh6AYFsV@X%#ky_9LtznUmOSLB(g+MqmgF$tP8jgX=i&|&-GRl8HEqsUKx zn#3)CncvsC_i9I8jD@RVd9|wcX)s+;MoH$%??528Q9=GX&M-M!l|oyxrH&1y$KUaH_0<9v}9MRx~~MuRVFub(2ZJ zqKNcK{qZsRjs8>1`M;H!Vn?+M zs#(&}NlZ)H$>%>j@Tzy~J^tqK@~7gPpta##E)tVBo)I$+_g@dj z!Y?2@pS$K7s7fg_j97fI3VLWl>U)d#rwrtEz#IO+sT(ftHf@>F&5b?=NsN8onY8cC zGo?6+p`v*|%pRnc_VxlaLmZ~zdivAD`;hHI8xQnv>WPyXXM1#%y!Z0UhE$Pz#BQ`wu? zQbmziA9)$nB2nmgztX|@r(2%-r`=|Qd}ROK#uCyG#Yv*d$I&@*uqx(!=uC0xjZ~00pcoSc5*Ddis|LJ=dczD`~)1J6oJLgW!>s*I;=xdp- z1lzd6tvB(X$l*?{Y_l{$;qmj(lPl`&NZ-pbP1O)MP>`~5owsQFSlW<~^KTOV+2kG1 zTO0Ws`0WTQ$PmX^W`JX;z*6!%y%!DcA+sl{`y8h4h5z@Hz_BA(aDb4{?}JTXtnIu~ zblx^Lb;cgW(WSQLo?t&lSnAg_hQIOO@Zng0=k}nVveqQqb*PX<8otN!Jg&872FYdd zf|7tHQc4va%r!VH+KIIHGO3fG{SR#v%otQ@V_uBMSnE>K8B2)*1oV|`UmvX}*uMW@ zHRkAf%_k|2#KI}I(JMYpz0yPUQ&;o8uGjB6S-#Vc<{gIu>lI$Kf;pdNlNMdbWhyYulP% zbJwL}8R6cY-fqZ@N%&!(c}kqXbfg)BVFF;LAX!krnFf8$ni2PoEQ=zKsA(g$y->WB zc>dFjYViIJB)zS*zV%1G)LpJiz>03){TqfnqihNW%XmJk?sFtSlKVS?=LriI#K~hL zvHiU5#+Q_tT+#MksjsJ7_nmzKzcPXXCt&!3DPJRpMnPXK>Yg9p2i=FmIbK3kUBU+0 z%$f9ZoIGG|(x+22NLM>Yr z`Vlig3H08pSI*+0grMOlx?lMiHlJ|@;)m`(L0PDC)UOy`)@GhhVzxOJ+UzJD>LE}v zx%R&26PFh#&v_S=>0U!&CKw)v(H^|d(Fc9F@IBEgS8Tfe%Ps#_nI7!yAcWkPFMJW`hUP%Y@V zZA7&9%BnzPRAw9XdL5|`faHDNYoDisDCUGNf{l*XETG_}H|JS6$^G6|dT3sdo^xR;BUL7WqR>J0_m)p2c@w8E3rYCKY z?i0wZ+)nYr@<0X#CaNDKk*+XC5nItkc0t_XwqzEe1izFRRu+CVF~(T5o_Cp(N@CY;}aag(-T1X2@U>~}jO%Nso< z&RsjMZ&dOuVGSO~R5N1j{B}J%o$$FD?Em}2pPj$G9RH$_H8!R49wya@VkxfXH#hDF zx6d>7`ySv*O2W0&2AyhjQPO&y&k_bbnEx1ycwY{aelh3%el*jY$ZZ(&592_KW#QB| zySmoM0DDU?9cjEfR$)A@KANcu^_@KFH%YZIa8;ps|w(qJuj`Nxm z>MdavP85ZwE$RaKEgv363LnNUGoN>;gL`^@Vg9lt`M+9#XW+jBNpaSWSFt4I#|!V3 zo|OI~0H5@_M&q4S8|FMyp#kGYXk>X1vPQIDoNnd+E%=b#Vwi87 z-J-s-)CPeM>$^VS#xR5p5O5-Jw%<1|{GBml%rmvENXZG{r5m&yhAtXIO%kKV$cgyc zvfKme?O5-TkX;V3nHNr-c53mSUrtwk7^b8>kNo<;x zKy*I7fsVp)T|@?vXL7W;-y~33s!_0lD4CnSJf9M?7N^bObpJ5FoXc+Qu}jbC{Fu>= zGo`ql;{tMnvfkE`CTn!zW4cHSm~ZFh_x^AiE7}N}5Rq8QEo#5aT(nI5jxl*i5yZwO z|4+QYG^DA?(vCvF&AZf&SzW{_*X413=B4tIG?VJ&e^@^Vg~c!*lYx%0#}D`dmip@b zcd9l!^XeA0PpOv+Y6P~Ynvq&fbZ7Mj#1iqNStl%f&6V5LlS=H~M$0S|lX6;Nb^{xV zfQ5SVd0N*uJPOZK_9e<=vVr*6$=GCQ%A4{@&x*0Q!bvgxC7BFpz_urg9u4V;Vvt%JgAAK#i<-+Q;wnt;f9GzkZeWU ze~YnDRIz!@BTG|7sjd5|C)Lh+xlMb~$brK0F_!*Ij1M+~Z5>#MZJWaYqgsYWsSyvP zP+W6r+Ea^IcZEpJ7@B$ljS5ky<4gGY#oVS)kem?MYIn>}xC^Jn#0Mqpn#Z2xLXA<| z?a!h162b=Ex@pjIGBazzxuRL2S%^knOwWus@+;rmrSur5+zKbhg)HbYH0S#}OE7qH zOFX9Ufn}!mF{CfO_?EcPKug@{eXLdvue zKd>CL5RMQya0{GxI}1Arg!xM~UAqjBz=0O27Fa(L=n4I@WA2;BZcyOd(y#o(w+J*d zWxNjgiMjiFXI-Zpti305NP$h2LCy#(2sB`J`kkL91a5V*q;%+3Q!?I;Knj7rJI#%^ z?^g!ea}JLk>js$m34Os%TQ|pF@Gt_z;b9?Iyp|svd}A?_;5Io;0gtmLdSXxt`}%8y z%fjB@JzsCZ2XMK=NCuyvV*g{Fkvff9&l%{CIJ49IY?P~Vw&0In5-#Pp3_bvMRUxqx z1j#6&1B@$n25H?4c}d)BEwG+YeTDUFk}`?c0U+;FwT zfB$(iH?>m9!u(y8GL?Xec6AAKo4ciq)&DLv=Sj`+wsbK(Y&EeoZY#z^Cyh!sFK^Vg zAvD&pqm1S=UZ_!Y^jrCGWutK9Nb~+6k3)aG~s;}GIGdg#3W5qld@9uoFIN`PrJblsosfpi z)M$EhdS)9EW^)n-di)_qM#pHXJHL#6A7Tmz0@_H@r_98lB~zkl4){?&LQuoE(_u~A zV8(L;R3gIXV*D;;pS=<2+r1^n>b*9)uSP9{W<^MdiN2in=$mB3;ou>~q;6Bn&tq^B`X}Q=D};wDP~qbfVkMKg z)Uj64SN%$+B}-0#(SC`>n=_O;X@1$ze1S3dQRc#rxJ`!A&Fe^Jeo36Jfsd%wC9!I@ z-|lfX7_~C3$(IujPdBM0^v=)eCYNMVW%{uwjJk+=cYzTr6-B-$owg{4p6do*k$&)4 z@d>Bd<{vn0p3K|S>simcnp2_5V`f04?Tm;&kkmsUmvV{^NZEKZ$QQ5#t9t)%7Kb7BleT+cG2>YaO z;l!l?B0Bm-7p}c6Kc`l%$d4hA^?7p6lMvBHnqNL#MxF{ddl-fnBh=dHyZZ5E^CVfr zI*$Vfe&YI7{}pXz?!eMH+yzYacMap03E3jJb`}hT<2!HCq3Hd*8X7GGV^xhI=q}P; zPL$h}GeY1ac8z&vp>05PHSiFkH`2i_|2am1qo^#8^$S3TVGWr@p&W|PJ&FI~?T#$R zSYVI7g)UD(gdbPQ!hwgtxx~vy4ug2(;zx&2dQ+J`=IFxu9{F&Cx4Ey;;Agk$oG>G& zncHKAH!Z>88ctf{E8YD#U3kw;3Dp{rkp~yX+SC+oTz#Re`btlEqewwOC3|p=B|%=t zu?vgtH*#Z?rz5Zc$wTSsNn-OqBNL9lmEU0%X1n*Sa^nmNqwl(@A^dR9^L$6!_arI) zasgMNxON<;H+g63w&_ABX4QGvGu%t#N1z9t>{g*eVQ#o~p&0^0V_lw14scd8=B?|L z%wEXZP3jECYR&&eRmID9;k5T{Bqq zy~GCOGV==Wth}gz!+cZa@^m(^W4C3sSCeiXM^;!Fl9LX@XMVH;QO*(jC|Nye9)`1( zvQP#gKhYBq;5!2Y!*tEK;pz&rf;hugMJkKrvv#BZLLt|qjWNx?Rth*&$6Mf7PbfU^kme6?LK^bxxT)%&pEMC!G5s zz5n9(G!x{KGX$!Hg=nj#>S+>yScMWY#0jL>V&`!12&t<0KOKGFBs& zl<86YcU{|ZnMKYZJfIAxEMP#(_O*?L91)rf`lC=P4qr3q;ttPf_+1k^W#|+lCZM^4 z&1X7r#8UbJcgCsDQy-2f-;-@;jWnn%;2i!ItAb(w-WuY+W9_p&!uV~U(@;GBmd=C1 zvbhCP5tA8AZY2WYrs32tq3oG2rSu}TWYc)Lyb2rs(tl1%kThXbjEe_QibqyQPC}Oh zym8e=Jky-Qh9V&Jy2)1+RbXJXDC9r9)V+afsTQ7M z!Mnt-B1pg@h^udo_zn+k{jI!YLzT`oTHM3+7c>?(b>~anR73FmRNs9=VbJ!>O9+jE z&`$o`64|Jo26B2~-0+NgIp=c}JtZmz882#e&2BY$f%D)hby}AXy6m7@&>O#(i=Y<( zR*Kxemf?ygSe%Lf;C+k`i9G(wy|vA)$zCR23T|0{1U>-5eeqB z*fadE#uS6!i7LHuoQRQI!J(sznU6vuOr}qIT~&;Q54yUF(e4ptwz8BB8cvTuzle_@ zsx@oiOHg+JI~;q?=SlQ_Ipk46@PJEp+kgyRj_;>lhlv=x_Zux4*K>KG@=Li8-hmN_ zuQ2|)e*b7=A40N2`c-RBOD%3er7Jh1-a2HQ#E=ZvOql;NX62Hx=3nL@;afV0| z|7R0dGLf}g8FvclC2i_oa&9XfugR)+Mt69Gl-L-bzVZpvG%3FtoNp#R&Z0?)Fg?L- z0=L%VER1R{Lp3LR%U$CBsa02oJJJn@DBAX~y{r~|^kdS|7eheo`6$4+Sa&#UQ!<&x z%FnK$q;lS5L0%g33J(v!e(-9gYT!1q&eNSo<4S*5dbg5FHHbjgsV&7^Py#7TNjYs)~xB3-%2yQrbDlLOcy;F{_IcLW7dCMAqsGeb~A&3EL zPqT+XMZS9Dlhg@~O|}NM&KU`fTM1b*c~ErJ%&SH8U4FWlI#AT3Oc3U=C;RBG?`F?k z`bSw%oKHi;A*QWrzsyDA3yXNg39Wbo zr%{dMf=GrdAWjY}_4yh(jlRbpT@K^4h5pUxPOIFJ>2ArnOwgU;Na6Kes2fBpN%SXN zSRHhir*B8~ihsXAGf<0AvuV*(qAbhY>oKmtYelj#z*OR+Vww78@s^+c3H6iA1(WzDmE^vgi zJ?@oHiyN!kJ0s5mdILt8(bo75%5lEWU?0y6vV#E>_G0b699MwDR?tP zoVq%RNw>XHJ8u+&pX!zdIAe&xm6nphfPyE>ArilCqV#ZeT2%P70-J;;{d(#mU5Z3o5l$gv>&>FF8)b6-#Y zni1;cGBCD9I@)v6cv7;cmaFNCr8l>a16j+ZiGFO^H5x|Z3)!i{Rm8i~#jC_=y7A%o z5;-^{bxNO~D1u+=KXoeFaqkyBQ&8@iU6)EOLp4~Y#;vg8b>ZWs!I!AjW>|{|HU1{E zflkLv$w5I@OT{k!4F|p4b1NkcE4@33eW7~sPnebT6An`&KiPsAW~lB#4x^J&bJA#{);*mR#2JE)uk0wLQlre6R`KQV5-|!J8}=c+uxT-TVgM_d z{ehW> z?_Pu=TWd!7jc<;TxdgOCluyG8-zBk?Zpn)TndXvh*@vZFtJLVRmC8f2;-eIr!HW@-Wxgp8h;VZ$-fM+;!#Z&*(%hM@I?gUG|~OX9-YKo%`Dn6u@D%vGgCF^=N^QEc*3S6xW);LuxG&1ulR`dOT1JY*C)lc(N{wChF z4o24u>lbV|GRu2uOIlJm7*0Hn1o3$sVh0hsay?o-zI? zS!$eMSdpO}nc)nFQ0iNgHudwxkH1X=96pqKHl!?H&T0A&h)=KA?8Gr(r5edJYoDN& z&1=$!PgG0j2k{fUq156vPzo9kc0>(fdSy1`#)*`rz_J@;z>}hdkJili8aX;Nq(8~G z464~l!=~2HVD*T1si&A2c3he2oeFo$bU|1{M=bHwX8eRwHj0(Ns%j@YNtWm)-@~I3 z>Bx4M8!z>+47Lm&l5n=I@$nz+Y==!&RGGa9B|d;3(ZY7V>|K&YAwD#wd*MZ9Oi_dl zHn%v$r$7+h)aROhp6P@~qOv_A+bmS=6|*bA7x_6#=uPJ{gjP?RrKF@6pP1v*RYB&l%h&>rwOls=?avrdt6X8H=aQRC}Kg4G~}!4G2}N9JsPUfl&+T#p+$R5*#} z8=DUNJGkVxWqsJMOEi;tlFC*AeLf$4I~3h4ACgfglnT{&|Miyi zU)Xm*A4%(2ufzy96-q0yNfp)5ZkRub2?g%Fg`y2%Z*%A(+RnQrXFF!qj{l}Z0L_72 zexHsrv)7UO`e9(8MKY|g_o87{SiR7U6@D5Y<#5K^U5KHY35?iNW62^_Ts1} z1G!5lo|qo{IyVZxT%gSy;bHiQ+X|@zxhsp*1HYm>P7{$dlpIim!2AlUeS>6PmckXu z&a9-LxA;$)E33jr2?0)icZFE$uV(c4^f%)tb!el)5wA7W>ZcY&j4W)5>r&Lbv330pcC1NnRbAB?7#te=u{{ay-8x3PhNM zzC}p>Vrp-J^{b1(#)s4hjo@+b{-dC}D;ggy#?;qmNd=VBW_**3&uppNh;&C_YD13m zW3G0Nbi#Q)72T?+;IUfDk|6q-8G3fW;P41@kN@Xkht#O*WE}ZfQ4EY;fP5r!$SVed zVBhDM(WG<2j1tzh2Op;q-nh!V#b4NFZkF)0F1CKNf~QZLVGYj=J;QAKj^Oh;{b3qv z9q)(Ft+|GVr$!G8xrW=U#m9|h0nzWH97ASGUy&hE9x|^o-`Ejt-^Q)*V2=Zz{?XYVwPgFf|^tJtB>t3Tom^`+V9U3n4)ZNZ#iuQ)nZv-+iC zY*XlPnoY{qm?ra&DT4x1fyp0`@FUoM#tbsiY8gp8#G?l^Sh9k{ga8I4K&D3cWdb;? zL80oYiLansc$tO?m;i(uF)fEobd`~%T!TTA; zz$W>!XvE%@;cYHeBAB&GfXrR4Y8UR|ZBJQB8t`st@Af3+Tt(9o8v)AqaqiLHzbe9ia>Z|SI8O4S&L*v`3TCffU(GWE9**%Xtp zv$RifGYL$1&U$>wF-(#gPpDhDzn{#LT+i;h#CFn&lF33QL~_0(+>%(~^PN9^dO2vO zms|XI7sM+bRj|xpF-Gj!NabV9v>U-G9V^9ViW{r6k>k&%SG*x8b*BQ%X4J0cd_ZPQ zD&ZJxe%tO_z6Q=72gdV@Oh!niILn$V$SdQhx z9f{#$NJK_dVD)m)Aq~B~AZ7TuD^B+rAp*-xbfi5NFK|p^DkbkdE%@%FQeuE*%A-%D z)u7dCmRK87k~MkrQUvUXT&!12xqr8O6)v4FO|UbdHEBM=#2>>_ER=QYY#D~y&$Pkd zT5U9mjpund{^_8QO8a-2^x7uX!ZOp^+^PCYt0vBHCywUNM&p@z951a#A=*(GzL!3M zYR-9_|E4;0=IvrGwzS4fy3Km*`b3{X>`PfKP1K7=WeZzEzyRn1o31|MI<}egXJi;I2NoGrr6Ma^Lg$oY; zwe3GHsv)d$&Vv4tl6c>hJIWuC$I0q>tUj#jUy-Twqv33Xxg-gvx-$7T zo76K^s*&;gXB8a-Pa?P+f;+JQqSA?xh?$}DY)j<1u%Zq_DGhGfrrmD?$E64dT~%Z& zlw>22fPi_34Tu_{I9dIG$|a@3ciEwDX3{SLlbDCqOhuz#CnykYTA`|3u*al(0u{T; z-L=E#S@L^p**%N92yM(24TO3lG}Vd8q*5Q9w-wX6o&_aewWG*;R8DS7Ebeqzh|dzg z9X=vRK9Zy?r5t}rqtrgh=ilK+;Kx};b&6|yO=$Rz(B^VT3{ZqpA%oN+gC!V(;u0>i z{Gn7vAy+Ov9_x4!Z$-AMueW>KJfmagq9#^APFL3LV;2zKEJ9TGa(;zBw# zm%Q<^QAq7yXkXmmH=F$pAlvx_=XI%tWZ9;Y1VO@KUYRWh95f+>cYN5KgT zOT7rIkvL@hP+Bd|dy9ojmv1IR?{JZ*NNuD;b?3!8k<6-L;hBa}+n%NwEpL5*Q8RC) z{Su8nTFR;?mX?;m^Ff)@f*5Fc>Fjr22R#tw`J^uP?j_QlXP4}sq7!q>sGL`UhyHtV z3Y*G0xkaAeJs)m7c#?mNJezk)T4s)4!S(Fl7G>*CLX;O0+hH^qz0GVfd-H~WNU z%_2F_*1%Aew655F{#PYiv+M18lIN$1nKvPPuSafSU*rxVn93@amf~?=72%j6fiUty zc&(@{WJngnrEJKG*fg9}rqNIqhTSL0LX)IAW4~P__&q;LNcvIuujC@&D|ab>`6@Xt<7uWET7iYpU%%ViSPPyflvrUofF z5GiEkJ^}l!!uIZ}CzfkBKLr2kE^LjDZeF5bjJ=(TroL*cgv{pp)6a-2 zFOs<=W3vLo$dW~W_hTPy37XjT$dP&FJju(rGoN!aZKq9Jx4LOv`@W_6zgmDk%w_fY zX8*NN5Tj6B<{dlp^fKRVNR=k?y`u6qo*i*%t9mb~L8&^XFnbkcOe3*rBKmhS20qS& zCm#BhvC5~VV80QrnIo~xpBzDS&!QaLRPt1BEUz#8Pu1A$ata56)0uX~FSD7>rx73M zMmn*R>Fm|Ea*X`h4^YkeodKl8Yw&A0y+#_^dP>LT)V%>2LURt<&lqepUB~C79FhhU zy9G^7j|<5IDsUY-W^9XLwS%8XuW7+{Zi_>epmJ8`ViPD>)J%nq)cHR7W&egW$ln)u zO;KPYxyE@L{%>vJ^h)e#S`p5?JW6UD`8^Aa<~7&&=xAS9Ae%So6A`lHtNebu7r^gq zzkLNIYS;4BQ4pbDRO)pp_|1`Eur+Y_m%x`Pl2tOBkcRhE?+Q1enZNQQ`IG0x8Xrl{ z_HisXWiq3yg=k(pMlj+f)#zs+6>8?kzsilBf5cldN%WU5aTBN!w*P5XgvxXk3n!S_ zfu$OMP?YjgPVTQo3g14JG&{gGlbBx1cgN(^!=WOwBjb2=5l-fmf?SSBD^7SbK_#ftCD60c<|4#rOAmQIp()ihD zdfB<;B!`BiQ+!tCN@Pn>LSz2ttd3Pu-%Yq;XBZ1EegcXx0|tZ{tUn$7S*fQjSUdQs zAa>@VCdd1U!`KQa=+lkAn2f%pjJG)$oPNWnD!;q^A1CP{dg`gvZOCvlbeFJkAJ*^1 zrH|plM{)imIRD{z`(a%87%qJh8|&x<+yE<)Zju>{2cb*yiFgq1LE@`Q(l)?*fBPqH zc+wB%J{HM`ogHR+&h(~66Bp_IKkvg=Pos7&S*I_KGU z3=qV`X>^*9F8gza{k4D{OqYjr>++4nFhW_Xpm!vSIgxan>8`*}He3*@zbs2uF@@gA z?^Nj;3>8s)P$`zuxsBW$97s@;&L~sqPn9E$#$ZN7km};mQAy&Om@Ruc@sDD~n30El zB*YR^utfs5GET+T;F8%<8?|vkxsJiQhm`9Wo0`kJ6&5uwm%y0fvQy#*a}mU5UlX>+ zsMw#&R?tX3GvoP%(o&HmRpX~3_gD2!fBh-tqe%WI5RJsS1qV5f0L9ej1xl7etn|c( zr=%q58m)BFr|RO@<1i(`cpVKf2@f9*Jl zLIx@K)Rrphh>!#Kqa6REz(10YJ8BodJL$4h;G10jPT@^{yE@>>elFZZI*jkXr*w4L z2vgzbjBE5$>Fsx&SzSH5Hhf6hd1O97KS3A45u7h(39P^}tmhhmB^UuV^4S>#LB0X< ziCmbkEPArGDAJLrmh>CTq9o}K$-C=Et0&1BtzJYwjgFp*XOQ9mB8empgnpvrp0Zqt zE0Vg9ML3qaV;e+xN{;p{S+A`41kAiKbA#VrK-D<=kHaN%NL>u7CtG^nN^c*m>A(Ml z*de_m^&h1l9&!VJT3SHRM3(V%)1(y>=mwcuq8?EMGq6;C#~kHEKjAe_I+2rlLG)Zf zc}3|HY#jjc*J>$tr${CG&6Rf~(xWD^q;#}8iz+5*owS2CP5Bdmx+~Elg;AYh9*kfM z<7ebtXyWmPi#gFvI3i~0++4<~8mD4wAYh#VK!8s2#s&NLFe-4Q+?j@pR!_Y=h@zH> zqNa(w(+I4E0pQz_H=;#B5*qOw)Rro34?E|xJ&23Gq{()t|CW>x(JIAD1Lmx43YAj| zp26J_r4tVuRU0%O9=6*lEH$xH#(#%suIge%E>&m%sN zltMh?qOZtaByZ1m6KSXu{%`-wiy!iJKUjn)D9`!yr{C*>vinZ-xa~zyJlXSE@dxpr zg6TvZd*UFyg8ZJrEMNGH7v1$s&rP(BI3^tcvviLA@jDh~ahzYxKNE{Mky+>7aL-@P z`OQ~Xbue(ijn%WS`lhu0EZiu-2BWnQpXT@oSwd|k4R^p82PK9YuIR^%PI%zI;G|y8 znz(q9V}4pU-bdi83hk(~Wbh zZyUII+=6Qek!Wm5ItB)4jG~*SSY{V;e3Pgqd8@!O;XI@i=p?R*`%?H}jB+vy zFvNfv#)Nf2xLkOgTqbk|^(jX3YVTv~QB34XExuA-lO$1kY<#0i)Jc9K2=M5qz5u{I zuY4X90VeI^SX}fk=(*k;QpXqCH=ZZoa11-n1u!NQ5ol;V28$P3nFF5 z(0`r@aDtg1-%uJWPeUHbf{3c%V9rW%2YPENm>5%-DPzJDihw48ZlpnHU@VMQHy6XC zTro^ZT+>@m0~$$?ILIp=3VVk2=vqYl`$d#CYyc)>AS{u3LpMws8)+z9Hz)Nj58Y+j z8VOO$6~&ctHBRNH=tt5KMy67f1(CPj{$t6S4H6|dX6Ib0PZgx*??=PsMUdnC%A=@^ zb5J1fy=CzZ%jA^JybvMyDF6&?2&VB`4)9;!*cubg8BZXIdQ=agCY^o;q_`#wt{@~OJj?6Cu-YFL(Qc;H&wr3Tisa8b5Y6}Yo zfs^PaJ%3~<7G|%2SOj3^i|exmU!Tf22Mdd6WoewU5UEy;!QbR=Fn|Vqw}o*H{a&NT$pJ)WSHxKguCR9sc}cfyw75DX!_=RhBBG%lNC` zyzOD%^uvGiTQ4@5fWRy;Fh0}Cs!)qO2w+5+tNa1y5C)2c6|<-?CNYYPAzG@;QssV; zN>FYLZO2{5U6ePGj{@5ub{jkP)hqVzx^w)=3zrsre`IG9Vxe zLtqBwzB?#}QA$UmvC0{(wp2M=MXY}p=cBh*fQbj3-i#1Y7+IBOB#n>4;_pv9T4k$7 z0v)w*Udcb_ynCNF^A-+)amiEh;0TVTbL?CwPBF75#Ln^htXuFNP&LlhuvnzX9Bpz? zMankdzjldq7QCloPKk26OCQ+i2__KWt~0A&barj*hY$u6*u*Pjxgci(v&^~cUy_<2 zbN>BfKG6G{0;y3_Fv&@X_Qgj~YjbZe5LSH)Rz{MZN{7%Bm zKGKs%fjSF`6lzb!6Xc=&&ardOr^PPTu)MLFb?(BY^~GPIs&Pu}K%^WIc*QaDNeso# zC?`u%&&sKW)=i6^6@p-tgdu+J40Ts1JE?Tn|I|N~X~7P}IwD2yUlA$e8_Ii9Y|rrr zBj6ayXlcWMfdrZ3^DI&CP$Y;QpNmtNA+YyG`(MUPd5Drnq#q=U%yC#+$P8;ziEGqK z{=KBj|M(!;tDnqDUf^_YHtW{@d~PR>$I;U`M_Z)q3JPPji9I)oIf`dwoh2kjg>Q0- zddj=`Dl-E36uE(juu5d&*^5ECs!!~Zvsy&n_3JNu_&5JZ|18c09iP#N#6;G|A88~c zvmd6E#7hu0>VA4ue03JBdIrX-6htEogrP)=`)4H^8It_PtDNJ`tC~EXQ&`xs%sMyg z++{5l_KI;H34H&aJn`jm->VxaVrpCaw72}L4ZW${vImULh}X%nrM zh<>enea;|p2qCyheSj|Vp@=va{M4n5*@a6Rm;Lq5aaE$eCbH?T%p-v(0RX&}`+nf3 zHuu0Sp&Flk1(g~{XF9rYKJQW6_yrYTKneYF;g9*iI*l5uBz!25j)gH`VI!1IHWFbG zBfP%8m?AqCLqa4>!o-G%NtlG#Pjd=_`1U;x;~gj@H7vf- z#;8)1u=tAotrtHb?(x_#=nF)jH5f1M!zPBXdb(nR~evk%Av&$ z-RJfmD`S^>@`Ff?MC(MQlZs@d!=0pY{PMkD^MRlH{Rj7D4vW7=91BQ<7#yF8AZ(J% zDOTS3>gRvnO}G5{YhK{1|3+~Q3#x=3< z6n#__IH_JpI8$@lT%L%&&63#u=rX9|166 znFq{yhM!co!zZseq#&TQPTNpA3m$TL6EAs|2=O%2S?+x{kY!JI5C;ZoKW?f4`aE{w7?NmotfF=JCrAKLB8FqMV9- zf*)@BoUd9fw{GjH=KpAvbh4jP1@&-^2QPMpy?@bX`MOn6v5L$0Jm~{J_xcBOq!kt+ z7WP(4vY$$lMsj?0ErJmn;!rnCLuBeGT~9dNeQ4X8BXM{88P=$5mhT6a*ZmM z7p1l_SCz|NdU3f-7TSpY64T-w6${Wg=ZjOb&TVvE*SSp!94um-9|2wmytUkT5xBU? zXRf%CK@0D0_3;aIO|OR0d#EID<*CPICxtRIo~Ln!GKYvf@Ay1AQ4jpBA03V`0}jV) z5E}-<)XSMRSX6|Z25!c8K_U{UN98!wQ#I0G8|WJJxkl&5Mfr&fy5U%P&qR~58|Tr-5qo4MIx8HG#{iE_79|1ztPjkD=m9z+8%;g+HAGPbvN~ z5)muu&`M$6JhoAkO2XQW1i4Ja(pGvn7O1g%PXwpF_C4oQ` zF2Wrb2@x`svHIuV^xVI`^T$8y$0j%_s8Xzf#asMHD=Zl~IgFB#-nd8oI2HR1FLQqE zYghZ*7e8v33I;mR@rWZZ|{Fie_s z&i(3-KK5U~@U6H1Soyvs$T0>HKIdDXmwxtFzwsgvz2`S?1EH5458PBRHQ}E=*OVhR zlE%>kyF88bWKN-U;>gUTjACPDRZHnu zahU2SWWedxNSX>KDxGYv5Cw=H8vdx8Zuzrcd%n+Z-u3G*^dBIUvC6mQ`%-subX-Km zbGSyQIbPRDBA3{>?8-uwo|;0Jv>fxsteeeT=kp!MEbN#sZOrbwxM(VzQPh!~725>G zS$_ZH*Z0NFWgfWo*BWNVJ)|h7pq_!NYM+(Iqks2Po-k>fY1>RDjWJX>Ai#wvM@Zz! zKk%~N%l+ZYzd!K{gA5B(2$BIXD?cS5!aL61nrl*_N|h>BAvTVbqORF3O5Y%j>+o-MCWeX&@| zc7x=FA#p#>h&xMMClw)w-V;SV#v3b(6VF>q2mJWY`^>9O9=qzqu~R2jh{zbCjuhb_ zB~Juc0R+GP;_tM^7(>>Wv=Z8FNXSs=Pht>Z?G-<=`pg&I^UCLugdV@dJFy%d>gNap z$U%DScrlJ#)c-|}6INq()8iVoB?rdB;zwN;gSnF1%8QD1SZ1Bun03ylHXLS9U*G61 zuFpR9Pn)fXYgERm*eR0O`MGc0g4nsdjRF9yompKyyLL|;>(CQBnvyt;dk~1={y&rD zjFJs_(>wp>36FXBq-`c`V~7k9#oOZLqZJgu!e83K-@*z(U<|aLO1~cjz~ZZ zqmsvgG|e-@98fIJdVorcyn%{ zs&H6I5j~E-joF-VMF9SYydXdXKuG8a1d3pG$O#l61nj=+<}1H(n?FuB_7f*lQ;btV zYzWLbV~XP4`NeZEmD+Fsa`JdwYl6`9D^`=sRbx{QVVugh6l-IhvyPNDb*o#YM~ynR zP@m*X!#J!s%=8(Tp2Q!oTUwggv+=$O8%R%HU&h(@+{;(2yP%RjEh8}6oZb)ce-dGG zIsiZ*WV|2}gk7_P;Kjjbouie3yqlsJr-GQ)fn;sSTb-zVV-iz5mTTl)t?7)6hoP!P z<))V>4#AYMF3JrNQLA*Lj5elj)qLIVdgkyczw@j(%xPp?6vj2^)V|O1*>m8?RqNLb zq!a*UIw$|oZVyoqnr=eJ%T34ZgdxsYv7*omC~_4%OAo|3^6)zrO*r8&uR>|E$0-Zs zKr}gt(@E$QQB_xNiafC^&bsq*WB9oTF%=({r^aY`5)q%%hs+w zd)12JV0LCOI~>dmt4hkM!b-|Pyr?81qC_DP5mCx`fugiXhyn#72JQO9O}9UK=hoz$ zMC`y3Wiw9rlK(xqZ>jV+g~Y%lkJGJ)PrjZkH!cf}ZzfJR=cv_s)F`h$3yrE9^`E!q zPPobV_^`)e-qpN4KdLH(RV&jYH1vOVY?UO431a~0By zas%NFWSDm=uf6`(2i|wqpppVbOy!C+nE=t2_;idXT=dWGjrYS>@yh<4o4>v7<^4M; z$^#`!(g}!q?RjYI7M6KP*pTLMM8(j#J%X+Sgo!9z3WyrDzxF$ zjc&Dhb8ht5(=RUn4QG$TyxV#5xqn=-?gD{%hQgbOLIordNJNrEL`djA%u*r|Nbhlo zoIoUjLLdo5LP7wr)`bjBR5B4njYKa$C5|`rN;#DiTmL#vXF`dpyjwQ=m1ZYuO_&G= zC=)kU8M9EUR_V9qMvv})VJh!7dmM&=e;$3~+;h&B5`&{Do=P8W9|KX5`3|4;C{MWy zI6Oix{dLEuzx&g}`*uV-(sMcx>)Me2)+Br57u1Yd8z?PL;di=b$N#OdkgCYq7-cNQ zlWpef*6-O;+Kw94C_T4OKeF^`hQ(ly!!Q5-8&LWrDoNvx|YG2te@SzCVBNdw0C>3Rx4xu5}a1)QLCC(FKOG>$-o|mVKO_PIs^cpy>gwu zOM~>el|c?95fLFeNsdSokJ3oZoH$>#%kkQ9fBz@H**Wkbc3k`D-Od<;K-{-&p-DZh%I~JQ38T6?M*4J zN|KX=rc(k3A~>{n`-C( zIg6az>w~OhZHQdTB9l)Hr`bzm!rJp#ld{%2YsuJfc6e|-;gvCWqfDdpu~GBT6H8lK zdPj0+u#mvwTUJWYgZX0tbJv5qikWin~b~rx6;g1(4e9^uC!^jQQFk4I=0YEtHko389S&j=7oDSukWe~_E;i{P3F#>4PG~_UbbiDW0Kiz68V!q@Rrpyc zy2^I}AiJv0)I#VXj?I3~xpF5?l9;rHB1KZh+K?yKX1;Fb7Mi`!o}u%e*yAwF$#U)G z7q6Th&JG8|K^1IHGCL@w%md}!v2t&G!kWRGZoB7Kx7-l!6g6^yF@KX1)~PrZEllq2 z@y&Z>v!Czuv+3k1f26PXHC9_^OwgKEnYo4fFK5KsBv^46W(j=!V;@<4)~Z!2XJ&?j zL7_O6L?2jXxk1s>9WOCLi0}O5zF*w@)wt+1?>o(oW>On5K=EKXNYy=I$`M%`f~o9u zQXa?HRvV>E-RigJN6ViDUn;CP46|f5U9#rv_pX>74ra#ujtmkrL3bh`gxIp}{yVl_ z-_7B~mSrLUaJlU#JeLaUdDcA6e`nnZiJO?;aY<`JB-JY2YIAJ9-u<^z-{ZF&SaBHU z6uD~sn)j@j@j=$iuo_m?U?3~R@$gEznMn&%?<~{DvOQ`74&i&DFo4p_3|Izz5V-N|4g@D z9t5Yz*K`J{{E{123_ZlXH4_}uPI^0VVG&MdBa+t-w94fhLb#f+fEXi z6k-X0ZTIfjdc(C|Wm2&`IU48=aK?O1r#=-+QO;W%ZLKl3QMzvRo&!hT**ByID-Od< zpLp!2^vCc?S>|+Nf1pTpD)IB*KCwwt*dKWO+1`tBeV+N| zo%zOLT-n__{&8Kux($(+6-P%QL;-<7=#mm5iXaedCI|!*ii80C2C{aB1pI|yAT2He zf0eqKtU4P_J1ow@rGJPUJ#~=JUd&pas>BBHd3(Lr`E<6 zw+$LqQEWWyhBujtaQL}?p%QPt`JdO#FyB2g&B!dUzVScyI7^btPiJwsG}`Lr`r;^C zfRm8U=e{Y2MDC9zgk+!e2eU|72g9=bM-1>5xqpLE`SjP0ANI1U zSj7(9Y3KVh5H7oW4;ynOIVs8K?`t`C8?33{4evZ1rC@I~C&*z{dXy8UOqIiOHXoV_+Nd<8@HxB~ec1@)9dExei7A_lp+K`Y~ImZk; zW8Yi@Sai&}JAU@j)Wp>ABO#iR(ad~51qkoyW(w0=&SiJ6x0Y>(x}+=Eh&MGHs?@DH zi7{|RJNo-kV|)D*$nkRwgq;#4hM2R8n@VDxb*y$!7$Xqi5Eyf!!>wq!9Xai#?p^T$ zUbvl&!ySN~W`_EkY-H%+fD2u1Lg7c3=lCN=;*IFmDI>z4RS3!;bOr9nb)?6{ql9aoKex-vP7w&tZ`+*s6E|Cmhat6pr6qrrxUY&&ro zaS<7g2B;Kg5>1qKWzN}VD`dTq527 zbrYsecW+nW-Zo>Tcll-EBO$Ji+Br_~Zp(U0U+0S5=}z+NP2RcKEgfjpxRYl~#B%N* zC)>iKVHU&L<^p;Z#Dd}cs?F{t$akG zjybE<^mnlcLPPcx1zh;%&PWQXpf3fF>jOz@LVJPO%erBIxv3x}-`@{C;vf^> z^+zt=;>*1K9SphXRCP%WoBV}>U(+i+e0`@;ec6uq`ufyp^^ses8{@!yw3z-bG7nOI zSEyKjb#|Gp(5i92)hdZbc%>4uXS6j9Bhh4+>?hDRD5ISYn<; zBd}7lx5_9w%`UNqrTx3(?puTk&?BcRYKbn2immQXx=9p#N4o=!Yd4~sIh?DPZiaG) z#5~BNw(D1CRHN=YJ$-en*6hd2-{Wg+2?DeIT7wvmD=MP&YPrBBRxW660T~<>9gLX_ z(8o<`#7GKUjB&bId++m6@o=wYe*QUd@OQVtoyj^<-SQj8VcFOD@WnGK7E`C2MWY9e zS)b@z!rdY>q)cv#h2Iyb^KL57KC+c+hTRNb=uO52lJj22;H%H5 z+sGu{} zJZeW(7+>LE#l*#RB~7!uKtOQ&Ok~#`KLm@Oir`a9Y^eh(?ksZ1c6en2!xs;c)jU+{ z7>)Ndt*<(m_R`?s6U-q>drz5H<#|Oe`}Zz0kPr0ffHQ|Bdzfvl=i={SjcP-tT$&6O z8($FSqIZI>AsiQpEjh)YuWb+gb>O^^N@Q9=ca8X`yglpA5T4qUxQxdXo58UgoBBv~ z@1@>VeD{$W^DiEjK`0c*3RP4C{+o52$h5@4l%vRe*M4VUS$j0!;<$j4 z;|#m?YO2qdc&>MI5||2$Jg&W=%ZCgm@g8m+hC0%lvgZxnT;CR{Ln9$UZ7a2n;+$7= z!}If{$Sq(VT6|1{o><+SDO%Dqv}2Af#7wTsw=jjBeCcT=tJW&p6SWlhFCh(fhws(Z zxw=jfrcWUZU%%4TgtWw_j(;iDZVoITWWLs~NKe(W_KrHd@g-m+Bj32!e|%VJcC?A< z3xv96ZKLOTk)}spZP72`)6{>vl7n+=>d&lU_4Bhh8R5eY_dJzpdvs(HYn3Wd!TwW_ zWIpGf?V*VbbQ&hYaVDU`NlLW^&sgQ#EHtT=1-PT2BfvMe+MybmnNgb#r&I9Jr~O*y zW<~jOvoUr4HLt7~11QrycWtW)atN>^h65V(lRdpzvT59@eD3k#=V(#pmN12{G`Ugd zjg3G(b<+zjR6CBYttX^6G5RfGBJPZl#N3~%V^cWeaE0owB#6;%{}h4sU4-iJ>^KIL zTWHx>y8q@jrZhanvyzg|CW)c%*`Hs%h%dd4gKUiz9hhcY&bgfj6N>&00MBBm{kio- z`9iwi(NdrO#;E5DbttK*ZRXr@UclHO=Fn-=a%{}?1^BJ@+(e#gw_E897-VVVoMrv< zt8!_)W3otOCu1d(r3+8ul@{XT)imn3EoZ%&j`4x6+BO8#a#-2wM2Rx> z@Bp!9k!!r;XN~@HXRQLcjKBTO?6n@P!4bpDCz32ocL91;d!ZZJbHgHcnnF8cmee~0 z>NQPA+W#LP2IQ3(ZGue!6~(HId0(lYVaLgibuD34D^>iAaJ^pRKVvBDDvIU)4+&#TR`aRV=l9H02l$A^CwC*i$M&2mVJ4e!eIN0B} z`qdk_&3{hRK0^ZDbv(Y9(+-J<=(4DdPhy8RkiLS%&%>BSlGs@+oXV1H_c@TYAg7GQ zG<}0oYT4)nXM3XqttJ>c{XBnlAPGMpa9+u); zsTS4n{8u_F(wVT6ug>VomgU=xd+bsb_o^1cz?=9gZ@J83*_hba#>U|VwXfCzm)$Xz zIl#im+f=t(5b8FD#5?Vb!3ROY21-AVDZV_utQa1w=Z~1MV2pQp;N}P2H<|KbKj?IC z$_LARmFJ-QalKTpUmMxIPt2dHWOw-t?^7ZRi35g+F36|FpuOnvHVugIi4YqoG&3TA1TxJ<86E2p^ zscIL;yoW>H>=?Y{PQ%C*krTY9chG>m$vC@?s4L7$m`IpvC>;X zs}-NP(RzHzF`4ygP8i5$#RXE`Plv)r7Qy#RmSE(#ooTkILqJY`xtzK>tjT&~+!e`LRoH?+?%H_zON>M<| zZ}DjYFP1-80|-M__zl-9#BYx#43wq@gOZ&F%A-5WfkeNncs#2#iC-Xsn-f$w!O}GK zzTL_y$-qYi4y0F`k1)SqPA!4&vpx-gcg=0cE?n+~GNetiX#-HQ3K=+Dhy5WIwD1G=n-JhUnxH*T@aaTng=<5Cr?ql-< zZrCgO)iUJ|M(UnO$mjXSv2VO)-6Q>f5Qii1p%bzHGPuCcKm-GNF15?TPL-nhkxmuZW8K;ESUB~!j z(+;OF(u|3CGBqAt0Y~nfORMsh3#q<44@LI5t1f1jL#@pR+Q`|C3)k&*l~SF0M8Bds z_mn9e_c+lEDg~ZGhP6ZUu3e{QrbG*%D*ZPTZTw<3jUN&hEHpoVDr1_k48`H|-q(>j zYdiXP8rHOg7&utb#1wE#RZ1qMlJMW(f{WD3Fj9RwGQ|tvauh6UPA(K0GK&)jDIMM5 zOouf?yU^hwL%qEpeq6#qFtfLp*SN5^eVAA<&qhjfN)w5`;ZR{HcNv|YCe}@EsvjGt z2EfWsOf>kjKrvj06*wyy>-g^s_O?WGU4_5B*;35QRd1+D57}1dLq`g&>?j+h$^>e4g0jXAKI ze^kxlMbRm=tTs2cGdvRQicgapFgSFdQ-gMLD>{7UWU74dHVxUGd`e4UUv;*D#s5v^Y-;Ps4e&0?kc~5E%*WJp+HbRv5gktu4Jo zs(sIz^Q$m;Q3WLQ66tc~jqRcupyb4iv8N1jrpe-xlzOzb^041~d~*Lg#OpI-L`lzA zHc%7xH@;jK_`-Gses9nE4KWlq15iSLL-0FoG*+IGagg*IA zJ!7xzbPz;e^yIWa<>BzfeBnY_oa3nj^O_gTo7|1g>p*Afd6ZB>OU!>D%LZ5)z*g|_>xP-zC#ZX$M+V=Sdwn5kgLd=1Mne#? zas592Whra+=P~-8gk4zGHm-0|MouZE!BqOmyV;nSm;pfiI6ghiwqN^u7}V9=aA+W4fBzy>r~ANV{+lox^VY+HN9)cN zjm+E^kj3{Xr6&<1+s%PfNyYj;ZE|qW&hiey@o+vVM?CWD<^aL{!^6qhS?7+ULG_G; zwDh|VACSGhy}6zDgEMUD`EM?%HLw1}C)O>L=aJYukTkiBjPW}jW3@vcd0=2*#*39v z(`2_~d6<}@XKO8S2nf_oX4AKcIBa-%I!9#r)fI|!l~BV3)TIA5TEAFil|T`B5;6=v z>@?nEr^x0s)i&JZf86C5IqZ^@lj}C9(yP^|QlonvA!gHZBF62w?X$StHI?GEb(FEc zWe}PdUIUpo=dhXvi7H6Q$x%^JA%=AcIXknvwWg=oG=%_IGm8U!GVymw?RMvzB7~uD z$xE;M1nXPS+_&l_-zJq&7CjBH!Tpu{n z6hqV_IkXk&4$?`8M)F-rl35w}4nku<&yygeRD=-koh8BaG$TU6#qVJXpGB%d#V*p$ z^R4{uT%{*Li~NtVgW>q;Doo)bTijK0Zo@U_hYwHRK(g=Mohs3#n;eIgZykEb20#Cj zoS`7QDj()oW`gvm=j;6wr@%TnfGX(336sY9?OB5g?kDwm70Ff$Qc|#671`QN#0O3T z6ojwvnW6?V2ZZu|7^yEk{{3i$S!t3tdf}JbrGE~$p~^a`1VRhNXw~V+Y`-tdyx5ya zP<%c@Lpt2Z+p7FY_=@eCE#|l!BCoB;G~;r}!KBT%dIE@Ee7`CXy*EZygo*jTCcYDovfICAip=2DF>B7Y zRSu1a$kX==6cH80BP7NU&%>l)XODk1sHp^=$;;Iw8KaeUbK{nVww=d}HP}7E3J0N; zId@Y&jkF~-i2kJ|AqZDnXIVWmP###Zq`0CV*mXW4ot#U_0s02J_3ZnMzj*QS@qfqi zq+Q*{AaS#cD|T2a9N}zBrP04}f$(nH|JRpv6 z{bT{kvjd~|QR`KM6lB9XORNKzB zhE10j;MD6J)vMwMfAT+xeL}$oFlNzeUwSd=YL|cV!W3px*F>5fFkRoTjg#f&D}1C5 z4Gmq54kEK>l$Mh#kV#>`uY5$zm&+JxX*`?n7mFetY$BVia+*^~_t=#*8A??*YaY_( zu68{$v1vYF*Kxn7eR<|(@Ea%mHIwh4fQ`vsT^Sl7Z*cFh%weUtM+ zUtLCB74S7mxpXb+K_4M^j4ZFw&|ZH8`E>Xpp8eWJ49!bRPVOt$ZkCXg(SN+Z0Tp7@j_=7yOHV-_ zb8~a;j+Z~R>73QNFZlR?n3R%aC_nB#Dv+MBC4HWE-AV)1n9m_7D=$C} zX6x4ml2|rq5<*GaN6n13<%g#{;yD)y@J{=PpoB;rlA10GOIQE=3Eu53xVAZP5fKrw+n;7SByfugN;|jPm!%5LuC!U;21o}DcGFgr zikUacN5Y7wh7>`>!EAN?G3rjAIca{QaB441Mm1ln&*6S?5#WxBt3UflpNFvAR@6`i z{>|QisZqC=*kls)2Q5e$H*b335Z-TC8d;F9N~3I6hDl!^RI1hZbL4CD!cZVO5$M|M z;0icRo*Ln|Z{I}3#D1=qQ4|)V0P^zMc61Ku*~JeV^E;f^uO(9Itkv2)8r^j)EQ*`& z7uAjtWRltS2NIc#jE%LczMh<%bO7C9%{JwYa|lI#)pa-Q8Wa`;^V? z`A+BNU`p7+`P$2eVY8t$o^I<_+Z=!qiClyj%*oC1Zti_p_<2di&7FMEZdG6!l@64k zlcBjITn&E1zi4ik+r2&5?-n}DjepdUb#!!~5itAf@VPhI3KegksIId-FF@+v-QgVd z2Uk`({&H=v!hd{*KOwBvvp*Kx4ZtR25DI>NbD(;nk@2UlQAH+zsXRtqBM8|~uU}I> zF9CbcLfwkC<}7>2CYk!}m5V}ObJgBO@&+=0g$RDj^GON`(C`*AZw3eR#-9gBWa35U zSRTXkYlgVDqHmsGz5mBez`{}-9hT|x*}{`msP%NxE5 z1oKl;ib+X7cd#F3$C({}GNRgBUre0>9*DNxMRvOmV;d;)p1Rc9%2(v zmX|`~BOqM8o@H{ypF&FVS{_fRac`equ7|3w*j7b*VotbRJj z>2Rr9mJ9?01d4j9-zF?3d`Fo1-;s-;V+aN`kS;h)X~)eTM)DjkmrUr!HKy;%13N-- zMD;_1Jtwh$KwxxgO!$ILf>4nOUE?dq9d2J=UkNGM7~uTC%{TCC?ck&fJ4sxvD*s4L z4TtQ!r=tsBUpFGg2*Q~{I2EV6|1e6lk^8RJpOA?zU)QIP(jA;7FR6%f-=T(>2%-D%r|A4$BIQ5 z%CI9PbmZhPJ|iRYii(Qwe-#D(boe>?f%|GH%|lE`s{)2vuuQ{l*=K8`Kf&_TBFB=T zAHr-43D5HVO(=XO2IBUG@oK9R3-7V=0VPI~~P-UC{7RdOOYwLIT#%#g7r~F;0Fp`g6V*&57guXR|Cu@3X6&&t= zY&YGYpm{lM_&qucKH*^29HtD50zT7OGphs7<96!OwC~3U|9}8I&4RZa(g5yu?2{)6 ztlk=mN&WFzP!PnOR<3wK0YHjCbi$W-cwHp*OP_{G`DPmQ*C-}Brl-|3SZx)Io%s3q z((=4@-6YMmIK97R2?y$28ukwiyyxIZ$o!Qlq(K;-cd3f;FJ2%Hw8UAewV&sRe{@jd?j_wGJ zQq?;7+Dd$*)dG%2j*_ERZ4|u-p;1ltPP+-KsbPhMgQX=|zP`DsGKWxl&7Zz=*c{T| z97vi{N(1_q;m%keVkSnAUuBbi>5a)?9P)RTv8oxXm;NXUgX7^T-^0ZkppRo)6jYsZ z0_N=nG7g?+cs7HqDf%OCtXmvR%aoOZQS53>*ez$#d>GqCVB1u6J>%4?O&X_AF)_F5 zm%N)-@7C7VI@<+q>bp0Ji?gZYpaQHcEU|dBD#yzWh!xxRS{D4p#V=pJ{4J0TwV$~< z7#4u$nnUtmjAJyci$jf!jIdt5R5V+3KWgosJ(`S3ON*GXGU<(>m>)ZR~R@OmQUMapUH>!W%#>2TFGF z+#EF&UpUiP9D50!eeBxQjj-ebhLV8Cgsw9X({O3g^L&3IHi*z3M5}HM>>IFAcG?VP<#JI5}^L-rsZeA9eFkH z+#N~so{EaaX;#VW;X>8G4C^U11qGPTl`y0j|%+GYX5PTHP)Z**yuJcE>-Qa2~as$pRJ5H6Bh%6Oxub??jRA1e*Ow`_uIJI>>X(bmIvzWs zlOC;sTn?L+`fGuTSB596T~CW3UnXUKho5N$nUbF?n&+^g^C4<_eT%aCRDgEjrVhZ8 zJFcx?fCaO`zu6}xBTez~&3B(!nB3gHYR7=@pz)23gq08~y+Oi4UEP#=%LHd}j|2w2 z`p%QJk!*O6OZ6@YCI-NTl35US++|S3%2YU=(Pr!DJvDW8>9=d=I^M{Yzf5=Cm903? zZ64oHmFmbuU!G~_lQuD-l(Df`zn| zfeO~wOscrjN z9nX?)HvyUMHC{pbX)#&>q_=lTcC1cj4#jqF*B7xY&$+`FzUAaE(dWVD7iM>t2XvZE z;lTP*Qr-Y?I_Q64VxF@9HzsEPe`Df9C%yymDnUlJIPGTV=$Pc+_cv#?YhMck4n;T! zBhW~8Z<2>kHN?G%`m!{#PG?c4sY_t{X!{cU$M5av2hq`J@FIo#QtPs5s{IR z(d}Xv{uh1yyl-*w;f@NuCN_Qo6lKiQ{ib{SLjF>n*Gsg`lDFn>)vso>G$=m7ExuaHrFm;V`Fzz z8Fn|AZu1%E8?q7ta2xe$O-vu_gI!%+(FC=pM0YQ44It&^yP^9*kR1^P+{rS{Ehb$+ z{)n4n5gJ)^bhlp$(6N&Q-a+AU9LY6Q57 zM#z_QsVZ|-4K6OOmeW33I^DL^l$50bGVlA9lYDa3?`JDPWCrKVD%YH}F{+|)snWGh zdn&&>JHNr&>Y|{+>237I9bUk~!I?wq(EAe@w*Urh2W45gedY>hn}db`SMUJ5`0LwS z6}JqjIZQG#GP+l&&dnsioayPk0s14It0gjH%Qb9hwqEtj^})Jrjn%|y%xRO>C$q0o z%pIRPuBT3^_}*!^HTXB66mK$sTXifKtfnw756hA$ZgvW0(LcNDCa>P23x;6`Ku@dP zsm)zQeHBT#9h*)u%k^?=Tmh29YB?D`QKFgy*|FnJ^SGQbbvznfSYt0Y2L`)Tg|@gj z-kpqBX3mP87z5EsXfG48^Hiw#HgT}91OXCsecXu&L?pHyx%ZuUfJNrs7};9W!fUNr zep>!VX0rU5(KM7@SzFEg45(l7nj*x@S`c~)==6Spht`r z$dP5=ic}pGSSO@TZD0t=P~v!bd7XAq{85%?qtA>WG`B@6?iGugM6lOx9;;YY!p$2= z8_0XK-_owovU`ZxglTC!mH|jr_f$#y-xa%&I&01R&q=)Ci zIw&?h=})dHWn7|5$31C{YOIZmilulzF<)>5l|ML3Fxx&pda zY1`SikiCl+i14vVNs`X8b-2M;aY`DgYVA6nSA+g3?9iUE_V%#(G5SBo=MS?-w6)p? zv$g#$Kb6koERt}Pg-2->k)~b;b*{8gj_)|e81_aBVP~TN6zY$$0dvx8V3HC1U|MyK z9uElX=MI3p7(goA=Yd35TAKFu%8D^OXZj)CtBGY)Wk%hiskhAwvR}XIxU@h*D5l;9 zycLl_5|ndDrew`xD^nl(%01e<_7xtU$2oa493T9x+>zdeAM*r@XGRhyxiZozZgI-F z<{jJ77977G%@@9M=!XpEDAzyO;xwmPjeAKmR+PE2NG7oau`{_3>`5P!J|_;E0K2rY zv2lHK)1Y_aFa0Z2WMt%2Ue}oNg}(B=F<6aON!0Dyev^9hDSre6eMx{K1`}fYz>a6X zLgbV`+(?=JV;6WvkTDvYZk+G^4b`Iq-{||d^!~H(AtgmuKMtTaiL)dhIu?)|SlHvdH?rM8iB$W*b%$m(yj3j z3V$q>%HM{BqDKZ9X;*8^Vd{q`RA*i&<(i7zWM@_5FaNoeLaC|>pg?q5Ug){G_2ULEJ|dsHPTR$^hVh5(wNJSQyms^NI%~U?-*JN_UY^%CTmALv z&!SBO0^G<(|4J{F{)7246kA^w+RaxL3V`8?u+7N zfrUnv`XZcn?Y<=IjY!9&bk@&p;0peJL>!U z_b;2EweH%D3{MrO0DHE7Zty$koLQrdSPb7)(-=@6NKSw&)W+X6VD9)IET^pcT9w6? zytpKd$2q=HwqCOtMjoi1AfQIKyKzubZYDE^_4G&-VJSi_9Ul_787!1QO*Y!SXVAN) z`;+nU`xB~+afF1K>e{81m4GQ)>sbg`y`MpRQD_{u9A`I=(`gqM$jZDxMASXoz{bIO zM`cz7WovqrCc$T;0pv6-cP)AW=o}RA)6?AL0aX+nwn;xfhiCN=5*7wHY9R>dgyX@? z<|CQkQZw@&bx&^FEvFc=b8;l*q_=XsJw*o6U-RD|3qLWJ*&1`j?f^i03r?>1Nu}!p zXeOh%k~pBR^o{3jWgOZ~jw@*{i$&vYsXQ)`E1f~rmQ&>h{QzYKd-a`_USEYub1#O6 zqwz!U9Z22xt6nB>n2(9bjwnL=wV{J1ENSm}Af@UoKxFu^(m{BQ2z(tKWDZytAx+B(yRe4 zEuNd9oK-Yb5J_PYSxo^~L%ik^eEI;`7Nl@uQub5_Ku6I zQJ%Zp@kvuZv>mp;T5w^>go6G?k;z$DSXA)_EwF?ywz^fjU)c?{+o>3vLnVY(6RPc0r?;>J7(idrGky#3UyD~Y@fcNJ+U<1sA+P}7 zxH`}L=BHL~qg~~u|#l685jJQm1LnTWX|0G!}I-vSisZ*Ql1)^TbI2nmO!O`!o0d_spWKHXbh-uQd{vlw@d@i3}pcMKIxB(XL zMGr@AlCUL>@Qe(y6n0w!$fnF|v_PRd4ZGm*@E3?+&*eLT;DCfzcfCu(E2e zPB)Ot11%??$Mtaxq(4PgQc{2Px9F3h$kJyfrEeM}0y~m#O{ApkBv)^_6#3*Hd7BeFnKy!#6okBqh++crbnWBgO3nwfqEZ$p zfJ25T=u`+GqbqJe)@XaUZ8{5%h$vIyYLXrCL+r)ZaKiQGe=ME?LRY$rhUiF0nVvzH zynt%pc5x`W)idO{KVGHfjj7mOk4W9|BwdnW;H+vn34v^3-(D=&8BHerchFe|v za+_{I-FN4`X_EaV3IQHTn6`FSDbonZrY`Mwr_==G3|awg$pi*%fINVcTITm?Llvzw zoQi=QMyhOqdz&S(>0=GfL49%YHZIAMH_b$m`_)Upg+FND zuMnqCu3rXZDAn3W_hLB!s@AmR8CN->OrFGeHJ770$!OBOx~k(&i)6E$d~&NW_62?c z%(_Uko&nGWKU^Gr+P%I|y(;l58H3MA$H>aMfdKO(2>P6o&zI`e0c-vEJ7AV)QnPk! zvDNEX?~(m%OSsx(BtN3gW99eQ7AiT-4TZw;W>{={8r{iy2{naxoEqJ$Hr*>eeSQ7? z=|(?m0c%6RU{P!LYQ1x-o1fRRv)I$1i&rdgaB!%aJ1BhsqF7-8fB~EJ#i+nw&(+-> zQe`Oqie5_uu>65{fHHS^w4`f73fTWz(hTbA>W3TY2vZ^I5)W5O(6C9iu&&>AWpipZ zX4p9CiSh;{F4mf3j%6CPm2(HgTwh-RZvzVD#v(gVp;^4svRuzL!-?5qB!@p6OqFXJ zKk`YC;HwJ9)%uti2{t>=mN4Mp)N)|p{fGy)*YWM%%^9gXnhy9A5p)$5yh$+KgvX%c zuc|XThKx2IUyut2cLrjUlImEH0#@BQ*+>RZH9ESx#VuPW@G(C=iECU;(hrQ)kH9no1^UUAo;6I| zcP3mKNvvOV3kwboHh3ztz#85tPZ2GEN%wwq1!$r$pxJGES-M=+g@lCMAI!8z$Hw|) zQv)#>lfiW0(q)UhG1H$$=G?YKJc@KE1cz!2$W1#Rg{&k=%DH<)OfP@(>$mca3JK8% zESZ4h3%QI*U%9CiUnM+~p%-Zwn}d+}B@Y%gI{9O=-ieah$&pez>lFVN^gT+-+cP-# z_nEf3+lwSkPG`Kj!Nrw;IV{vE#FR3SI6!$&-|OFN^xKNPS(63ucBu z#A0uM8s=cGGfP;*ZfEu}K^KsVrmMyGnrue|-78uOZiIsS%)K1Wq^!4^>;d0$yzo>) zN-74YdK^lq4V*2k*lvPUq+K8G$E9M>yjEFro7Z9qIDv6kH$FN`TYR=CmK|_647=T) zmQZSpn=p;T%gc+4GVG1$xHt+blm81o7(h%Z^?9dnAbOlkJ()I}EjV0sxk zL$!%{I}yA8LbJ4NKg5IFKXu&y`z@o$#T#3pXMp_w>)QR9z!U`LoHT5_oTSDEonGTt z{gTuQ>J#A9iYngc%KTsD5f+V9>$C|Y=vC!E@sQ-LV#khx0%0?=$MYQs7FK2}ceSPJ z!NXDc&BL9gEvv;SEUBxAyQpc0waIW`kHmp`HW9~W0ig3uuFjT|uv+G~x-3#KVT(oh zvRl{G9JLV*rN#C=JD&#;05n(p%TI~ ztthrrZdz6b7WlYM?G6fB#FJHWf5E6T4*MsKr`EicG~FEo0b@Y7+bZyrU(Lx-TCK{c zuadGmzK4j2mwZYpn!rQuLpr-m%9h=a$9%x@r5+q2;mN})mIu(RB)P;xLK7p5S=R@Y za8h&yg&UZ{s3`V!R`}*on9uq5_N_XooTzS>>IYXmN9)55+_fIgM+_~kz<7s#Du)J& z2Am%*q-lhSo!&7xw|Aj>)4tmwZE$jHM{`sMF5nc@fxKM!6-{#>ojH#ac;1s29>*}#2X=d9m1YVzrzu=tQ0do#A0Ug-Ug z5<8b6P8$6LHeDlI_Q1dvW(-ikus^XsWTsW~654Ga_e2(COgTOttEfW53>qJg*{aah zZLhB@{$_Lk8}_u1Vc+ ztxu+l_x*`@(p=Zyzhl|1gNN~TJh`YhihTozmCZqwl^?I42z(O(2A)hZwd+2 zLab~p6|bh4C#S0-3M#tLYe@q3hBs30h= zLG{{@I%qwxo)hYipJm~bOYQNlXvSjeh^N<7gZf=w2LfJPDxPbUmRgkoJODhoKzrV5 z!|`PGS}fg;C##}BG!bYi#|=YkYh+uOJT|64=ErKG4zFN$ePX5ph{``%Gc{%%vqw{> z1J%QJEBEk$7z7%vnyl-D4bn6$L7g2k9E*Q|pBI9PiZ6ZK(>qrhER5+cba$Z_8dsJg zpe7G4z}zlXhiiXC5s$K{SmpI@%O*=!(z3TkLPw`}@Y)NWWLs5>jg94UJEz7Jxc>-5 zwbQ%Fyi*5LI8-gPfo3|Abwf4(kH0B%!Jjp~(Z2&so4$+PeZwU<|H(fC#&@hN<#M)T ztvhP1lBd|3K>8u!*1L7`L0ZB1V56c9WyvFl&u4K106t6QE)4)rU-HHb3Be*kf4DX8 zpRM%^!O`!3^_o}Bz2a^MGAq1mXjq$hKB>8~;LpO-Y)TSF68$xeY}@2VgNggUM`gdh0#W4+T^ZCLPHiysTY>NGa{@;XF#|-oZgcwwC6VM4!y-1QnC=lTL9A zoKYHIz^|-w*pkH{TQbg%YMS5jHA6X#{kn+i|&;l13vPu-DNIB*s17+(rr z>Ab>*X?8a6p!(%`^$GfDw;s%1Nb@;K5uDWijt7(X!oN1R zytL&XB=EVy4IFk{wQ>KeC%P*kv3xcx07PjBN1B$k&!zwhxxHvLc=L(Xo}Ui@zk$0tVglpEaAVRw?E#} z^0*wXPw9HovqCN6tANb{ow8hLS1caH>jbn6!rTae+%D0e=&}BOxZ0A_Z7GBg<8iTo zxbg8`5u*{Saki2R*PO_v)qp10{?R+w)Bmf;^cBpUxh1+ca1aJXg(34s)ZT^0ukF<}IO7X3 z+=GLUNvB&ofSRJc!;_{l+w6kBh)7OTLh0PmJP+96Pd^k4mVhZu3#}eo`w6fNV8u6x zm4AzcYA_ZJlm|RjxC^LT*`2CToHh`f@1JE$vA4fDb3Pc;Afu&uFVYh0A&X3fmm$#gr;jIS~6mPLq@G+=0pkqq`Gp=ZZiM>`Sjfd1LKk97;3#BtJyI z!F(tCCGa~s9W6kqxE4Y+6SxNLJ0DQyiiXi7OcpDDbY%umjgHRjBj0K8t929wb+$58 zogYIs2@E~bA6PyJ0QK^!f>GHGeS5lURzBuQmpMMZ-|=084+!eKy`U&ic1-!1FD&%t zNFhQ<>u2&jJY(Nfw!Oua{fF-;@kuqA6RE?eU1Dpwg1LvP6@X5>_f)*5e;T6#Lux!o zc+gY^6odH(!P_k1pe8bz_^w)a#gB)W_RZJ5EkV ziSnJ+AE!7#sXUYhf=Pw%cYNFV2h-U!Q9kv_@e7a}Qvvi`br^W0F;T|kGbPTeur3mC zeqLU5N($;P+jeMRmqGOJVwk3d*@y}iZwh#OdFj#J&PQ~jfehpE z{n>^l``7p3M2Lu(7CVuzVWRk5Wa***WdSt6bHPXlwV99t>1X}VzhSJnOZym~(E?_5 zC~dYzr=r#jgIG;Z9Nli1Z}vJE`=g%VOn*#lt;--4m1S9Krc*V($9nuI($x|p-X{PW z@VM;%5GsT{T}60WG8CY)@4(h^`e*BG%!w5=pBu|kQKRfHqEiCtsJm;kJwPnaLn^}Y zl^xB3?8rN!YzvNl06exUJHAjpoc>?FWyo=kbJq2}IbKf_lK`q&)$t-o2g6R5e!IP> zb!~S3Hi6RWWpoa@xy{!r)Knjf}MzVOR&nD2NaVWir0rr-B}P!cNZliUBf zANX$y81SchRYpHhhq6DNvf(QUv_NyR1VP~D9OrL1>AN@ypb9_iNyNct0$Zsp;-9VL z_q>%#=>c*{FZi$wN1xepp`unp?R_^}yRwy`e`$4m>N`==UvKq4;Hm#ETKq|t)-vH9 z`QS>W)e1Zz*DTip#O5BH?t>%7WPfLPJ|^9X@LH@>7m2f#KJH!Iv;&KJp`8YX`q%TO zJGN76Z#zF&aw}Qw7ZTFzLK$|=&+oem#G2?B7I+x=Es82BBWZkaW%*=SOD}2&0qKyX zvWH0E={Ud~)3CnMRXCMxa)b9z=nGY|rGO4X$YC?EuWAYbbV6y_y8wJ0y{A;e{y4VJhuDJS6>+k$d>JCZ6|Jvn z2mnIyQFFRL0t?8~R&J)SCDf1s?s@4o7+y}!tx0HZXQYYjBGmbJ?Yi1i96AV-4Dca= zOl;NOCHF{-?C*5`0><{+7$CnT1$6f(iFa1Wc)fjTgj3MACps3j(4T4Go;LHKY0H2*O2xN((@W1dmgA-~kFCMU{sq0JEii zl&^aJ`W&I9wKa*;{w-iAh7)tWjO~37W0npCllxew3ZGj&_+(WG zIGk*B8cLd=uGMBrzh#f=s|I9Z!oLpSMzX8Mw0v40wx!xt<4OWZs;DE4Kihy_s zgrfLTWvSp$_;t~PLqoqtk@0;U_k0-%#L0KZi&7uYSP^o*9WFGpc-@2l3n*>k12?o( z*cMJEkPd{rqksJP1I+NwLNmvg{LkbpEReJ-AjR9~^pJdKqbnMet@<%Z=6rk94^YhD zmNzyiV5lp-I-%7rOD77-H_&cfmL23oEH^y(1PL=(7@>sxn&7v-nU*<7p#d~MX%%3w zaaDfc!APsAswPwK%E1!}!5YZFeN(O*hZp|iTem>;}jefRRCy!T{bMP zV@5Uvo~W^uGQUl#nH>IpPDk^O$?K1YwS)e+OX9YsfkQw8>2(I84}cvJY+D~*LGon` zS0Jc2*K1MsE-t`xB|*T01(k-~7+Yi~z$;wNsmhg30NsL~Mt^*K95$mM_v~Ba_;i*q zqRCKl@1#rpPqUS`PqsFIZ-xN@ByG$2Vl2PQfM)Ujs>KxyUS3&&$$T|3pKGz4DQ&~2 zc(2-eJ=}Wrg+5c6Oo)hx2nZO28wu&|G*D6$326ic>FyW|T1C1;B&4OJ8A3V*De3Nx zVTj?o$NhibbKdiv<8^Uu*f49>to5wtx$j>+IP-{=@$qq57Z(=}D#b2q+|v0w7>m~@ z9E{z;W-6-L$>zzI8Z&S?da;AkB_Gp7W^8gd#UyGBW-I36Q+LD zb8WgTZT-`PoG~agP*#85^L=$NHa|?rM#%UFz1TT2GAO_C)Y8~o9h<*)Ch|vzvpg1y zmVNZ7*tCZZBp*bVFPnJ1U*7GsE-N-!zp?1`67*#MFfzWU?9c>BIBsiq_rlhfM(R^h z80h!?KhXk~p6H;Z`sGYY(Lu_Tt6$x{%j4lZaq{b{?d->l z{=<}8{VzPVwSTpY*4)gmI1f|h02@JtoLkjyw|E7r)}vxIzv`NZ?X4jcGAWWfH|_4b z^ElN-3zW`l!*|cTPnSnCxkaV|2~gsuX}IlAGQ!L+BgI*<^Vt|Jnl&0b-eegH|6fn=4O5Sp*vnjdoQ-8>Op1I zTkYlmINq~a_UVKKnpD&y2b7+R16aNI`1#seTWxCrG*#KdEbSgVJ<;qsq!)PoG!zmlf?+^>}}$IAqA{5?38tKQB7>Fhr=)Ge{0y zwLhp+u|Jq9u4p|0z7SmhRETsa+G&bx%0D{^?nxx&D6gv8MN=m)o_=8yn1sLx%>Dwh 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 z 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 Material Properties dialog: Front material tab + +\image html material_back.png +
Set Material Properties dialog: Back material tab
+ +This functionality is available in both OCC and VTK viewers. + +User can changed the following material properties + +- ambient color and coefficient +- diffuse color and coefficient +- specular color and coefficient +- emission color and coefficient (available only in OCC viewer) +- shininess + +With help of Front material and Back material tabs of +Set Material Properties dialog it is possible to set front and +back materials of the selected shape(s). To make Back material +tab visible it is needed to check Enable back material check +box. If back material is not defined, front material specified for the +selected shape(s) is used as both front and back materials. + +All currently available materials are shown in the left-side list box +of the Set Material Properties dialog. + +- [Current] item in the list corresponds to + the front/back (depending on what tab is currently active) material + currently used for the selected shape(s) +- [Default] item in the list corresponds to the front/back material + specified in Geometry module preferences +- Global materials are shown in blue color in the list +- User materials are shown in black color in the list + + +Examples: + +\image html material_OCC.png +
Different materials in OCC viewer
+ +\image html material_VTK.png +
Different materials in VTK viewer
+ +*/ + diff --git a/doc/salome/gui/GEOM/input/viewing_geom_obj.doc b/doc/salome/gui/GEOM/input/viewing_geom_obj.doc index 4a43a25df..9ff681259 100644 --- a/doc/salome/gui/GEOM/input/viewing_geom_obj.doc +++ b/doc/salome/gui/GEOM/input/viewing_geom_obj.doc @@ -29,6 +29,8 @@ transparency of geometrical objects. isolines displayed within a shape.
  • \subpage deflection_page "Deflection" - allows to change the deflection coefficient of a shape.
  • +
  • \subpage material_page "Material" - allows to change the +material properties of a shape.
  • \subpage point_marker_page "Point Marker" - allows to change the representation of geometrical vertices.
  • Auto color / Disable auto color - activates the auto color diff --git a/resources/SalomeApp.xml.in b/resources/SalomeApp.xml.in index dc59f51f5..8ea7476e7 100644 --- a/resources/SalomeApp.xml.in +++ b/resources/SalomeApp.xml.in @@ -43,6 +43,7 @@ + @@ -54,6 +55,8 @@ + + diff --git a/src/DisplayGUI/DisplayGUI.cxx b/src/DisplayGUI/DisplayGUI.cxx index a0d6812ce..c7f5df89c 100644 --- a/src/DisplayGUI/DisplayGUI.cxx +++ b/src/DisplayGUI/DisplayGUI.cxx @@ -27,6 +27,7 @@ #include "DisplayGUI.h" #include #include "GeometryGUI_Operations.h" +#include #include #include #include @@ -91,11 +92,28 @@ bool DisplayGUI::OnGUIEvent(int theCommandID, SUIT_Desktop* parent) SALOME_ListIO selected; Sel->selectedObjects( selected ); + QString aDispModeName; + int aDispMode; + if ( theCommandID == GEOMOp::OpDisplayMode ) + aDispMode = GetDisplayMode(); + switch ( theCommandID ) { - case GEOMOp::OpDisplayMode: // MENU VIEW - DISPLAY MODE - WIREFRAME/SHADING - InvertDisplayMode(); - getGeometryGUI()->action( GEOMOp::OpDisplayMode )->setText - ( GetDisplayMode() == 1 ? tr( "GEOM_MEN_WIREFRAME" ) : tr("GEOM_MEN_SHADING") ); + case GEOMOp::OpDisplayMode: // MENU VIEW - DISPLAY MODE - WIREFRAME/SHADING/SHADING WITH EDGES + //InvertDisplayMode(); + switch ( aDispMode) { + case 0: + aDispModeName = tr( "GEOM_MEN_WIREFRAME" ); + break; + case 1: + aDispModeName = tr("GEOM_MEN_SHADING"); + break; + case 2: + aDispModeName = tr("GEOM_MEN_SHADING_WITH_EDGES"); + break; + default: + break; + } + getGeometryGUI()->action( GEOMOp::OpDisplayMode )->setText( aDispModeName ); getGeometryGUI()->menuMgr()->update(); break; case GEOMOp::OpShowAll: // MENU VIEW - SHOW ALL @@ -128,11 +146,14 @@ bool DisplayGUI::OnGUIEvent(int theCommandID, SUIT_Desktop* parent) case GEOMOp::OpShading: // POPUP MENU - DISPLAY MODE - SHADING ChangeDisplayMode( 1 ); break; + case GEOMOp::OpShadingWithEdges: // POPUP MENU - DISPLAY MODE - SHADING WITH EDGES + ChangeDisplayMode( 2 ); + break; case GEOMOp::OpTexture: // POPUP MENU - DISPLAY MODE - TEXTURE ChangeDisplayMode( 3 ); break; - case GEOMOp::OpVectors: // POPUP MENU - DISPLAY MODE - SHOW EDGE DIRECTION - ChangeDisplayMode( 2 ); + case GEOMOp::OpVectors: // POPUP MENU - DISPLAY MODE - SHOW EDGE DIRECTION + ChangeDisplayMode( 4 ); break; default: app->putInfo(tr("GEOM_PRP_COMMAND").arg(theCommandID)); @@ -350,23 +371,42 @@ void DisplayGUI::SetDisplayMode( const int mode, SUIT_ViewWindow* viewWindow ) else if ( viewWindow->getViewManager()->getType() == OCCViewer_Viewer::Type() ) { OCCViewer_Viewer* v3d = ((OCCViewer_ViewManager*)(viewWindow->getViewManager()))->getOCCViewer(); Handle(AIS_InteractiveContext) ic = v3d->getAISContext(); - AIS_DisplayMode newmode = (mode == 1 ? AIS_Shaded : AIS_WireFrame); + + AIS_DisplayMode newmode; + switch (mode) { + case 0: + newmode = AIS_WireFrame; + break; + case 1: + newmode = AIS_Shaded; + break; + case 2: + newmode = AIS_DisplayMode( GEOM_AISShape::ShadingWithEdges ); + break; + case 3: + newmode = AIS_DisplayMode( GEOM_AISShape::TexturedShape ); + break; + default: + break; + } + AIS_ListOfInteractive List; ic->DisplayedObjects( List ); AIS_ListOfInteractive List1; ic->ObjectsInCollector( List1 ); List.Append( List1 ); - + AIS_ListIteratorOfListOfInteractive ite( List ); while( ite.More() ) { if( ite.Value()->IsInstance( STANDARD_TYPE(GEOM_AISShape) ) ) { - Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast( ite.Value() ); - ic->SetDisplayMode( aSh, Standard_Integer( newmode ),true ); + Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast( ite.Value() ); + ic->SetDisplayMode( aSh, Standard_Integer( newmode ),true ); } ite.Next(); } - + ic->SetDisplayMode( newmode, Standard_False ); + GeometryGUI::Modified(); } } @@ -386,9 +426,8 @@ int DisplayGUI::GetDisplayMode( SUIT_ViewWindow* viewWindow ) } else if ( viewWindow->getViewManager()->getType() == OCCViewer_Viewer::Type() ) { OCCViewer_Viewer* v3d = ((OCCViewer_ViewManager*)(viewWindow->getViewManager()))->getOCCViewer(); - Handle(AIS_InteractiveContext) ic = v3d->getAISContext(); - AIS_DisplayMode mode = (AIS_DisplayMode)ic->DisplayMode(); - dispMode = (mode == AIS_WireFrame ? 0 : 1 ); + Handle(AIS_InteractiveContext) ic = v3d->getAISContext(); + dispMode = ic->DisplayMode(); } return dispMode; } @@ -456,7 +495,7 @@ int DisplayGUI::GetVectorMode( SUIT_ViewWindow* viewWindow ) //===================================================================================== // function : DisplayGUI::InvertDisplayMode() -// purpose : Invert display mode ( shadin <-> wireframe ) for the viewer +// purpose : Invert display mode ( shading <-> wireframe ) for the viewer // (current viewer if = 0 ) //===================================================================================== void DisplayGUI::InvertDisplayMode( SUIT_ViewWindow* viewWindow ) @@ -503,11 +542,13 @@ void DisplayGUI::ChangeDisplayMode( const int mode, SUIT_ViewWindow* viewWindow SVTK_Prs* vtkPrs = stvkViewer ? dynamic_cast( stvkViewer->CreatePrs( It.Value()->getEntry() ) ) : 0; if ( vtkPrs && !vtkPrs->IsNull() ) { - if ( mode == 0 ) + if (mode == 0 ) aView->ChangeRepresentationToWireframe( vtkPrs->GetObjects() ); - else if ( mode == 1 ) + else if ( mode == 1 ) aView->ChangeRepresentationToSurface( vtkPrs->GetObjects() ); - else if ( mode == 2 ) { + else if ( mode == 2 ) + aView->ChangeRepresentationToSurfaceWithEdges( vtkPrs->GetObjects() ); + else if ( mode == 4 ) { vtkActorCollection* anActors = vtkPrs->GetObjects(); anActors->InitTraversal(); while (vtkActor* anAct = anActors->GetNextActor()) { @@ -516,12 +557,12 @@ void DisplayGUI::ChangeDisplayMode( const int mode, SUIT_ViewWindow* viewWindow aGeomActor->SetVectorMode(vectorMode); } } - if(mode == 0 || mode == 1) { - aStudy->setObjectProperty(mgrId,It.Value()->getEntry(),DISPLAY_MODE_PROP, mode); - } - else if (mode == 3) { - aStudy->setObjectProperty(mgrId, It.Value()->getEntry(),VECTOR_MODE_PROP , vectorMode); - } + if(mode == 0 || mode == 1 || mode == 2) { + aStudy->setObjectProperty(mgrId,It.Value()->getEntry(),DISPLAY_MODE_PROP, mode); + } + else if (mode == 4) { + aStudy->setObjectProperty(mgrId, It.Value()->getEntry(),VECTOR_MODE_PROP, vectorMode); + } } } aView->Repaint(); @@ -543,14 +584,16 @@ void DisplayGUI::ChangeDisplayMode( const int mode, SUIT_ViewWindow* viewWindow AIS_ListOfInteractive shapes; occPrs->GetObjects( shapes ); AIS_ListIteratorOfListOfInteractive interIter( shapes ); for ( ; interIter.More(); interIter.Next() ) { - if ( mode == 0 ) + if ( mode == 0 ) ic->SetDisplayMode( interIter.Value(), AIS_WireFrame, false ); - else if ( mode == 1 ) + else if ( mode == 1 ) ic->SetDisplayMode( interIter.Value(), AIS_Shaded, false ); - else if ( mode == 3 ) + else if ( mode == 2 ) + ic->SetDisplayMode( interIter.Value(), GEOM_AISShape::ShadingWithEdges, false ); + else if ( mode == 3 ) ic->SetDisplayMode( interIter.Value(), AIS_ExactHLR, false ); - else if (mode == 2 ) { - Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast( interIter.Value() ); + else if (mode == 4 ) { + Handle(GEOM_AISShape) aSh = Handle(GEOM_AISShape)::DownCast( interIter.Value() ); if ( !aSh.IsNull() ) { vectorMode = !aSh->isShowVectors(); aSh->SetDisplayVectors(vectorMode); @@ -558,11 +601,12 @@ void DisplayGUI::ChangeDisplayMode( const int mode, SUIT_ViewWindow* viewWindow } } } - if(mode == 0 || mode == 1) { - aStudy->setObjectProperty(mgrId, It.Value()->getEntry(),DISPLAY_MODE_PROP, mode); - } else if (mode == 2) { - aStudy->setObjectProperty(mgrId, It.Value()->getEntry(),VECTOR_MODE_PROP, vectorMode); - } + if(mode == 0 || mode == 1 || mode == 2 || mode == 3) { + aStudy->setObjectProperty(mgrId, It.Value()->getEntry(),DISPLAY_MODE_PROP, mode); + } + else if (mode == 4) { + aStudy->setObjectProperty(mgrId, It.Value()->getEntry(),VECTOR_MODE_PROP, vectorMode); + } } } ic->UpdateCurrentViewer(); diff --git a/src/GEOMGUI/GEOMGUI_Selection.cxx b/src/GEOMGUI/GEOMGUI_Selection.cxx index ef94bfc52..ca089eb23 100644 --- a/src/GEOMGUI/GEOMGUI_Selection.cxx +++ b/src/GEOMGUI/GEOMGUI_Selection.cxx @@ -28,6 +28,8 @@ #include "GeometryGUI.h" #include "GEOM_Displayer.h" +#include + #include #include @@ -66,6 +68,10 @@ str = QString( "Wireframe" ); \ else if ( dm == AIS_Shaded ) \ str = QString( "Shading" ); \ + else if ( dm == GEOM_AISShape::ShadingWithEdges ) \ + str = QString( "ShadingWithEdges" ); \ + else if ( dm == GEOM_AISShape::TexturedShape ) \ + str = QString( "Texture" ); \ else \ str = QString(); } @@ -74,6 +80,8 @@ str = QString( "Wireframe" ); \ else if ( dm == 1 ) \ str = QString( "Shading" ); \ + else if ( dm == 3 ) \ + str = QString( "ShadingWithEdges" ); \ else \ str = QString(); } diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx index ca2b6c92f..40b98f034 100644 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -27,6 +27,7 @@ #include "GeometryGUI.h" +#include #include #include #include @@ -41,6 +42,8 @@ #include #include +#include + #include #include #include @@ -78,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -810,6 +814,11 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs ) anAspect->SetColor( aColor ); AISShape->Attributes()->SetWireAspect( anAspect ); + // Set color for edges in shading + col = aResMgr->colorValue( "Geometry", "edges_in_shading_color", QColor( 255, 255, 0 ) ); + aColor = SalomeApp_Tools::color( col ); + AISShape->SetEdgesInShadingColor( aColor ); + // bug [SALOME platform 0019868] // Set deviation angle. Default one is 12 degrees (Prs3d_Drawer.cxx:18) //AISShape->SetOwnDeviationAngle( 10*PI/180 ); @@ -934,6 +943,68 @@ void GEOM_Displayer::Update( SALOME_OCCPrs* prs ) } } } + + // get material properties, set material + Material_Model* aModelF = 0; + Material_Model* aModelB = 0; + if ( useStudy ) { + // Get front material property from study and construct front material model + QString aMaterialF = aPropMap.value(FRONT_MATERIAL_PROP).toString(); + QStringList aProps = aMaterialF.split(DIGIT_SEPARATOR); + aModelF = Material_Model::getMaterialModel( aProps ); + + // Get back material property from study and construct back material model + QString aMaterialB = aPropMap.value(BACK_MATERIAL_PROP).toString(); + if ( !aMaterialB.isEmpty() ) { + QStringList aPropsB = aMaterialB.split(DIGIT_SEPARATOR); + aModelB = Material_Model::getMaterialModel( aPropsB ); + } + else + aModelB = aModelF; + + } else { + // Get front material property from study and construct front material model + aModelF = new Material_Model(); + aModelF->fromResources( aResMgr, "Geometry", true ); + + // Get back material property from study and construct back material model + aModelB = new Material_Model(); + aModelB->fromResources( aResMgr, "Geometry", false ); + } + + // Set front material property + QString aMaterialPropF = aModelF->getMaterialProperty(); + aStudy->setObjectProperty( aMgrId, anIO->getEntry(), FRONT_MATERIAL_PROP, aMaterialPropF ); + + // Set back material property + QString aMaterialPropB = aModelB->getMaterialProperty(); + aStudy->setObjectProperty( aMgrId, anIO->getEntry(), BACK_MATERIAL_PROP, aMaterialPropB ); + + // Get front material properties from the model + Graphic3d_MaterialAspect aMatF = aModelF->getMaterialOCCAspect(); + + // Get back material properties from the model + Graphic3d_MaterialAspect aMatB = aModelB->getMaterialOCCAspect(); + + printf(">> GEOM_Displayer::Update() : SetMaterial\n"); + // Set front material for the selected shape + AISShape->SetCurrentFacingModel(Aspect_TOFM_FRONT_SIDE); + AISShape->SetMaterial(aMatF); + + // Set back material for the selected shape + AISShape->SetCurrentFacingModel(Aspect_TOFM_BACK_SIDE); + AISShape->SetMaterial(aMatB); + + // Return to the default facing mode + AISShape->SetCurrentFacingModel(Aspect_TOFM_BOTH_SIDE); + + // Release memory + if ( aModelF ) + delete aModelF; + if ( aModelB ) + delete aModelB; + + // AISShape->SetName(???); ??? necessary to set name ??? occPrs->AddObject( AISShape ); @@ -993,6 +1064,11 @@ void GEOM_Displayer::Update( SALOME_VTKPrs* prs ) vtkActorCollection* theActors = 0; + QString anEntry; + if(!myIO.IsNull()) { + anEntry = myIO->getEntry(); + } + if ( myType == GEOM_MARKER && myShape.ShapeType() == TopAbs_FACE ) { //myToActivate = false; // ouv: commented to make the trihedron pickable (see IPAL18657) GEOM_VTKTrihedron* aTrh = GEOM_VTKTrihedron::New(); @@ -1021,10 +1097,8 @@ void GEOM_Displayer::Update( SALOME_VTKPrs* prs ) else { PropMap aDefPropMap = getDefaultPropertyMap(SVTK_Viewer::Type()); - QString anEntry; if(!myIO.IsNull()) { aMgrId = getViewManagerId(myViewFrame); - anEntry = myIO->getEntry(); } useStudy = !anEntry.isEmpty() && aMgrId != -1; @@ -1083,6 +1157,14 @@ void GEOM_Displayer::Update( SALOME_VTKPrs* prs ) aGeomGActor->SetShadingProperty( aProp ); aGeomGActor->SetWireframeProperty( aProp ); } + + // Set color for edges in shading + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + if(aResMgr) { + QColor c = aResMgr->colorValue( "Geometry", "edges_in_shading_color", QColor( 255, 255, 0 ) ); + aGeomGActor->SetEdgesInShadingColor( c.red()/255., c.green()/255., c.blue()/255. ); + } + int aIsos[2]= { 1, 1 }; if(useStudy) { QString anIsos = aPropMap.value(ISOS_PROP).toString(); @@ -1091,9 +1173,61 @@ void GEOM_Displayer::Update( SALOME_VTKPrs* prs ) aGeomGActor->SetNbIsos(aIsos); aGeomGActor->SetOpacity(1.0 - aPropMap.value(TRANSPARENCY_PROP).toDouble()); aGeomGActor->SetVectorMode(aPropMap.value(VECTOR_MODE_PROP).toInt()); - aGeomGActor->setDisplayMode(aPropMap.value(DISPLAY_MODE_PROP).toInt()); + int aDispModeId = aPropMap.value(DISPLAY_MODE_PROP).toInt(); + // Specially processing of 'Shading with edges' mode from preferences, + // because there is the following enum in VTK viewer: + // Points - 0, Wireframe - 1, Surface - 2, Insideframe - 3, SurfaceWithEdges - 4 + // (see VTKViewer::Representation enum) and the following enum in GEOM_Actor: + // eWireframe - 0, eShading - 1, eShadingWithEdges - 3 + if ( aDispModeId == 2 ) + // this is 'Shading with edges' mode => do the correct mapping to EDisplayMode + // enum in GEOM_Actor (and further to VTKViewer::Representation enum) + aDispModeId++; + aGeomGActor->setDisplayMode(aDispModeId); aGeomGActor->SetDeflection(aPropMap.value(DEFLECTION_COEFF_PROP).toDouble()); + // Get front material property of the object stored in the study + QString aMaterialF = aPropMap.value(FRONT_MATERIAL_PROP).toString(); + QStringList aPropsF = aMaterialF.split(DIGIT_SEPARATOR); + // Create front material model + Material_Model* aModelF = Material_Model::getMaterialModel( aPropsF ); + // Set front material properties for the object + QString aMaterialPropF = aModelF->getMaterialProperty(); + aStudy->setObjectProperty( aMgrId, anEntry, FRONT_MATERIAL_PROP, aMaterialPropF ); + // Get material properties from the front model + vtkProperty* aMatPropF = aModelF->getMaterialVTKProperty(); + + // Get back material property of the object stored in the study + QString aMaterialB = aPropMap.value(BACK_MATERIAL_PROP).toString(); + if ( !aMaterialB.isEmpty() ) { + QStringList aPropsB = aMaterialB.split(DIGIT_SEPARATOR); + // Create back material model + Material_Model* aModelB = Material_Model::getMaterialModel( aPropsB ); + // Set back material properties for the object + QString aMaterialPropB = aModelB->getMaterialProperty(); + aStudy->setObjectProperty( aMgrId, anEntry, BACK_MATERIAL_PROP, aMaterialPropB ); + // Get material properties from the back model + vtkProperty* aMatPropB = aModelB->getMaterialVTKProperty(); + + // Set front and back materials for the selected shape + std::vector aProps; + aProps.push_back(aMatPropF); + aProps.push_back(aMatPropB); + aGeomGActor->SetMaterial(aProps); + + // Release memory + delete aModelB; + } + else { + // Set the same front and back materials for the selected shape + std::vector aProps; + aProps.push_back(aMatPropF); + aGeomGActor->SetMaterial(aProps); + } + + // Release memory + delete aModelF; + vtkFloatingPointType aColor[3] = {1.,0.,0.}; if(aPropMap.contains(COLOR_PROP)) { QColor c = aPropMap.value(COLOR_PROP).value(); @@ -1126,6 +1260,36 @@ void GEOM_Displayer::Update( SALOME_VTKPrs* prs ) } aGeomGActor->SetColor(aColor[0],aColor[1],aColor[2]); } + else { + SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr(); + if ( aResMgr ) { + // Create front material model + Material_Model aModelF; + // Get front material name from resources + aModelF.fromResources( aResMgr, "Geometry", true ); + // Set front material properties for the object + QString aMaterialPropF = aModelF.getMaterialProperty(); + aStudy->setObjectProperty( aMgrId, anEntry, FRONT_MATERIAL_PROP, aMaterialPropF ); + // Get material properties from the front model + vtkProperty* aMatPropF = aModelF.getMaterialVTKProperty(); + + // Create back material model + Material_Model aModelB; + // Get back material name from resources + aModelB.fromResources( aResMgr, "Geometry", false ); + // Set back material properties for the object + QString aMaterialPropB = aModelB.getMaterialProperty(); + aStudy->setObjectProperty( aMgrId, anEntry, BACK_MATERIAL_PROP, aMaterialPropB ); + // Get material properties from the back model + vtkProperty* aMatPropB = aModelB.getMaterialVTKProperty(); + + // Set material for the selected shape + std::vector aProps; + aProps.push_back(aMatPropF); + aProps.push_back(aMatPropB); + aGeomGActor->SetMaterial(aProps); + } + } } if ( myToActivate ) @@ -1791,6 +1955,19 @@ PropMap GEOM_Displayer::getDefaultPropertyMap(const QString& viewer_type) { aDefaultMap.insert( DEFLECTION_COEFF_PROP , aDC); + //8. Material + // Front material + Material_Model aModelF; + aModelF.fromResources( aResMgr, "Geometry", true ); + QString aMaterialF = aModelF.getMaterialProperty(); + aDefaultMap.insert( FRONT_MATERIAL_PROP , aMaterialF ); + + // Back material + Material_Model aModelB; + aModelB.fromResources( aResMgr, "Geometry", false ); + QString aMaterialB = aModelB.getMaterialProperty(); + aDefaultMap.insert( BACK_MATERIAL_PROP , aMaterialB ); + return aDefaultMap; } @@ -1820,6 +1997,14 @@ bool GEOM_Displayer::MergePropertyMaps(PropMap& theOrigin, PropMap& theDefault) theOrigin.insert(DEFLECTION_COEFF_PROP, theDefault.value(DEFLECTION_COEFF_PROP)); nbInserted++; } + if(!theOrigin.contains(FRONT_MATERIAL_PROP)) { + theOrigin.insert(FRONT_MATERIAL_PROP, theDefault.value(FRONT_MATERIAL_PROP)); + nbInserted++; + } + if(!theOrigin.contains(BACK_MATERIAL_PROP)) { + theOrigin.insert(BACK_MATERIAL_PROP, theDefault.value(BACK_MATERIAL_PROP)); + nbInserted++; + } return (nbInserted > 0); } diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index 09fa417d3..da7b2e0f8 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -945,6 +945,10 @@ Please, select face, shell or solid and try again GEOM_MEN_SHADING Shading + + GEOM_MEN_SHADING_WITH_EDGES + Shading With Edges + GEOM_MEN_SKETCHER_X Enter a Length to Set X @@ -2561,6 +2565,10 @@ Please, select face, shell or solid and try again MEN_POP_SHADING Shading + + MEN_POP_SHADING_WITH_EDGES + Shading With Edges + MEN_POP_TEXTURE Texture @@ -2637,6 +2645,10 @@ Please, select face, shell or solid and try again MEN_SHADING Shading + + MEN_SHADING_WITH_EDGES + Shading With Edges + MEN_SHADING_COLOR Shading Color @@ -2753,6 +2765,10 @@ Please, select face, shell or solid and try again MEN_POP_POINT_MARKER Point Marker + + MEN_POP_MATERIAL_PROPERTIES + Material Properties + NAME_LBL Name: @@ -2857,6 +2873,10 @@ Please, select face, shell or solid and try again PREF_SHADING_COLOR Default shading color + + PREF_EDGES_IN_SHADING + Edges in shading + PREF_STEP_VALUE Step value for spin boxes @@ -2877,6 +2897,14 @@ Please, select face, shell or solid and try again PREF_WIREFRAME_COLOR Default wireframe color + + PREF_FRONT_MATERIAL + Default front material + + + PREF_BACK_MATERIAL + Default back material + PROCESS_SHAPE_NEW_OBJ_NAME ProcessShape @@ -3229,6 +3257,10 @@ Please, select face, shell or solid and try again STB_POP_SHADING Shading + + STB_POP_SHADING_WITH_EDGES + Shading With Edges + STB_POP_SETTEXTURE Add a texture @@ -3369,6 +3401,10 @@ Please, select face, shell or solid and try again STB_POP_POINT_MARKER Set Point Marker + + STB_POP_MATERIAL_PROPERTIES + Set Material Properties + SUPPRESS_RESULT Suppress Result @@ -3781,6 +3817,10 @@ Please, select face, shell or solid and try again TOP_POP_SHADING Shading + + TOP_POP_SHADING_WITH_EDGES + Shading With Edges + TOP_POP_SETTEXTURE Texture @@ -3901,6 +3941,10 @@ Please, select face, shell or solid and try again TOP_POP_POINT_MARKER Point Marker + + TOP_POP_MATERIAL_PROPERTIES + Material Properties + WRN_NOT_IMPLEMENTED Sorry, this functionality is not yet implemented @@ -5005,6 +5049,61 @@ Would you like to continue? Load Texture + + GEOMToolsGUI_MaterialPropertiesDlg + + MATERIAL_PROPERTIES_TLT + Set Material Properties + + + MATERIAL_BACK_CHK + Enable back material + + + AMBIENT_GRP + Ambient + + + DIFFUSE_GRP + Diffuse + + + SPECULAR_GRP + Specular + + + EMISSION_GRP + Emission + + + COLOR + Color: + + + COEFFICIENT + Coefficient: + + + SHININESS + Shininess: + + + CUSTOM_MATERIAL + Custom material + + + OK_BTN + &OK + + + CANCEL_BTN + &Cancel + + + HELP_BTN + &Help + + OperationGUI_GetSharedShapesDlg diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index b5ee36ed4..e037eb54e 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -945,6 +945,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_MEN_SHADING Ombrage + + GEOM_MEN_SHADING_WITH_EDGES + Ombrage Avec Arêtes + GEOM_MEN_SKETCHER_X Indiquez la distance selon l'axe X @@ -2561,6 +2565,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_POP_SHADING Ombrage + + MEN_POP_SHADING_WITH_EDGES + Ombrage Avec Arêtes + MEN_POP_TEXTURE Texture @@ -2637,6 +2645,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_SHADING Ombrage + + MEN_SHADING_WITH_EDGES + Ombrage Avec Arêtes + MEN_SHADING_COLOR Couleur d'ombrage @@ -2753,6 +2765,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_POP_POINT_MARKER Marqueur de point + + MEN_POP_MATERIAL_PROPERTIES + Propriétés des matériaux + NAME_LBL Nom : @@ -2857,6 +2873,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau PREF_SHADING_COLOR Couleur d'ombrage par défaut + + PREF_EDGES_IN_SHADING + Bords de l'ombrage + PREF_STEP_VALUE Valeur du pas pour les boîtes d'incrément @@ -2877,6 +2897,14 @@ Choisissez une face, une coque ou un solide et essayez de nouveau PREF_WIREFRAME_COLOR Couleur des contours par défaut + + PREF_FRONT_MATERIAL + Devant du matériel par défaut + + + PREF_BACK_MATERIAL + Retour du matériel par défaut + PROCESS_SHAPE_NEW_OBJ_NAME FormeRetraitée @@ -3229,6 +3257,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_POP_SHADING Ombrage + + STB_POP_SHADING_WITH_EDGES + Ombrage Avec Arêtes + STB_POP_SETTEXTURE Ajoute une texture @@ -3369,6 +3401,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_POP_POINT_MARKER Définir un marqueur de point + + STB_POP_MATERIAL_PROPERTIES + Définir un propriétés des matériaux + SUPPRESS_RESULT Supprimer le résultat @@ -3781,6 +3817,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_POP_SHADING Ombrage + + TOP_POP_SHADING_WITH_EDGES + Ombrage Avec Arêtes + TOP_POP_SETTEXTURE Texture @@ -3901,6 +3941,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_POP_POINT_MARKER Marqueur de point + + TOP_POP_MATERIAL_PROPERTIES + Propriétés des matériaux + WRN_NOT_IMPLEMENTED Désolé, cette fonctionnalité n'est pas encore implémentée @@ -5005,6 +5049,61 @@ Voulez-vous continuer? Ouvrir une Texture + + GEOMToolsGUI_MaterialPropertiesDlg + + MATERIAL_PROPERTIES_TLT + Définir un Propriétés des Matériaux + + + MATERIAL_BACK_CHK + Activer retour du matériel + + + AMBIENT_GRP + Ambiante + + + DIFFUSE_GRP + Diffuse + + + SPECULAR_GRP + Spéculaire + + + EMISSION_GRP + Démission + + + COLOR + Couleurs: + + + COEFFICIENT + Coefficient: + + + SHININESS + Shininess: + + + CUSTOM_MATERIAL + Matériau personnalisé + + + OK_BTN + &OK + + + CANCEL_BTN + A&nnuler + + + HELP_BTN + &Aide + + OperationGUI_GetSharedShapesDlg diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index 60d773472..cfa64c465 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -31,11 +31,14 @@ #include "GeometryGUI_Operations.h" #include "GEOMGUI_OCCSelector.h" #include "GEOMGUI_Selection.h" +#include "GEOM_Constants.h" #include "GEOM_Displayer.h" #include "GEOM_AISShape.hxx" #include "GEOM_Actor.h" +#include + #include #include #include @@ -389,169 +392,171 @@ void GeometryGUI::OnGUIEvent( int id ) QString libName; // find corresponding GUI library switch ( id ) { - case GEOMOp::OpOriginAndVectors: // MENU BASIC - ORIGIN AND BASE VECTORS + case GEOMOp::OpOriginAndVectors: // MENU BASIC - ORIGIN AND BASE VECTORS createOriginAndBaseVectors(); // internal operation return; - case GEOMOp::OpImport: // MENU FILE - IMPORT - case GEOMOp::OpExport: // MENU FILE - EXPORT - case GEOMOp::OpSelectVertex: // POPUP MENU - SELECT ONLY - VERTEX - case GEOMOp::OpSelectEdge: // POPUP MENU - SELECT ONLY - EDGE - case GEOMOp::OpSelectWire: // POPUP MENU - SELECT ONLY - WIRE - case GEOMOp::OpSelectFace: // POPUP MENU - SELECT ONLY - FACE - case GEOMOp::OpSelectShell: // POPUP MENU - SELECT ONLY - SHELL - case GEOMOp::OpSelectSolid: // POPUP MENU - SELECT ONLY - SOLID - case GEOMOp::OpSelectCompound: // POPUP MENU - SELECT ONLY - COMPOUND - case GEOMOp::OpSelectAll: // POPUP MENU - SELECT ONLY - SELECT ALL - case GEOMOp::OpDelete: // MENU EDIT - DELETE - case GEOMOp::OpCheckGeom: // MENU TOOLS - CHECK GEOMETRY - case GEOMOp::OpDeflection: // POPUP MENU - DEFLECTION COEFFICIENT - case GEOMOp::OpColor: // POPUP MENU - COLOR - case GEOMOp::OpSetTexture: // POPUP MENU - SETTEXTURE - case GEOMOp::OpTransparency: // POPUP MENU - TRANSPARENCY - case GEOMOp::OpIncrTransparency: // SHORTCUT - INCREASE TRANSPARENCY - case GEOMOp::OpDecrTransparency: // SHORTCUT - DECREASE TRANSPARENCY - case GEOMOp::OpIsos: // POPUP MENU - ISOS - case GEOMOp::OpIncrNbIsos: // SHORTCUT - INCREASE NB ISOS - case GEOMOp::OpDecrNbIsos: // SHORTCUT - DECREASE NB ISOS - case GEOMOp::OpAutoColor: // POPUP MENU - AUTO COLOR - case GEOMOp::OpNoAutoColor: // POPUP MENU - DISABLE AUTO COLOR - case GEOMOp::OpShowChildren: // POPUP MENU - SHOW CHILDREN - case GEOMOp::OpHideChildren: // POPUP MENU - HIDE CHILDREN - case GEOMOp::OpUnpublishObject: // POPUP MENU - UNPUBLISH - case GEOMOp::OpPublishObject: // ROOT GEOM OBJECT - POPUP MENU - PUBLISH - case GEOMOp::OpPointMarker: // POPUP MENU - POINT MARKER + case GEOMOp::OpImport: // MENU FILE - IMPORT + case GEOMOp::OpExport: // MENU FILE - EXPORT + case GEOMOp::OpSelectVertex: // POPUP MENU - SELECT ONLY - VERTEX + case GEOMOp::OpSelectEdge: // POPUP MENU - SELECT ONLY - EDGE + case GEOMOp::OpSelectWire: // POPUP MENU - SELECT ONLY - WIRE + case GEOMOp::OpSelectFace: // POPUP MENU - SELECT ONLY - FACE + case GEOMOp::OpSelectShell: // POPUP MENU - SELECT ONLY - SHELL + case GEOMOp::OpSelectSolid: // POPUP MENU - SELECT ONLY - SOLID + case GEOMOp::OpSelectCompound: // POPUP MENU - SELECT ONLY - COMPOUND + case GEOMOp::OpSelectAll: // POPUP MENU - SELECT ONLY - SELECT ALL + case GEOMOp::OpDelete: // MENU EDIT - DELETE + case GEOMOp::OpCheckGeom: // MENU TOOLS - CHECK GEOMETRY + case GEOMOp::OpDeflection: // POPUP MENU - DEFLECTION COEFFICIENT + case GEOMOp::OpColor: // POPUP MENU - COLOR + case GEOMOp::OpSetTexture: // POPUP MENU - SETTEXTURE + case GEOMOp::OpTransparency: // POPUP MENU - TRANSPARENCY + case GEOMOp::OpIncrTransparency: // SHORTCUT - INCREASE TRANSPARENCY + case GEOMOp::OpDecrTransparency: // SHORTCUT - DECREASE TRANSPARENCY + case GEOMOp::OpIsos: // POPUP MENU - ISOS + case GEOMOp::OpIncrNbIsos: // SHORTCUT - INCREASE NB ISOS + case GEOMOp::OpDecrNbIsos: // SHORTCUT - DECREASE NB ISOS + case GEOMOp::OpAutoColor: // POPUP MENU - AUTO COLOR + case GEOMOp::OpNoAutoColor: // POPUP MENU - DISABLE AUTO COLOR + case GEOMOp::OpShowChildren: // POPUP MENU - SHOW CHILDREN + case GEOMOp::OpHideChildren: // POPUP MENU - HIDE CHILDREN + case GEOMOp::OpUnpublishObject: // POPUP MENU - UNPUBLISH + case GEOMOp::OpPublishObject: // ROOT GEOM OBJECT - POPUP MENU - PUBLISH + case GEOMOp::OpPointMarker: // POPUP MENU - POINT MARKER + case GEOMOp::OpMaterialProperties: // POPUP MENU - MATERIAL PROPERTIES libName = "GEOMToolsGUI"; break; - case GEOMOp::OpDisplayMode: // MENU VIEW - WIREFRAME/SHADING - case GEOMOp::OpShowAll: // MENU VIEW - SHOW ALL - case GEOMOp::OpShowOnly: // MENU VIEW - DISPLAY ONLY - case GEOMOp::OpHideAll: // MENU VIEW - ERASE ALL - case GEOMOp::OpHide: // MENU VIEW - ERASE - case GEOMOp::OpShow: // MENU VIEW - DISPLAY - case GEOMOp::OpSwitchVectors: // MENU VIEW - VECTOR MODE - case GEOMOp::OpWireframe: // POPUP MENU - WIREFRAME - case GEOMOp::OpShading: // POPUP MENU - SHADING - case GEOMOp::OpTexture: // POPUP MENU - TEXTURE - case GEOMOp::OpVectors: // POPUP MENU - VECTORS + case GEOMOp::OpDisplayMode: // MENU VIEW - WIREFRAME/SHADING + case GEOMOp::OpShowAll: // MENU VIEW - SHOW ALL + case GEOMOp::OpShowOnly: // MENU VIEW - DISPLAY ONLY + case GEOMOp::OpHideAll: // MENU VIEW - ERASE ALL + case GEOMOp::OpHide: // MENU VIEW - ERASE + case GEOMOp::OpShow: // MENU VIEW - DISPLAY + case GEOMOp::OpSwitchVectors: // MENU VIEW - VECTOR MODE + case GEOMOp::OpWireframe: // POPUP MENU - WIREFRAME + case GEOMOp::OpShading: // POPUP MENU - SHADING + case GEOMOp::OpShadingWithEdges: // POPUP MENU - SHADING WITH EDGES + case GEOMOp::OpTexture: // POPUP MENU - TEXTURE + case GEOMOp::OpVectors: // POPUP MENU - VECTORS libName = "DisplayGUI"; break; - case GEOMOp::OpPoint: // MENU BASIC - POINT - case GEOMOp::OpLine: // MENU BASIC - LINE - case GEOMOp::OpCircle: // MENU BASIC - CIRCLE - case GEOMOp::OpEllipse: // MENU BASIC - ELLIPSE - case GEOMOp::OpArc: // MENU BASIC - ARC - case GEOMOp::OpVector: // MENU BASIC - VECTOR - case GEOMOp::OpPlane: // MENU BASIC - PLANE - case GEOMOp::OpCurve: // MENU BASIC - CURVE - case GEOMOp::OpLCS: // MENU BASIC - LOCAL COORDINATE SYSTEM + case GEOMOp::OpPoint: // MENU BASIC - POINT + case GEOMOp::OpLine: // MENU BASIC - LINE + case GEOMOp::OpCircle: // MENU BASIC - CIRCLE + case GEOMOp::OpEllipse: // MENU BASIC - ELLIPSE + case GEOMOp::OpArc: // MENU BASIC - ARC + case GEOMOp::OpVector: // MENU BASIC - VECTOR + case GEOMOp::OpPlane: // MENU BASIC - PLANE + case GEOMOp::OpCurve: // MENU BASIC - CURVE + case GEOMOp::OpLCS: // MENU BASIC - LOCAL COORDINATE SYSTEM libName = "BasicGUI"; break; - case GEOMOp::OpBox: // MENU PRIMITIVE - BOX - case GEOMOp::OpCylinder: // MENU PRIMITIVE - CYLINDER - case GEOMOp::OpSphere: // MENU PRIMITIVE - SPHERE - case GEOMOp::OpTorus: // MENU PRIMITIVE - TORUS - case GEOMOp::OpCone: // MENU PRIMITIVE - CONE - case GEOMOp::OpRectangle: // MENU PRIMITIVE - FACE - case GEOMOp::OpDisk: // MENU PRIMITIVE - DISK + case GEOMOp::OpBox: // MENU PRIMITIVE - BOX + case GEOMOp::OpCylinder: // MENU PRIMITIVE - CYLINDER + case GEOMOp::OpSphere: // MENU PRIMITIVE - SPHERE + case GEOMOp::OpTorus: // MENU PRIMITIVE - TORUS + case GEOMOp::OpCone: // MENU PRIMITIVE - CONE + case GEOMOp::OpRectangle: // MENU PRIMITIVE - FACE + case GEOMOp::OpDisk: // MENU PRIMITIVE - DISK libName = "PrimitiveGUI"; break; - case GEOMOp::OpPrism: // MENU GENERATION - PRISM - case GEOMOp::OpRevolution: // MENU GENERATION - REVOLUTION - case GEOMOp::OpFilling: // MENU GENERATION - FILLING - case GEOMOp::OpPipe: // MENU GENERATION - PIPE + case GEOMOp::OpPrism: // MENU GENERATION - PRISM + case GEOMOp::OpRevolution: // MENU GENERATION - REVOLUTION + case GEOMOp::OpFilling: // MENU GENERATION - FILLING + case GEOMOp::OpPipe: // MENU GENERATION - PIPE libName = "GenerationGUI"; break; - case GEOMOp::Op2dSketcher: // MENU ENTITY - SKETCHER - case GEOMOp::Op3dSketcher: // MENU ENTITY - 3D SKETCHER - case GEOMOp::OpExplode: // MENU ENTITY - EXPLODE + case GEOMOp::Op2dSketcher: // MENU ENTITY - SKETCHER + case GEOMOp::Op3dSketcher: // MENU ENTITY - 3D SKETCHER + case GEOMOp::OpExplode: // MENU ENTITY - EXPLODE #ifdef WITH_OPENCV - case GEOMOp::OpFeatureDetect: // MENU ENTITY - FEATURE DETECTION + case GEOMOp::OpFeatureDetect: // MENU ENTITY - FEATURE DETECTION #endif - case GEOMOp::OpPictureImport: // MENU ENTITY - IMPORT PICTURE IN VIEWER + case GEOMOp::OpPictureImport: // MENU ENTITY - IMPORT PICTURE IN VIEWER libName = "EntityGUI"; break; - case GEOMOp::OpEdge: // MENU BUILD - EDGE - case GEOMOp::OpWire: // MENU BUILD - WIRE - case GEOMOp::OpFace: // MENU BUILD - FACE - case GEOMOp::OpShell: // MENU BUILD - SHELL - case GEOMOp::OpSolid: // MENU BUILD - SOLID - case GEOMOp::OpCompound: // MENU BUILD - COMPUND + case GEOMOp::OpEdge: // MENU BUILD - EDGE + case GEOMOp::OpWire: // MENU BUILD - WIRE + case GEOMOp::OpFace: // MENU BUILD - FACE + case GEOMOp::OpShell: // MENU BUILD - SHELL + case GEOMOp::OpSolid: // MENU BUILD - SOLID + case GEOMOp::OpCompound: // MENU BUILD - COMPUND libName = "BuildGUI"; break; - case GEOMOp::OpFuse: // MENU BOOLEAN - FUSE - case GEOMOp::OpCommon: // MENU BOOLEAN - COMMON - case GEOMOp::OpCut: // MENU BOOLEAN - CUT - case GEOMOp::OpSection: // MENU BOOLEAN - SECTION + case GEOMOp::OpFuse: // MENU BOOLEAN - FUSE + case GEOMOp::OpCommon: // MENU BOOLEAN - COMMON + case GEOMOp::OpCut: // MENU BOOLEAN - CUT + case GEOMOp::OpSection: // MENU BOOLEAN - SECTION libName = "BooleanGUI"; break; - case GEOMOp::OpTranslate: // MENU TRANSFORMATION - TRANSLATION - case GEOMOp::OpRotate: // MENU TRANSFORMATION - ROTATION - case GEOMOp::OpChangeLoc: // MENU TRANSFORMATION - LOCATION - case GEOMOp::OpMirror: // MENU TRANSFORMATION - MIRROR - case GEOMOp::OpScale: // MENU TRANSFORMATION - SCALE - case GEOMOp::OpOffset: // MENU TRANSFORMATION - OFFSET - case GEOMOp::OpProjection: // MENU TRANSFORMATION - PROJECTION - case GEOMOp::OpMultiTranslate: // MENU TRANSFORMATION - MULTI-TRANSLATION - case GEOMOp::OpMultiRotate: // MENU TRANSFORMATION - MULTI-ROTATION - case GEOMOp::OpReimport: // CONTEXT(POPUP) MENU - RELOAD_IMPORTED + case GEOMOp::OpTranslate: // MENU TRANSFORMATION - TRANSLATION + case GEOMOp::OpRotate: // MENU TRANSFORMATION - ROTATION + case GEOMOp::OpChangeLoc: // MENU TRANSFORMATION - LOCATION + case GEOMOp::OpMirror: // MENU TRANSFORMATION - MIRROR + case GEOMOp::OpScale: // MENU TRANSFORMATION - SCALE + case GEOMOp::OpOffset: // MENU TRANSFORMATION - OFFSET + case GEOMOp::OpProjection: // MENU TRANSFORMATION - PROJECTION + case GEOMOp::OpMultiTranslate: // MENU TRANSFORMATION - MULTI-TRANSLATION + case GEOMOp::OpMultiRotate: // MENU TRANSFORMATION - MULTI-ROTATION + case GEOMOp::OpReimport: // CONTEXT(POPUP) MENU - RELOAD_IMPORTED libName = "TransformationGUI"; break; - case GEOMOp::OpPartition: // MENU OPERATION - PARTITION - case GEOMOp::OpArchimede: // MENU OPERATION - ARCHIMEDE - case GEOMOp::OpFillet3d: // MENU OPERATION - FILLET - case GEOMOp::OpChamfer: // MENU OPERATION - CHAMFER - case GEOMOp::OpClipping: // MENU OPERATION - CLIPPING RANGE - case GEOMOp::OpShapesOnShape: // MENU OPERATION - GET SHAPES ON SHAPE - case GEOMOp::OpFillet2d: // MENU OPERATION - FILLET 2D - case GEOMOp::OpFillet1d: // MENU OPERATION - FILLET 1D - case GEOMOp::OpSharedShapes: // MENU OPERATION - GET SHARED SHAPES + case GEOMOp::OpPartition: // MENU OPERATION - PARTITION + case GEOMOp::OpArchimede: // MENU OPERATION - ARCHIMEDE + case GEOMOp::OpFillet3d: // MENU OPERATION - FILLET + case GEOMOp::OpChamfer: // MENU OPERATION - CHAMFER + case GEOMOp::OpClipping: // MENU OPERATION - CLIPPING RANGE + case GEOMOp::OpShapesOnShape: // MENU OPERATION - GET SHAPES ON SHAPE + case GEOMOp::OpFillet2d: // MENU OPERATION - FILLET 2D + case GEOMOp::OpFillet1d: // MENU OPERATION - FILLET 1D + case GEOMOp::OpSharedShapes: // MENU OPERATION - GET SHARED SHAPES libName = "OperationGUI"; break; - case GEOMOp::OpSewing: // MENU REPAIR - SEWING - case GEOMOp::OpSuppressFaces: // MENU REPAIR - SUPPRESS FACES - case GEOMOp::OpSuppressHoles: // MENU REPAIR - SUPPRESS HOLE - case GEOMOp::OpShapeProcess: // MENU REPAIR - SHAPE PROCESSING - case GEOMOp::OpCloseContour: // MENU REPAIR - CLOSE CONTOUR - case GEOMOp::OpRemoveIntWires: // MENU REPAIR - REMOVE INTERNAL WIRES - case GEOMOp::OpAddPointOnEdge: // MENU REPAIR - ADD POINT ON EDGE - case GEOMOp::OpFreeBoundaries: // MENU MEASURE - FREE BOUNDARIES - case GEOMOp::OpFreeFaces: // MENU MEASURE - FREE FACES - case GEOMOp::OpOrientation: // MENU REPAIR - CHANGE ORIENTATION - case GEOMOp::OpGlueFaces: // MENU REPAIR - GLUE FACES - case GEOMOp::OpGlueEdges: // MENU REPAIR - GLUE EDGES - case GEOMOp::OpLimitTolerance: // MENU REPAIR - LIMIT TOLERANCE - case GEOMOp::OpRemoveExtraEdges: // MENU REPAIR - REMOVE EXTRA EDGES + case GEOMOp::OpSewing: // MENU REPAIR - SEWING + case GEOMOp::OpSuppressFaces: // MENU REPAIR - SUPPRESS FACES + case GEOMOp::OpSuppressHoles: // MENU REPAIR - SUPPRESS HOLE + case GEOMOp::OpShapeProcess: // MENU REPAIR - SHAPE PROCESSING + case GEOMOp::OpCloseContour: // MENU REPAIR - CLOSE CONTOUR + case GEOMOp::OpRemoveIntWires: // MENU REPAIR - REMOVE INTERNAL WIRES + case GEOMOp::OpAddPointOnEdge: // MENU REPAIR - ADD POINT ON EDGE + case GEOMOp::OpFreeBoundaries: // MENU MEASURE - FREE BOUNDARIES + case GEOMOp::OpFreeFaces: // MENU MEASURE - FREE FACES + case GEOMOp::OpOrientation: // MENU REPAIR - CHANGE ORIENTATION + case GEOMOp::OpGlueFaces: // MENU REPAIR - GLUE FACES + case GEOMOp::OpGlueEdges: // MENU REPAIR - GLUE EDGES + case GEOMOp::OpLimitTolerance: // MENU REPAIR - LIMIT TOLERANCE + case GEOMOp::OpRemoveExtraEdges: // MENU REPAIR - REMOVE EXTRA EDGES libName = "RepairGUI"; break; - case GEOMOp::OpProperties: // MENU MEASURE - PROPERTIES - case GEOMOp::OpCenterMass: // MENU MEASURE - CDG - case GEOMOp::OpInertia: // MENU MEASURE - INERTIA - case GEOMOp::OpNormale: // MENU MEASURE - NORMALE - case GEOMOp::OpBoundingBox: // MENU MEASURE - BOUNDING BOX - case GEOMOp::OpMinDistance: // MENU MEASURE - MIN DISTANCE - case GEOMOp::OpAngle: // MENU MEASURE - ANGLE - case GEOMOp::OpTolerance: // MENU MEASURE - TOLERANCE - case GEOMOp::OpWhatIs: // MENU MEASURE - WHATIS - case GEOMOp::OpCheckShape: // MENU MEASURE - CHECK - case GEOMOp::OpCheckCompound: // MENU MEASURE - CHECK COMPOUND OF BLOCKS - case GEOMOp::OpPointCoordinates: // MENU MEASURE - POINT COORDINATES - case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS + case GEOMOp::OpProperties: // MENU MEASURE - PROPERTIES + case GEOMOp::OpCenterMass: // MENU MEASURE - CDG + case GEOMOp::OpInertia: // MENU MEASURE - INERTIA + case GEOMOp::OpNormale: // MENU MEASURE - NORMALE + case GEOMOp::OpBoundingBox: // MENU MEASURE - BOUNDING BOX + case GEOMOp::OpMinDistance: // MENU MEASURE - MIN DISTANCE + case GEOMOp::OpAngle: // MENU MEASURE - ANGLE + case GEOMOp::OpTolerance: // MENU MEASURE - TOLERANCE + case GEOMOp::OpWhatIs: // MENU MEASURE - WHATIS + case GEOMOp::OpCheckShape: // MENU MEASURE - CHECK + case GEOMOp::OpCheckCompound: // MENU MEASURE - CHECK COMPOUND OF BLOCKS + case GEOMOp::OpPointCoordinates: // MENU MEASURE - POINT COORDINATES + case GEOMOp::OpCheckSelfInters: // MENU MEASURE - CHECK SELF INTERSECTIONS libName = "MeasureGUI"; break; - case GEOMOp::OpGroupCreate: // MENU GROUP - CREATE - case GEOMOp::OpGroupCreatePopup: // POPUP MENU - CREATE GROUP - case GEOMOp::OpGroupEdit: // MENU GROUP - EDIT + case GEOMOp::OpGroupCreate: // MENU GROUP - CREATE + case GEOMOp::OpGroupCreatePopup: // POPUP MENU - CREATE GROUP + case GEOMOp::OpGroupEdit: // MENU GROUP - EDIT libName = "GroupGUI"; break; - case GEOMOp::OpHexaSolid: // MENU BLOCKS - HEXAHEDRAL SOLID - case GEOMOp::OpMultiTransform: // MENU BLOCKS - MULTI-TRANSFORMATION - case GEOMOp::OpQuadFace: // MENU BLOCKS - QUADRANGLE FACE - case GEOMOp::OpPropagate: // MENU BLOCKS - PROPAGATE - case GEOMOp::OpExplodeBlock: // MENU BLOCKS - EXPLODE ON BLOCKS + case GEOMOp::OpHexaSolid: // MENU BLOCKS - HEXAHEDRAL SOLID + case GEOMOp::OpMultiTransform: // MENU BLOCKS - MULTI-TRANSFORMATION + case GEOMOp::OpQuadFace: // MENU BLOCKS - QUADRANGLE FACE + case GEOMOp::OpPropagate: // MENU BLOCKS - PROPAGATE + case GEOMOp::OpExplodeBlock: // MENU BLOCKS - EXPLODE ON BLOCKS libName = "BlocksGUI"; break; - case GEOMOp::OpAdvancedNoOp: // NO OPERATION (advanced operations base) - case GEOMOp::OpPipeTShape: // MENU NEW ENTITY - ADVANCED - PIPE TSHAPE + case GEOMOp::OpAdvancedNoOp: // NO OPERATION (advanced operations base) + case GEOMOp::OpPipeTShape: // MENU NEW ENTITY - ADVANCED - PIPE TSHAPE // case GEOMOp::OpPipeTShapeGroups: // MENU NEW ENTITY - ADVANCED - PIPE TSHAPE GROUPS //@@ insert new functions before this line @@ do not remove this line @@ do not remove this line @@ do not remove this line @@ do not remove this line @@// libName = "AdvancedGUI"; @@ -571,8 +576,24 @@ void GeometryGUI::OnGUIEvent( int id ) } // call method of corresponding GUI library - if ( library ) + if ( library ) { library->OnGUIEvent( id, desk ); + + // Update a list of materials for "Preferences" dialog + if ( id == GEOMOp::OpMaterialProperties ) { + LightApp_Preferences* pref = preferences(); + if ( pref ) { + Material_ResourceMgr aMatResMgr; + QStringList aPerfMatNames = aMatResMgr.getPreferenceMaterialsNames(); + setPreferenceProperty( pref->rootItem()->findItem( tr( "PREF_FRONT_MATERIAL" ), true )->id(), + "strings", + aPerfMatNames ); + setPreferenceProperty( pref->rootItem()->findItem( tr( "PREF_BACK_MATERIAL" ), true )->id(), + "strings", + aPerfMatNames ); + } + } + } else SUIT_MessageBox::critical( desk, tr( "GEOM_ERROR" ), tr( "GEOM_ERR_LIB_NOT_FOUND" ), tr( "GEOM_BUT_OK" ) ); } @@ -821,6 +842,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpWireframe, "POP_WIREFRAME", "", 0, true ); createGeomAction( GEOMOp::OpShading, "POP_SHADING", "", 0, true ); + createGeomAction( GEOMOp::OpShadingWithEdges, "POP_SHADING_WITH_EDGES", "", 0, true ); createGeomAction( GEOMOp::OpTexture, "POP_TEXTURE", "", 0, true ); createGeomAction( GEOMOp::OpVectors, "POP_VECTORS", "", 0, true ); createGeomAction( GEOMOp::OpDeflection, "POP_DEFLECTION" ); @@ -836,6 +858,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpUnpublishObject, "POP_UNPUBLISH_OBJ" ); createGeomAction( GEOMOp::OpPublishObject, "POP_PUBLISH_OBJ" ); createGeomAction( GEOMOp::OpPointMarker, "POP_POINT_MARKER" ); + createGeomAction( GEOMOp::OpMaterialProperties, "POP_MATERIAL_PROPERTIES" ); createGeomAction( GEOMOp::OpPipeTShape, "PIPETSHAPE" ); @@ -1185,6 +1208,9 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->insert( action( GEOMOp::OpShading ), dispmodeId, -1 ); // shading mgr->setRule( action( GEOMOp::OpShading ), clientOCCorVTK_AndSomeVisible, QtxPopupMgr::VisibleRule ); mgr->setRule( action( GEOMOp::OpShading ), clientOCCorVTK + " and displaymode='Shading'", QtxPopupMgr::ToggleRule ); + mgr->insert( action( GEOMOp::OpShadingWithEdges ), dispmodeId, -1 ); // shading with edges + mgr->setRule( action( GEOMOp::OpShadingWithEdges ), clientOCCorVTK_AndSomeVisible, QtxPopupMgr::VisibleRule ); + mgr->setRule( action( GEOMOp::OpShadingWithEdges ), clientOCCorVTK + " and displaymode='ShadingWithEdges'", QtxPopupMgr::ToggleRule ); mgr->insert( action( GEOMOp::OpTexture ), dispmodeId, -1 ); // wireframe mgr->setRule( action( GEOMOp::OpTexture ), clientOCC_AndSomeVisible, QtxPopupMgr::VisibleRule ); mgr->setRule( action( GEOMOp::OpTexture), clientOCC + " and displaymode='Texture'", QtxPopupMgr::ToggleRule ); @@ -1204,6 +1230,8 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->insert( action( GEOMOp::OpPointMarker ), -1, -1 ); // point marker //mgr->setRule( action( GEOMOp::OpPointMarker ), QString( "selcount>0 and $typeid in {%1}" ).arg(GEOM_POINT ), QtxPopupMgr::VisibleRule ); mgr->setRule( action( GEOMOp::OpPointMarker ), QString( "selcount>0 and ( $typeid in {%1} or compoundOfVertices=true ) " ).arg(GEOM::VERTEX).arg(GEOM::COMPOUND), QtxPopupMgr::VisibleRule ); + mgr->insert( action( GEOMOp::OpMaterialProperties ), -1, -1 ); // material properties + mgr->setRule( action( GEOMOp::OpMaterialProperties ), clientOCCorVTK_AndSomeVisible + " and ($component={'GEOM'}) and selcount>0 and isVisible", QtxPopupMgr::VisibleRule ); mgr->insert( action( GEOMOp::OpSetTexture ), -1, -1 ); // texture mgr->setRule( action( GEOMOp::OpSetTexture ), clientOCCorOB_AndSomeVisible + " and ($component={'GEOM'})", QtxPopupMgr::VisibleRule ); mgr->insert( separator(), -1, -1 ); // ----------- @@ -1624,6 +1652,9 @@ void GeometryGUI::createPreferences() addPreference( tr( "PREF_SHADING_COLOR" ), genGroup, LightApp_Preferences::Color, "Geometry", "shading_color" ); + addPreference( tr( "PREF_EDGES_IN_SHADING" ), genGroup, + LightApp_Preferences::Color, "Geometry", "edges_in_shading_color" ); + addPreference( tr( "PREF_WIREFRAME_COLOR" ), genGroup, LightApp_Preferences::Color, "Geometry", "wireframe_color" ); @@ -1645,6 +1676,14 @@ void GeometryGUI::createPreferences() int defl = addPreference( tr( "PREF_DEFLECTION" ), genGroup, LightApp_Preferences::DblSpin, "Geometry", "deflection_coeff" ); + int front_material = addPreference( tr( "PREF_FRONT_MATERIAL" ), genGroup, + LightApp_Preferences::Selector, + "Geometry", "front_material" ); + + int back_material = addPreference( tr( "PREF_BACK_MATERIAL" ), genGroup, + LightApp_Preferences::Selector, + "Geometry", "back_material" ); + // Quantities with individual precision settings int precGroup = addPreference( tr( "GEOM_PREF_GROUP_PRECISION" ), tabId ); setPreferenceProperty( precGroup, "columns", 2 ); @@ -1688,10 +1727,12 @@ void GeometryGUI::createPreferences() QStringList aModesList; aModesList.append( tr("MEN_WIREFRAME") ); aModesList.append( tr("MEN_SHADING") ); + aModesList.append( tr("MEN_SHADING_WITH_EDGES") ); QList anIndexesList; anIndexesList.append(0); anIndexesList.append(1); + anIndexesList.append(2); setPreferenceProperty( dispmode, "strings", aModesList ); setPreferenceProperty( dispmode, "indexes", anIndexesList ); @@ -1707,6 +1748,12 @@ void GeometryGUI::createPreferences() setPreferenceProperty( defl, "step", 1.0e-04 ); setPreferenceProperty( defl, "precision", 6 ); + // Set property for default material + Material_ResourceMgr aMatResMgr; + QStringList aPrefMatNames = aMatResMgr.getPreferenceMaterialsNames(); + setPreferenceProperty( front_material, "strings", aPrefMatNames ); + setPreferenceProperty( back_material, "strings", aPrefMatNames ); + // Set property vertex marker type QList aMarkerTypeIndicesList; QList aMarkerTypeIconsList; @@ -1787,7 +1834,7 @@ const char gDigitsSep = ':'; // character used to separate numeric parameter val * \brief Store visual parameters * * This method is called just before the study document is saved. - * Store visual parameters in AttributeParameter attribue(s) + * Store visual parameters in AttributeParameter attribute(s) */ void GeometryGUI::storeVisualParameters (int savePoint) { @@ -1894,6 +1941,16 @@ void GeometryGUI::storeVisualParameters (int savePoint) param = occParam + MARKER_TYPE_PROP; ip->setParameter(entry, param, aProps.value(MARKER_TYPE_PROP).toString().toLatin1().data()); } + + if(aProps.contains(FRONT_MATERIAL_PROP)) { + param = occParam + FRONT_MATERIAL_PROP; + ip->setParameter(entry, param, aProps.value(FRONT_MATERIAL_PROP).toString().toLatin1().data()); + } + + if(aProps.contains(BACK_MATERIAL_PROP)) { + param = occParam + BACK_MATERIAL_PROP; + ip->setParameter(entry, param, aProps.value(BACK_MATERIAL_PROP).toString().toLatin1().data()); + } } // object iterator } // for (views) } // for (viewManagers) @@ -1903,7 +1960,7 @@ void GeometryGUI::storeVisualParameters (int savePoint) * \brief Restore visual parameters * * This method is called after the study document is opened. - * Restore visual parameters from AttributeParameter attribue(s) + * Restore visual parameters from AttributeParameter attribute(s) */ void GeometryGUI::restoreVisualParameters (int savePoint) { @@ -2001,6 +2058,10 @@ void GeometryGUI::restoreVisualParameters (int savePoint) aListOfMap[viewIndex].insert( DEFLECTION_COEFF_PROP, val.toDouble()); } else if(paramNameStr == MARKER_TYPE_PROP) { aListOfMap[viewIndex].insert( MARKER_TYPE_PROP, val); + } else if(paramNameStr == FRONT_MATERIAL_PROP) { + aListOfMap[viewIndex].insert( FRONT_MATERIAL_PROP, val); + } else if(paramNameStr == BACK_MATERIAL_PROP) { + aListOfMap[viewIndex].insert( BACK_MATERIAL_PROP, val); } } // for names/parameters iterator diff --git a/src/GEOMGUI/GeometryGUI.h b/src/GEOMGUI/GeometryGUI.h index e523da284..406120e93 100644 --- a/src/GEOMGUI/GeometryGUI.h +++ b/src/GEOMGUI/GeometryGUI.h @@ -54,24 +54,6 @@ #include "SALOMEconfig.h" #include CORBA_CLIENT_HEADER(SALOMEDS) -// minimum allowed value for deflection coefficient -#define DEFLECTION_MIN 1e-06 - -//Define separators -#define NAME_SEPARATOR '_' // character used to separate parameter names -#define DIGIT_SEPARATOR ':' // character used to separate numeric parameter values (color = r:g:b) - -#define VISIBILITY_PROP "Visibility" //Object visibility property -#define OPACITY_PROP "Opacity" //Object opacity property -#define TRANSPARENCY_PROP "Transparency" //Object transparency property -#define DISPLAY_MODE_PROP "DisplayMode" //Object display mode property -#define ISOS_PROP "Isos" //Number of the Isos property of the object -#define COLOR_PROP "Color" //Color of the object -#define VECTOR_MODE_PROP "VectorMode" //Vector mode property -#define DEFLECTION_COEFF_PROP "DeflectionCoeff" //Deflection coeff property -#define MARKER_TYPE_PROP "MarkerType" // Marker type property - - class QDialog; class QMenu; class GEOMGUI_OCCSelector; diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 1731c1772..5ff8d5921 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -25,155 +25,157 @@ namespace GEOMOp { enum { // ToolsGUI ------------------//-------------------------------- - OpImport = 1000, // MENU FILE - IMPORT - OpExport = 1001, // MENU FILE - EXPORT - OpDelete = 1020, // MENU EDIT - DELETE - OpCheckGeom = 1030, // MENU TOOLS - CHECK GEOMETRY - OpSelectVertex = 1100, // POPUP MENU - SELECT ONLY - VERTEX - OpSelectEdge = 1101, // POPUP MENU - SELECT ONLY - EDGE - OpSelectWire = 1102, // POPUP MENU - SELECT ONLY - WIRE - OpSelectFace = 1103, // POPUP MENU - SELECT ONLY - FACE - OpSelectShell = 1104, // POPUP MENU - SELECT ONLY - SHELL - OpSelectSolid = 1105, // POPUP MENU - SELECT ONLY - SOLID - OpSelectCompound = 1106, // POPUP MENU - SELECT ONLY - COMPOUND - OpSelectAll = 1107, // POPUP MENU - SELECT ONLY - SELECT ALL - OpDeflection = 1200, // POPUP MENU - DEFLECTION COEFFICIENT - OpColor = 1201, // POPUP MENU - COLOR - OpTransparency = 1202, // POPUP MENU - TRANSPARENCY - OpIncrTransparency = 1203, // SHORTCUT - INCREASE TRANSPARENCY - OpDecrTransparency = 1204, // SHORTCUT - DECREASE TRANSPARENCY - OpIsos = 1205, // POPUP MENU - ISOS - OpIncrNbIsos = 1206, // SHORTCUT - INCREASE NB ISOS - OpDecrNbIsos = 1207, // SHORTCUT - DECREASE NB ISOS - OpAutoColor = 1208, // POPUP MENU - AUTO COLOR - OpNoAutoColor = 1209, // POPUP MENU - DISABLE AUTO COLOR - OpPointMarker = 1210, // POPUP MENU - POINT MARKER - OpSetTexture = 1211, // POPUP MENU - SETTEXTURE - OpShowChildren = 1250, // POPUP MENU - SHOW CHILDREN - OpHideChildren = 1251, // POPUP MENU - HIDE CHILDREN - OpUnpublishObject = 1253, // POPUP MENU - UNPUBLISH - OpPublishObject = 1254, // GEOM ROOT OBJECT - POPUP MENU - PUBLISH + OpImport = 1000, // MENU FILE - IMPORT + OpExport = 1001, // MENU FILE - EXPORT + OpDelete = 1020, // MENU EDIT - DELETE + OpCheckGeom = 1030, // MENU TOOLS - CHECK GEOMETRY + OpSelectVertex = 1100, // POPUP MENU - SELECT ONLY - VERTEX + OpSelectEdge = 1101, // POPUP MENU - SELECT ONLY - EDGE + OpSelectWire = 1102, // POPUP MENU - SELECT ONLY - WIRE + OpSelectFace = 1103, // POPUP MENU - SELECT ONLY - FACE + OpSelectShell = 1104, // POPUP MENU - SELECT ONLY - SHELL + OpSelectSolid = 1105, // POPUP MENU - SELECT ONLY - SOLID + OpSelectCompound = 1106, // POPUP MENU - SELECT ONLY - COMPOUND + OpSelectAll = 1107, // POPUP MENU - SELECT ONLY - SELECT ALL + OpDeflection = 1200, // POPUP MENU - DEFLECTION COEFFICIENT + OpColor = 1201, // POPUP MENU - COLOR + OpTransparency = 1202, // POPUP MENU - TRANSPARENCY + OpIncrTransparency = 1203, // SHORTCUT - INCREASE TRANSPARENCY + OpDecrTransparency = 1204, // SHORTCUT - DECREASE TRANSPARENCY + OpIsos = 1205, // POPUP MENU - ISOS + OpIncrNbIsos = 1206, // SHORTCUT - INCREASE NB ISOS + OpDecrNbIsos = 1207, // SHORTCUT - DECREASE NB ISOS + OpAutoColor = 1208, // POPUP MENU - AUTO COLOR + OpNoAutoColor = 1209, // POPUP MENU - DISABLE AUTO COLOR + OpPointMarker = 1210, // POPUP MENU - POINT MARKER + OpSetTexture = 1211, // POPUP MENU - SETTEXTURE + OpMaterialProperties = 1212, // POPUP MENU - MATERIAL PROPERTIES + OpShowChildren = 1250, // POPUP MENU - SHOW CHILDREN + OpHideChildren = 1251, // POPUP MENU - HIDE CHILDREN + OpUnpublishObject = 1253, // POPUP MENU - UNPUBLISH + OpPublishObject = 1254, // GEOM ROOT OBJECT - POPUP MENU - PUBLISH // DisplayGUI ----------------//-------------------------------- - OpDisplayMode = 2000, // MENU VIEW - DISPLAY MODE - WIREFRAME/SHADING - OpSwitchVectors = 2001, // MENU VIEW - DISPLAY MODE - SHOW/HIDE EDGE DIRECTION - OpShowAll = 2002, // MENU VIEW - SHOW ALL - OpHideAll = 2003, // MENU VIEW - HIDE ALL - OpShow = 2100, // POPUP MENU - SHOW - OpShowOnly = 2101, // POPUP MENU - SHOW ONLY - OpHide = 2102, // POPUP MENU - HIDE - OpWireframe = 2200, // POPUP MENU - DISPLAY MODE - WIREFRAME - OpShading = 2201, // POPUP MENU - DISPLAY MODE - SHADING - OpVectors = 2202, // POPUP MENU - DISPLAY MODE - SHOW EDGE DIRECTION - OpTexture = 2203, // POPUP MENU - DISPLAY MODE - TEXTURE + OpDisplayMode = 2000, // MENU VIEW - DISPLAY MODE - WIREFRAME/SHADING/SHADING WITH EDGES + OpSwitchVectors = 2001, // MENU VIEW - DISPLAY MODE - SHOW/HIDE EDGE DIRECTION + OpShowAll = 2002, // MENU VIEW - SHOW ALL + OpHideAll = 2003, // MENU VIEW - HIDE ALL + OpShow = 2100, // POPUP MENU - SHOW + OpShowOnly = 2101, // POPUP MENU - SHOW ONLY + OpHide = 2102, // POPUP MENU - HIDE + OpWireframe = 2200, // POPUP MENU - DISPLAY MODE - WIREFRAME + OpShading = 2201, // POPUP MENU - DISPLAY MODE - SHADING + OpShadingWithEdges = 2202, // POPUP MENU - DISPLAY MODE - SHADING WITH EDGES + OpVectors = 2203, // POPUP MENU - DISPLAY MODE - SHOW EDGE DIRECTION + OpTexture = 2204, // POPUP MENU - DISPLAY MODE - TEXTURE // BasicGUI ------------------//-------------------------------- - OpPoint = 3000, // MENU NEW ENTITY - BASIC - POINT - OpLine = 3001, // MENU NEW ENTITY - BASIC - LINE - OpCircle = 3002, // MENU NEW ENTITY - BASIC - CIRCLE - OpEllipse = 3003, // MENU NEW ENTITY - BASIC - ELLIPSE - OpArc = 3004, // MENU NEW ENTITY - BASIC - ARC - OpVector = 3005, // MENU NEW ENTITY - BASIC - VECTOR - OpPlane = 3006, // MENU NEW ENTITY - BASIC - PLANE - OpCurve = 3007, // MENU NEW ENTITY - BASIC - CURVE - OpLCS = 3008, // MENU NEW ENTITY - BASIC - LOCAL COORDINATE SYSTEM - OpOriginAndVectors = 3009, // MENU NEW ENTITY - BASIC - ORIGIN AND BASE VECTORS + OpPoint = 3000, // MENU NEW ENTITY - BASIC - POINT + OpLine = 3001, // MENU NEW ENTITY - BASIC - LINE + OpCircle = 3002, // MENU NEW ENTITY - BASIC - CIRCLE + OpEllipse = 3003, // MENU NEW ENTITY - BASIC - ELLIPSE + OpArc = 3004, // MENU NEW ENTITY - BASIC - ARC + OpVector = 3005, // MENU NEW ENTITY - BASIC - VECTOR + OpPlane = 3006, // MENU NEW ENTITY - BASIC - PLANE + OpCurve = 3007, // MENU NEW ENTITY - BASIC - CURVE + OpLCS = 3008, // MENU NEW ENTITY - BASIC - LOCAL COORDINATE SYSTEM + OpOriginAndVectors = 3009, // MENU NEW ENTITY - BASIC - ORIGIN AND BASE VECTORS // PrimitiveGUI --------------//-------------------------------- - OpBox = 3100, // MENU NEW ENTITY - PRIMITIVES - BOX - OpCylinder = 3101, // MENU NEW ENTITY - PRIMITIVES - CYLINDER - OpSphere = 3102, // MENU NEW ENTITY - PRIMITIVES - SPHERE - OpTorus = 3103, // MENU NEW ENTITY - PRIMITIVES - TORUS - OpCone = 3104, // MENU NEW ENTITY - PRIMITIVES - CONE - OpRectangle = 3105, // MENU NEW ENTITY - PRIMITIVES - FACE - OpDisk = 3106, // MENU NEW ENTITY - PRIMITIVES - DISK + OpBox = 3100, // MENU NEW ENTITY - PRIMITIVES - BOX + OpCylinder = 3101, // MENU NEW ENTITY - PRIMITIVES - CYLINDER + OpSphere = 3102, // MENU NEW ENTITY - PRIMITIVES - SPHERE + OpTorus = 3103, // MENU NEW ENTITY - PRIMITIVES - TORUS + OpCone = 3104, // MENU NEW ENTITY - PRIMITIVES - CONE + OpRectangle = 3105, // MENU NEW ENTITY - PRIMITIVES - FACE + OpDisk = 3106, // MENU NEW ENTITY - PRIMITIVES - DISK // GenerationGUI -------------//-------------------------------- - OpPrism = 3200, // MENU NEW ENTITY - GENERATION - EXTRUSION - OpRevolution = 3201, // MENU NEW ENTITY - GENERATION - REVOLUTION - OpFilling = 3202, // MENU NEW ENTITY - GENERATION - FILLING - OpPipe = 3203, // MENU NEW ENTITY - GENERATION - EXTRUSION ALONG PATH + OpPrism = 3200, // MENU NEW ENTITY - GENERATION - EXTRUSION + OpRevolution = 3201, // MENU NEW ENTITY - GENERATION - REVOLUTION + OpFilling = 3202, // MENU NEW ENTITY - GENERATION - FILLING + OpPipe = 3203, // MENU NEW ENTITY - GENERATION - EXTRUSION ALONG PATH // EntityGUI -----------------//-------------------------------- - Op2dSketcher = 3300, // MENU NEW ENTITY - SKETCHER - Op3dSketcher = 3301, // MENU NEW ENTITY - 3D SKETCHER - OpExplode = 3302, // MENU NEW ENTITY - EXPLODE + Op2dSketcher = 3300, // MENU NEW ENTITY - SKETCHER + Op3dSketcher = 3301, // MENU NEW ENTITY - 3D SKETCHER + OpExplode = 3302, // MENU NEW ENTITY - EXPLODE #ifdef WITH_OPENCV - OpFeatureDetect = 3303, // MENU NEW ENTITY - FEATURE DETECTION + OpFeatureDetect = 3303, // MENU NEW ENTITY - FEATURE DETECTION #endif - OpPictureImport = 3304, // MENU NEW ENTITY - IMPORT PICTURE IN VIEWER + OpPictureImport = 3304, // MENU NEW ENTITY - IMPORT PICTURE IN VIEWER // BuildGUI ------------------//-------------------------------- - OpEdge = 3400, // MENU NEW ENTITY - BUILD - EDGE - OpWire = 3401, // MENU NEW ENTITY - BUILD - WIRE - OpFace = 3402, // MENU NEW ENTITY - BUILD - FACE - OpShell = 3403, // MENU NEW ENTITY - BUILD - SHELL - OpSolid = 3404, // MENU NEW ENTITY - BUILD - SOLID - OpCompound = 3405, // MENU NEW ENTITY - BUILD - COMPOUND + OpEdge = 3400, // MENU NEW ENTITY - BUILD - EDGE + OpWire = 3401, // MENU NEW ENTITY - BUILD - WIRE + OpFace = 3402, // MENU NEW ENTITY - BUILD - FACE + OpShell = 3403, // MENU NEW ENTITY - BUILD - SHELL + OpSolid = 3404, // MENU NEW ENTITY - BUILD - SOLID + OpCompound = 3405, // MENU NEW ENTITY - BUILD - COMPOUND // BooleanGUI ----------------//-------------------------------- - OpFuse = 3500, // MENU OPERATIONS - BOOLEAN - FUSE - OpCommon = 3501, // MENU OPERATIONS - BOOLEAN - COMMON - OpCut = 3502, // MENU OPERATIONS - BOOLEAN - CUT - OpSection = 3503, // MENU OPERATIONS - BOOLEAN - SECTION + OpFuse = 3500, // MENU OPERATIONS - BOOLEAN - FUSE + OpCommon = 3501, // MENU OPERATIONS - BOOLEAN - COMMON + OpCut = 3502, // MENU OPERATIONS - BOOLEAN - CUT + OpSection = 3503, // MENU OPERATIONS - BOOLEAN - SECTION // TransformationGUI ---------//-------------------------------- - OpTranslate = 3600, // MENU OPERATIONS - TRANSFORMATION - TRANSLATION - OpRotate = 3601, // MENU OPERATIONS - TRANSFORMATION - ROTATION - OpChangeLoc = 3602, // MENU OPERATIONS - TRANSFORMATION - LOCATION - OpMirror = 3603, // MENU OPERATIONS - TRANSFORMATION - MIRROR - OpScale = 3604, // MENU OPERATIONS - TRANSFORMATION - SCALE - OpOffset = 3605, // MENU OPERATIONS - TRANSFORMATION - OFFSET - OpMultiTranslate = 3606, // MENU OPERATIONS - TRANSFORMATION - MULTI-TRANSLATION - OpMultiRotate = 3607, // MENU OPERATIONS - TRANSFORMATION - MULTI-ROTATION - OpReimport = 3608, // POPUP MENU - RELOAD IMPORTED - OpProjection = 3609, // MENU OPERATIONS - TRANSFORMATION - PROJECTION + OpTranslate = 3600, // MENU OPERATIONS - TRANSFORMATION - TRANSLATION + OpRotate = 3601, // MENU OPERATIONS - TRANSFORMATION - ROTATION + OpChangeLoc = 3602, // MENU OPERATIONS - TRANSFORMATION - LOCATION + OpMirror = 3603, // MENU OPERATIONS - TRANSFORMATION - MIRROR + OpScale = 3604, // MENU OPERATIONS - TRANSFORMATION - SCALE + OpOffset = 3605, // MENU OPERATIONS - TRANSFORMATION - OFFSET + OpMultiTranslate = 3606, // MENU OPERATIONS - TRANSFORMATION - MULTI-TRANSLATION + OpMultiRotate = 3607, // MENU OPERATIONS - TRANSFORMATION - MULTI-ROTATION + OpReimport = 3608, // POPUP MENU - RELOAD IMPORTED + OpProjection = 3609, // MENU OPERATIONS - TRANSFORMATION - PROJECTION // OperationGUI - OpPartition = 3700, // MENU OPERATION - PARTITION - OpArchimede = 3701, // MENU OPERATION - ARCHIMEDE - OpFillet3d = 3702, // MENU OPERATION - FILLET - OpChamfer = 3703, // MENU OPERATION - CHAMFER - OpShapesOnShape = 3704, // MENU OPERATION - GET SHAPES ON SHAPE - OpFillet2d = 3705, // MENU OPERATION - FILLET 2D - OpFillet1d = 3706, // MENU OPERATION - FILLET 1D - OpClipping = 3707, // MENU OPERATION - CLIPPING RANGE - OpSharedShapes = 3708, // MENU OPERATION - GET SHARED SHAPES + OpPartition = 3700, // MENU OPERATION - PARTITION + OpArchimede = 3701, // MENU OPERATION - ARCHIMEDE + OpFillet3d = 3702, // MENU OPERATION - FILLET + OpChamfer = 3703, // MENU OPERATION - CHAMFER + OpShapesOnShape = 3704, // MENU OPERATION - GET SHAPES ON SHAPE + OpFillet2d = 3705, // MENU OPERATION - FILLET 2D + OpFillet1d = 3706, // MENU OPERATION - FILLET 1D + OpClipping = 3707, // MENU OPERATION - CLIPPING RANGE + OpSharedShapes = 3708, // MENU OPERATION - GET SHARED SHAPES // RepairGUI -----------------//-------------------------------- - OpSewing = 4000, // MENU REPAIR - SEWING - OpSuppressFaces = 4001, // MENU REPAIR - SUPPRESS FACES - OpSuppressHoles = 4002, // MENU REPAIR - SUPPRESS HOLES - OpShapeProcess = 4003, // MENU REPAIR - SHAPE PROCESSING - OpCloseContour = 4004, // MENU REPAIR - CLOSE CONTOUR - OpRemoveIntWires = 4005, // MENU REPAIR - REMOVE INTERNAL WIRES - OpAddPointOnEdge = 4006, // MENU REPAIR - ADD POINT ON EDGE - OpFreeBoundaries = 4007, // MENU MEASURES - FREE BOUNDARIES - OpFreeFaces = 4008, // MENU MEASURES - FREE FACES - OpOrientation = 4009, // MENU REPAIR - CHANGE ORIENTATION - OpGlueFaces = 4010, // MENU REPAIR - GLUE FACES - OpRemoveExtraEdges = 4011, // MENU REPAIR - REMOVE EXTRA EDGES - OpLimitTolerance = 4012, // MENU REPAIR - LIMIT TOLERANCE - OpGlueEdges = 4013, // MENU REPAIR - GLUE EDGES + OpSewing = 4000, // MENU REPAIR - SEWING + OpSuppressFaces = 4001, // MENU REPAIR - SUPPRESS FACES + OpSuppressHoles = 4002, // MENU REPAIR - SUPPRESS HOLES + OpShapeProcess = 4003, // MENU REPAIR - SHAPE PROCESSING + OpCloseContour = 4004, // MENU REPAIR - CLOSE CONTOUR + OpRemoveIntWires = 4005, // MENU REPAIR - REMOVE INTERNAL WIRES + OpAddPointOnEdge = 4006, // MENU REPAIR - ADD POINT ON EDGE + OpFreeBoundaries = 4007, // MENU MEASURES - FREE BOUNDARIES + OpFreeFaces = 4008, // MENU MEASURES - FREE FACES + OpOrientation = 4009, // MENU REPAIR - CHANGE ORIENTATION + OpGlueFaces = 4010, // MENU REPAIR - GLUE FACES + OpRemoveExtraEdges = 4011, // MENU REPAIR - REMOVE EXTRA EDGES + OpLimitTolerance = 4012, // MENU REPAIR - LIMIT TOLERANCE + OpGlueEdges = 4013, // MENU REPAIR - GLUE EDGES // MeasureGUI ----------------//-------------------------------- - OpProperties = 5000, // MENU MEASURES - PROPERTIES - OpCenterMass = 5001, // MENU MEASURES - CENTRE OF MASS - OpInertia = 5002, // MENU MEASURES - INERTIA - OpNormale = 5003, // MENU MEASURES - NORMALE - OpBoundingBox = 5004, // MENU MEASURES - BOUNDING BOX - OpMinDistance = 5005, // MENU MEASURES - MIN DISTANCE - OpAngle = 5006, // MENU MEASURES - ANGLE - OpTolerance = 5007, // MENU MEASURES - TOLERANCE - OpWhatIs = 5008, // MENU MEASURES - WHAT IS - OpCheckShape = 5009, // MENU MEASURES - CHECK - OpCheckCompound = 5010, // MENU MEASURES - CHECK COMPOUND OF BLOCKS - OpPointCoordinates = 5011, // MENU MEASURES - POINT COORDINATES - OpCheckSelfInters = 5012, // MENU MEASURES - CHECK SELF INTERSECTIONS + OpProperties = 5000, // MENU MEASURES - PROPERTIES + OpCenterMass = 5001, // MENU MEASURES - CENTRE OF MASS + OpInertia = 5002, // MENU MEASURES - INERTIA + OpNormale = 5003, // MENU MEASURES - NORMALE + OpBoundingBox = 5004, // MENU MEASURES - BOUNDING BOX + OpMinDistance = 5005, // MENU MEASURES - MIN DISTANCE + OpAngle = 5006, // MENU MEASURES - ANGLE + OpTolerance = 5007, // MENU MEASURES - TOLERANCE + OpWhatIs = 5008, // MENU MEASURES - WHAT IS + OpCheckShape = 5009, // MENU MEASURES - CHECK + OpCheckCompound = 5010, // MENU MEASURES - CHECK COMPOUND OF BLOCKS + OpPointCoordinates = 5011, // MENU MEASURES - POINT COORDINATES + OpCheckSelfInters = 5012, // MENU MEASURES - CHECK SELF INTERSECTIONS // GroupGUI ------------------//-------------------------------- - OpGroupCreate = 6000, // MENU GROUP - CREATE - OpGroupEdit = 6001, // MENU GROUP - EDIT - OpGroupCreatePopup = 6002, // POPUP MENU - CREATE GROUP + OpGroupCreate = 6000, // MENU GROUP - CREATE + OpGroupEdit = 6001, // MENU GROUP - EDIT + OpGroupCreatePopup = 6002, // POPUP MENU - CREATE GROUP // BlocksGUI -----------------//-------------------------------- - OpHexaSolid = 6100, // MENU BLOCKS - HEXAHEDRAL SOLID - OpMultiTransform = 6101, // MENU BLOCKS - MULTI-TRANSFORMATION - OpQuadFace = 6102, // MENU BLOCKS - QUADRANGLE FACE - OpPropagate = 6103, // MENU BLOCKS - PROPAGATE - OpExplodeBlock = 6104, // MENU BLOCKS - EXPLODE ON BLOCKS + OpHexaSolid = 6100, // MENU BLOCKS - HEXAHEDRAL SOLID + OpMultiTransform = 6101, // MENU BLOCKS - MULTI-TRANSFORMATION + OpQuadFace = 6102, // MENU BLOCKS - QUADRANGLE FACE + OpPropagate = 6103, // MENU BLOCKS - PROPAGATE + OpExplodeBlock = 6104, // MENU BLOCKS - EXPLODE ON BLOCKS // AdvancedGUI ---------------//-------------------------------- - OpAdvancedNoOp = 10000, // NO OPERATION (advanced operations base) - OpPipeTShape = 10001, // MENU NEW ENTITY - ADVANCED - PIPE TSHAPE + OpAdvancedNoOp = 10000, // NO OPERATION (advanced operations base) + OpPipeTShape = 10001, // MENU NEW ENTITY - ADVANCED - PIPE TSHAPE // OpPipeTShapeGroups = 10002, // MENU NEW ENTITY - ADVANCED - PIPE TSHAPE GROUPS //@@ insert new functions before this line @@ do not remove this line @@// }; diff --git a/src/GEOMGUI/Makefile.am b/src/GEOMGUI/Makefile.am index bfd12147f..056df6e05 100644 --- a/src/GEOMGUI/Makefile.am +++ b/src/GEOMGUI/Makefile.am @@ -74,6 +74,7 @@ libGEOM_la_CPPFLAGS = \ $(OPENCV_INCLUDES) \ -I$(srcdir)/../OBJECT \ -I$(srcdir)/../GEOMFiltersSelection \ + -I$(srcdir)/../Material \ -I$(srcdir)/../GEOMClient \ -I$(srcdir)/../GEOMImpl \ -I$(top_builddir)/idl \ @@ -82,6 +83,7 @@ libGEOM_la_CPPFLAGS = \ libGEOM_la_LDFLAGS = \ $(PYTHON_LIBS) \ ../GEOMFiltersSelection/libGEOMFiltersSelection.la \ + ../Material/libMaterial.la \ ../GEOMClient/libGEOMClient.la \ ../OBJECT/libGEOMObject.la \ $(KERNEL_LDFLAGS) -lSalomeLifeCycleCORBA -lSalomeNS -lSalomeDSClient \ diff --git a/src/GEOMToolsGUI/GEOMToolsGUI.cxx b/src/GEOMToolsGUI/GEOMToolsGUI.cxx index cc95e6831..f1abd61d0 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI.cxx @@ -349,6 +349,9 @@ bool GEOMToolsGUI::OnGUIEvent(int theCommandID, SUIT_Desktop* parent) case GEOMOp::OpDecrNbIsos: // SHORTCUT - DECREASE NB ISOLINES OnNbIsos( DECR ); break; + case GEOMOp::OpMaterialProperties: // POPUP - MATERIAL PROPERTIES + OnMaterialProperties(); + break; case GEOMOp::OpAutoColor: // POPUP - AUTO COLOR OnAutoColor(); break; diff --git a/src/GEOMToolsGUI/GEOMToolsGUI.h b/src/GEOMToolsGUI/GEOMToolsGUI.h index 12cead468..5706765f0 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI.h +++ b/src/GEOMToolsGUI/GEOMToolsGUI.h @@ -75,6 +75,7 @@ private: void OnUnpublishObject(); void OnPublishObject() ; void OnPointMarker(); + void OnMaterialProperties(); // Shortcut commands void OnChangeTransparency( bool ); diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx index 103a4bcfa..5d2005cc0 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx @@ -31,9 +31,11 @@ #include "GEOMToolsGUI_DeflectionDlg.h" #include "GEOMToolsGUI_MarkerDlg.h" #include "GEOMToolsGUI_PublishDlg.h" +#include "GEOMToolsGUI_MaterialPropertiesDlg.h" #include #include +#include #include #include @@ -518,6 +520,7 @@ void GEOMToolsGUI::OnNbIsos( ActionType actionType ) ic->InitCurrent(); if ( ic->MoreCurrent() ) { Handle(GEOM_AISShape) CurObject = Handle(GEOM_AISShape)::DownCast(ic->Current()); + CurObject->restoreIsoNumbers(); Handle(AIS_Drawer) CurDrawer = CurObject->Attributes(); int UIso = CurDrawer->UIsoAspect()->Number(); @@ -557,16 +560,18 @@ void GEOMToolsGUI::OnNbIsos( ActionType actionType ) CurObject = Handle(GEOM_AISShape)::DownCast(ic->Current()); Handle(AIS_Drawer) CurDrawer = CurObject->Attributes(); - + CurDrawer->SetUIsoAspect( new Prs3d_IsoAspect(Quantity_NOC_GRAY75, Aspect_TOL_SOLID, 0.5 , newNbUIso) ); CurDrawer->SetVIsoAspect( new Prs3d_IsoAspect(Quantity_NOC_GRAY75, Aspect_TOL_SOLID, 0.5 , newNbVIso) ); + + CurObject->storeIsoNumbers(); ic->SetLocalAttributes(CurObject, CurDrawer); ic->Redisplay(CurObject); QString anIsos("%1%2%3");anIsos = anIsos.arg(newNbUIso);anIsos = anIsos.arg(DIGIT_SEPARATOR);anIsos = anIsos.arg(newNbVIso); int aMgrId = window->getViewManager()->getGlobalId(); - aStudy->setObjectProperty(aMgrId ,CurObject->getIO()->getEntry(), "Isos", anIsos); + aStudy->setObjectProperty(aMgrId ,CurObject->getIO()->getEntry(), ISOS_PROP, anIsos); } } GeometryGUI::Modified(); @@ -616,8 +621,10 @@ void GEOMToolsGUI::OnNbIsos( ActionType actionType ) int VIso = 0; vtkActor* anAct = aCollection->GetNextActor(); - if (GEOM_Actor* anActor = GEOM_Actor::SafeDownCast(anAct)) + if (GEOM_Actor* anActor = GEOM_Actor::SafeDownCast(anAct)) { + anActor->RestoreIsoNumbers(); anActor->GetNbIsos(UIso,VIso); + } else return; @@ -656,6 +663,7 @@ void GEOMToolsGUI::OnNbIsos( ActionType actionType ) // There are no casting to needed actor. int aIsos[2]={newNbUIso,newNbVIso}; anActor->SetNbIsos(aIsos); + anActor->StoreIsoNumbers(); QString anIsos("%1%2%3");anIsos = anIsos.arg(newNbUIso);anIsos = anIsos.arg(DIGIT_SEPARATOR);anIsos = anIsos.arg(newNbVIso); int aMgrId = window->getViewManager()->getGlobalId(); @@ -847,6 +855,11 @@ void GEOMToolsGUI::OnPointMarker() dlg.exec(); } +void GEOMToolsGUI::OnMaterialProperties() +{ + GEOMToolsGUI_MaterialPropertiesDlg dlg( SUIT_Session::session()->activeApplication()->desktop() ); + dlg.exec(); +} void GEOMToolsGUI::OnUnpublishObject() { SALOME_ListIO selected; diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_DeflectionDlg.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_DeflectionDlg.cxx index 1e4240103..bc9e9ea63 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI_DeflectionDlg.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI_DeflectionDlg.cxx @@ -23,6 +23,7 @@ // #include "GEOMToolsGUI_DeflectionDlg.h" #include +#include #include #include diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx index bf70a697f..54131a27f 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI_MarkerDlg.cxx @@ -22,6 +22,7 @@ #include "GEOMToolsGUI_MarkerDlg.h" #include +#include #include #include diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.cxx new file mode 100644 index 000000000..9a826cce7 --- /dev/null +++ b/src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.cxx @@ -0,0 +1,1254 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com + +// File : GEOMToolsGUI_MaterialPropertiesDlg.cxx +// Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com) + +#include "GEOMToolsGUI_MaterialPropertiesDlg.h" + +#include "Material_Model.h" +#include "Material_ResourceMgr.h" + +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +// OCCT Includes +#include + +// VTK includes +#include +#include + +// QT Includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MARGIN 9 +#define SPACING 6 + +/*! + \class GEOMToolsGUI_MaterialPropertiesDlg + \brief GEOM material properties dialog box class. + + The dialog box lists all GEOM materials available via the application and allows + user to create own materials. +*/ + +/*! + \brief Constructor + \param parent parent widget +*/ +GEOMToolsGUI_MaterialPropertiesDlg::GEOMToolsGUI_MaterialPropertiesDlg( QWidget* parent ) + : QtxDialog( parent, true, true, OK | Close | Apply | Help), + myResMgr( 0 ) +{ + // Set title + setWindowTitle( tr( "MATERIAL_PROPERTIES_TLT" ) ); + + // Set viewer type + SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() ); + if ( app ) { + SUIT_ViewWindow* window = app->desktop()->activeWindow(); + if ( window && window->getViewManager()->getType() == OCCViewer_Viewer::Type() ) + myViewerType = OCC; + else if ( window && window->getViewManager()->getType() == SVTK_Viewer::Type() ) + myViewerType = VTK; + } + + // Create main layout + QVBoxLayout* main = new QVBoxLayout( mainFrame() ); + main->setMargin( 0 ); main->setSpacing( SPACING ); + + // Create main widgets + myBackMaterialCheck = new QCheckBox( tr( "MATERIAL_BACK_CHK" ), this ); + QFrame* fr = new QFrame( this ); + fr->setFrameStyle( QFrame::Box | QFrame::Sunken ); + + main->addWidget( myBackMaterialCheck ); + main->addWidget( fr ); + + // Create editor widgets + myMaterialList = new QListWidget( fr ); + myMaterialTab = new QTabWidget( fr ); + + QHBoxLayout* frLayout = new QHBoxLayout( fr ); + frLayout->setMargin( MARGIN ); frLayout->setSpacing( SPACING ); + frLayout->addWidget( myMaterialList ); + frLayout->addWidget( myMaterialTab ); + frLayout->setStretchFactor( myMaterialList, 1 ); + frLayout->setStretchFactor( myMaterialTab, 2 ); + + // ======================= Create a tab for front material ======================= + QWidget* w1 = new QWidget( myMaterialTab ); + QVBoxLayout* vLayout1 = new QVBoxLayout( w1 ); + + QGridLayout* gLayout1 = new QGridLayout( w1 ); + gLayout1->setMargin( MARGIN ); gLayout1->setSpacing( SPACING ); + + // ----------------- "Ambient" reflection type group box ----------------- + myAmbientGroupF = new QGroupBox( tr( "AMBIENT_GRP" ), w1 ); + myAmbientGroupF->setCheckable(true); + connect( myAmbientGroupF, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Ambient color + QLabel* ambColorLab1 = new QLabel( tr( "COLOR" ), myAmbientGroupF ); + myAmbientColorF = new QtxColorButton( myAmbientGroupF ); + myAmbientColorF->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( myAmbientColorF, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Ambient coefficient + QLabel* ambCoefficientLab1 = new QLabel( tr( "COEFFICIENT" ), myAmbientGroupF ); + myAmbientCoefntF = new QtxDoubleSpinBox( myAmbientGroupF ); + myAmbientCoefntF->setMaximum(1); + myAmbientCoefntF->setSingleStep(0.05); + connect( myAmbientCoefntF, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Ambient group box layout + QGridLayout* ambientLayout1 = new QGridLayout( myAmbientGroupF ); + ambientLayout1->setMargin( MARGIN ); ambientLayout1->setSpacing( SPACING ); + ambientLayout1->addWidget( ambColorLab1, 0, 0 ); + ambientLayout1->addWidget( myAmbientColorF, 0, 1 ); + ambientLayout1->addWidget( ambCoefficientLab1, 1, 0 ); + ambientLayout1->addWidget( myAmbientCoefntF, 1, 1 ); + + // ----------------- "Diffuse" reflection type group box ----------------- + myDiffuseGroupF = new QGroupBox( tr( "DIFFUSE_GRP" ), w1 ); + myDiffuseGroupF->setCheckable(true); + connect( myDiffuseGroupF, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Diffuse color + QLabel* difColorLab1 = new QLabel( tr( "COLOR" ), myDiffuseGroupF ); + myDiffuseColorF = new QtxColorButton( myDiffuseGroupF ); + myDiffuseColorF->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( myDiffuseColorF, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Diffuse coefficient + QLabel* difCoefficientLab1 = new QLabel( tr( "COEFFICIENT" ), myDiffuseGroupF ); + myDiffuseCoefntF = new QtxDoubleSpinBox( myDiffuseGroupF ); + myDiffuseCoefntF->setMaximum(1); + myDiffuseCoefntF->setSingleStep(0.05); + connect( myDiffuseCoefntF, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Diffuse group box layout + QGridLayout* diffuseLayout1 = new QGridLayout( myDiffuseGroupF ); + diffuseLayout1->setMargin( MARGIN ); diffuseLayout1->setSpacing( SPACING ); + diffuseLayout1->addWidget( difColorLab1, 0, 0 ); + diffuseLayout1->addWidget( myDiffuseColorF, 0, 1 ); + diffuseLayout1->addWidget( difCoefficientLab1, 1, 0 ); + diffuseLayout1->addWidget( myDiffuseCoefntF, 1, 1 ); + + // ----------------- "Specular" reflection type group box ----------------- + mySpecularGroupF = new QGroupBox( tr( "SPECULAR_GRP" ), w1 ); + mySpecularGroupF->setCheckable(true); + connect( mySpecularGroupF, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Specular color + QLabel* specColorLab1 = new QLabel( tr( "COLOR" ), mySpecularGroupF ); + mySpecularColorF = new QtxColorButton( mySpecularGroupF ); + mySpecularColorF->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( mySpecularColorF, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Specular coefficient + QLabel* specCoefficientLab1 = new QLabel( tr( "COEFFICIENT" ), mySpecularGroupF ); + mySpecularCoefntF = new QtxDoubleSpinBox( mySpecularGroupF ); + mySpecularCoefntF->setMaximum(1); + mySpecularCoefntF->setSingleStep(0.05); + connect( mySpecularCoefntF, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Specular group box layout + QGridLayout* specularLayout1 = new QGridLayout( mySpecularGroupF ); + specularLayout1->setMargin( MARGIN ); specularLayout1->setSpacing( SPACING ); + specularLayout1->addWidget( specColorLab1, 0, 0 ); + specularLayout1->addWidget( mySpecularColorF, 0, 1 ); + specularLayout1->addWidget( specCoefficientLab1, 1, 0 ); + specularLayout1->addWidget( mySpecularCoefntF, 1, 1 ); + + // ----------------- "Emission" reflection type group box ----------------- + myEmissionGroupF = new QGroupBox( tr( "EMISSION_GRP" ), w1 ); + myEmissionGroupF->setCheckable(true); + connect( myEmissionGroupF, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Emission color + QLabel* emisColorLab1 = new QLabel( tr( "COLOR" ), myEmissionGroupF ); + myEmissionColorF = new QtxColorButton( myEmissionGroupF ); + myEmissionColorF->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( myEmissionColorF, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Emission coefficient + QLabel* emisCoefficientLab1 = new QLabel( tr( "COEFFICIENT" ), myEmissionGroupF ); + myEmissionCoefntF = new QtxDoubleSpinBox( myEmissionGroupF ); + myEmissionCoefntF->setMaximum(1); + myEmissionCoefntF->setSingleStep(0.05); + connect( myEmissionCoefntF, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Emission group box layout + QGridLayout* emissionLayout1 = new QGridLayout( myEmissionGroupF ); + emissionLayout1->setMargin( MARGIN ); emissionLayout1->setSpacing( SPACING ); + emissionLayout1->addWidget( emisColorLab1, 0, 0 ); + emissionLayout1->addWidget( myEmissionColorF, 0, 1 ); + emissionLayout1->addWidget( emisCoefficientLab1, 1, 0 ); + emissionLayout1->addWidget( myEmissionCoefntF, 1, 1 ); + + // Erase emission group in case of VTK viewer + if ( myViewerType == VTK ) + myEmissionGroupF->hide(); + + // Add group boxes to the main grid layout of the frame with material properties + gLayout1->addWidget( myAmbientGroupF, 0, 0 ); + gLayout1->addWidget( myDiffuseGroupF, 0, 1 ); + gLayout1->addWidget( mySpecularGroupF, 1, 0 ); + gLayout1->addWidget( myEmissionGroupF, 1, 1 ); + + // Shininess + QLabel* shininessLab1 = new QLabel( tr( "SHININESS" ), w1 ); + myShininessF = new QtxDoubleSpinBox( w1 ); + myShininessF->setMaximum(1); + myShininessF->setSingleStep(0.05); + connect( myShininessF, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Shininess layout + QHBoxLayout* shLayout1 = new QHBoxLayout( w1 ); + shLayout1->setMargin( MARGIN ); frLayout->setSpacing( SPACING ); + shLayout1->addWidget( shininessLab1 ); + shLayout1->addWidget( myShininessF ); + + // Fill initial vertical layout of the reflection type group box + vLayout1->addLayout( gLayout1 ); + vLayout1->addLayout( shLayout1 ); + vLayout1->addStretch(); + + // ======================= Create a tab for back material ======================= + myMaterialBWidget = new QWidget( myMaterialTab ); + QVBoxLayout* vLayout2 = new QVBoxLayout( myMaterialBWidget ); + + QGridLayout* gLayout2 = new QGridLayout( myMaterialBWidget ); + gLayout2->setMargin( MARGIN ); gLayout2->setSpacing( SPACING ); + + // ----------------- "Ambient" reflection type group box ----------------- + myAmbientGroupB = new QGroupBox( tr( "AMBIENT_GRP" ), myMaterialBWidget ); + myAmbientGroupB->setCheckable(true); + connect( myAmbientGroupB, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Ambient color + QLabel* ambColorLab2 = new QLabel( tr( "COLOR" ), myAmbientGroupB ); + myAmbientColorB = new QtxColorButton( myAmbientGroupB ); + myAmbientColorB->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( myAmbientColorB, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Ambient coefficient + QLabel* ambCoefficientLab2 = new QLabel( tr( "COEFFICIENT" ), myAmbientGroupB ); + myAmbientCoefntB = new QtxDoubleSpinBox( myAmbientGroupB ); + myAmbientCoefntB->setMaximum(1); + myAmbientCoefntB->setSingleStep(0.05); + connect( myAmbientCoefntB, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Ambient group box layout + QGridLayout* ambientLayout2 = new QGridLayout( myAmbientGroupB ); + ambientLayout2->setMargin( MARGIN ); ambientLayout2->setSpacing( SPACING ); + ambientLayout2->addWidget( ambColorLab2, 0, 0 ); + ambientLayout2->addWidget( myAmbientColorB, 0, 1 ); + ambientLayout2->addWidget( ambCoefficientLab2, 1, 0 ); + ambientLayout2->addWidget( myAmbientCoefntB, 1, 1 ); + + // ----------------- "Diffuse" reflection type group box ----------------- + myDiffuseGroupB = new QGroupBox( tr( "DIFFUSE_GRP" ), myMaterialBWidget ); + myDiffuseGroupB->setCheckable(true); + connect( myDiffuseGroupB, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Diffuse color + QLabel* difColorLab2 = new QLabel( tr( "COLOR" ), myDiffuseGroupB ); + myDiffuseColorB = new QtxColorButton( myDiffuseGroupB ); + myDiffuseColorB->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( myDiffuseColorB, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Diffuse coefficient + QLabel* difCoefficientLab2 = new QLabel( tr( "COEFFICIENT" ), myDiffuseGroupB ); + myDiffuseCoefntB = new QtxDoubleSpinBox( myDiffuseGroupB ); + myDiffuseCoefntB->setMaximum(1); + myDiffuseCoefntB->setSingleStep(0.05); + connect( myDiffuseCoefntB, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Diffuse group box layout + QGridLayout* diffuseLayout2 = new QGridLayout( myDiffuseGroupB ); + diffuseLayout2->setMargin( MARGIN ); diffuseLayout2->setSpacing( SPACING ); + diffuseLayout2->addWidget( difColorLab2, 0, 0 ); + diffuseLayout2->addWidget( myDiffuseColorB, 0, 1 ); + diffuseLayout2->addWidget( difCoefficientLab2, 1, 0 ); + diffuseLayout2->addWidget( myDiffuseCoefntB, 1, 1 ); + + // ----------------- "Specular" reflection type group box ----------------- + mySpecularGroupB = new QGroupBox( tr( "SPECULAR_GRP" ), myMaterialBWidget ); + mySpecularGroupB->setCheckable(true); + connect( mySpecularGroupB, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Specular color + QLabel* specColorLab2 = new QLabel( tr( "COLOR" ), mySpecularGroupB ); + mySpecularColorB = new QtxColorButton( mySpecularGroupB ); + mySpecularColorB->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( mySpecularColorB, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Specular coefficient + QLabel* specCoefficientLab2 = new QLabel( tr( "COEFFICIENT" ), mySpecularGroupB ); + mySpecularCoefntB = new QtxDoubleSpinBox( mySpecularGroupB ); + mySpecularCoefntB->setMaximum(1); + mySpecularCoefntB->setSingleStep(0.05); + connect( mySpecularCoefntB, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Specular group box layout + QGridLayout* specularLayout2 = new QGridLayout( mySpecularGroupB ); + specularLayout2->setMargin( MARGIN ); specularLayout2->setSpacing( SPACING ); + specularLayout2->addWidget( specColorLab2, 0, 0 ); + specularLayout2->addWidget( mySpecularColorB, 0, 1 ); + specularLayout2->addWidget( specCoefficientLab2, 1, 0 ); + specularLayout2->addWidget( mySpecularCoefntB, 1, 1 ); + + // ----------------- "Emission" reflection type group box ----------------- + myEmissionGroupB = new QGroupBox( tr( "EMISSION_GRP" ), myMaterialBWidget ); + myEmissionGroupB->setCheckable(true); + connect( myEmissionGroupB, SIGNAL( toggled( bool ) ), this, SLOT( onReflectionTypeToggled( bool ) ) ); + + // Emission color + QLabel* emisColorLab2 = new QLabel( tr( "COLOR" ), myEmissionGroupB ); + myEmissionColorB = new QtxColorButton( myEmissionGroupB ); + myEmissionColorB->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + connect( myEmissionColorB, SIGNAL( changed( QColor ) ), this, SIGNAL( changed() ) ); + + // Emission coefficient + QLabel* emisCoefficientLab2 = new QLabel( tr( "COEFFICIENT" ), myEmissionGroupB ); + myEmissionCoefntB = new QtxDoubleSpinBox( myEmissionGroupB ); + myEmissionCoefntB->setMaximum(1); + myEmissionCoefntB->setSingleStep(0.05); + connect( myEmissionCoefntB, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Emission group box layout + QGridLayout* emissionLayout2 = new QGridLayout( myEmissionGroupB ); + emissionLayout2->setMargin( MARGIN ); emissionLayout2->setSpacing( SPACING ); + emissionLayout2->addWidget( emisColorLab2, 0, 0 ); + emissionLayout2->addWidget( myEmissionColorB, 0, 1 ); + emissionLayout2->addWidget( emisCoefficientLab2, 1, 0 ); + emissionLayout2->addWidget( myEmissionCoefntB, 1, 1 ); + + // Erase emission group in case of VTK viewer + if ( myViewerType == VTK ) + myEmissionGroupB->hide(); + + // Add group boxes to the main grid layout of the frame with material properties + gLayout2->addWidget( myAmbientGroupB, 0, 0 ); + gLayout2->addWidget( myDiffuseGroupB, 0, 1 ); + gLayout2->addWidget( mySpecularGroupB, 1, 0 ); + gLayout2->addWidget( myEmissionGroupB, 1, 1 ); + + // Shininess + QLabel* shininessLab2 = new QLabel( tr( "SHININESS" ), myMaterialBWidget ); + myShininessB = new QtxDoubleSpinBox( myMaterialBWidget ); + myShininessB->setMaximum(1); + myShininessB->setSingleStep(0.05); + connect( myShininessB, SIGNAL( valueChanged( double ) ), this, SIGNAL( materialChanged() ) ); + + // Shininess layout + QHBoxLayout* shLayout2 = new QHBoxLayout( myMaterialBWidget ); + shLayout2->setMargin( MARGIN ); frLayout->setSpacing( SPACING ); + shLayout2->addWidget( shininessLab2 ); + shLayout2->addWidget( myShininessB ); + + // Fill initial vertical layout of the reflection type group box + vLayout2->addLayout( gLayout2 ); + vLayout2->addLayout( shLayout2 ); + vLayout2->addStretch(); + + // Add tabs to material tab widget + myMaterialTab->addTab( w1, tr( "Front material" ) ); + myMaterialTab->addTab( myMaterialBWidget, tr( "Back material" ) ); + + // Initialize dialog box + setFocusProxy( fr ); + setButtonPosition( Right, Close ); + setDialogFlags( AlignOnce ); + myMaterialList->setEditTriggers( QAbstractItemView::EditKeyPressed ); + + // ! RESOURCES + QStringList globalMaterials = resourceMgr()->materials( Material_ResourceMgr::Global ); + QStringList userMaterials = resourceMgr()->materials( Material_ResourceMgr::User ); + + QListWidgetItem* item; + + // Current material + item = new QListWidgetItem( tr( "[ Current ]" ) ); + item->setForeground( QColor( Qt::red ) ); + item->setData( TypeRole, QVariant( Current ) ); + myMaterialList->addItem( item ); + // Default material + item = new QListWidgetItem( tr( "[ Default ]" ) ); + item->setForeground( QColor( Qt::green ) ); + item->setData( TypeRole, QVariant( Default ) ); + myMaterialList->addItem( item ); + // ! RESOURCES + // Global materials + foreach ( QString sname, globalMaterials ) { + item = new QListWidgetItem( sname ); + item->setForeground( QColor( Qt::blue ) ); + item->setData( TypeRole, QVariant( Global ) ); + item->setData( NameRole, QVariant( sname ) ); + myMaterialList->addItem( item ); + } + // ! RESOURCES + // User materials + foreach ( QString sname, userMaterials ) { + item = new QListWidgetItem( sname ); + item->setData( TypeRole, QVariant( User ) ); + item->setData( NameRole, QVariant( sname ) ); + item->setFlags( item->flags() | Qt::ItemIsEditable ); + myMaterialList->addItem( item ); + } + + // Connect signals + connect( myMaterialTab, SIGNAL( currentChanged( int ) ), + this, SLOT( onCurrentTabChanged( int ) ) ); + connect( myBackMaterialCheck, SIGNAL( toggled( bool ) ), + this, SLOT( onBackMaterialChecked( bool ) ) ); + + connect( myMaterialList, SIGNAL( itemSelectionChanged() ), + this, SLOT( onMaterialChanged() ) ); + connect( myMaterialList, SIGNAL( itemChanged( QListWidgetItem* ) ), + this, SLOT( onItemChanged( QListWidgetItem* ) ) ); + connect( myMaterialList, SIGNAL( itemDoubleClicked( QListWidgetItem* ) ), + this, SLOT( onApply() ) ); + + connect( this, SIGNAL( changed() ), this, SIGNAL( materialChanged() ) ); + connect( this, SIGNAL( materialChanged() ), this, SLOT( onChanged() ) ); + + connect( this, SIGNAL( dlgApply() ), this, SLOT( onApply() ) ); + connect( this, SIGNAL( dlgHelp() ), this, SLOT( onHelp() ) ); + + // Initialize current fornt and back material models of the selected shape + if ( app ) { + LightApp_SelectionMgr* aSelMgr = app->selectionMgr(); + if ( aSelMgr ) { + SalomeApp_Study* aStudy = dynamic_cast(app->activeStudy()); + if( aStudy ) { + SALOME_ListIO selected; + aSelMgr->selectedObjects( selected ); + + Handle(SALOME_InteractiveObject) FirstIOS = selected.First(); + if ( !FirstIOS.IsNull() ) { + SUIT_ViewWindow* window = app->desktop()->activeWindow(); + int aMgrId = window->getViewManager()->getGlobalId(); + + QString aMaterialF; + QString aMaterialB; + + for ( SALOME_ListIteratorOfListIO It( selected ); It.More(); It.Next() ) { + + PropMap aPropMap = aStudy->getObjectPropMap( aMgrId, It.Value()->getEntry() ); + aMaterialF = aPropMap.value(FRONT_MATERIAL_PROP).toString(); + aMaterialB = aPropMap.value(BACK_MATERIAL_PROP).toString(); + + if ( !aMaterialF.isEmpty() ) { + + QStringList aPropsF = aMaterialF.split(DIGIT_SEPARATOR); + + myCurrentModelF = Material_Model::getMaterialModel( aPropsF ); + + if ( !aMaterialB.isEmpty() ) { + QStringList aPropsB = aMaterialB.split(DIGIT_SEPARATOR); + myCurrentModelB = Material_Model::getMaterialModel( aPropsB ); + + myBackMaterialCheck->setChecked( true ); + } + else { + myCurrentModelB = Material_Model::getMaterialModel( aPropsF ); + + myBackMaterialCheck->setChecked( false ); + myMaterialTab->removeTab( 1 ); + } + + break; + } + } + + if ( aMaterialF.isEmpty() ) { + myCurrentModelF = new Material_Model(); + myCurrentModelF->fromResources( SUIT_Session::session()->resourceMgr(), "Geometry" ); + + myCurrentModelB = new Material_Model(); + myCurrentModelB->fromResources( SUIT_Session::session()->resourceMgr(), "Geometry", false ); + } + } + } + } + } + + myMaterialList->setCurrentRow( 0 ); + myMaterialListFId = 0; + myMaterialListBId = 0; + + myIsBTabWasActivated = false; + + myHelpFileName = "material_page.html"; +} + +/*! + \brief Destructor +*/ +GEOMToolsGUI_MaterialPropertiesDlg::~GEOMToolsGUI_MaterialPropertiesDlg() +{ + if ( myCurrentModelF ) + delete myCurrentModelF; + + if ( myCurrentModelB ) + delete myCurrentModelB; +} + +/*! + \brief Called when "OK" button is clicked +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::accept() +{ + onApply(); + QtxDialog::accept(); +} + +/*! + \brief Process key press event + \param e key event +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::keyPressEvent( QKeyEvent* e ) +{ + if ( e->key() == Qt::Key_Delete ) { + QListWidgetItem* item = myMaterialList->currentItem(); + if ( item && item->data( TypeRole ).toInt() == User ) { + if ( QMessageBox::question( this, + tr( "Delete user material" ), + tr( "Remove material %1?" ).arg( item->text() ), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes ) == QMessageBox::Yes ) { + resourceMgr()->remove( item->data( NameRole ).toString() ); + resourceMgr()->save(); + delete item; + } + } + } + QtxDialog::keyPressEvent( e ); +} + +/*! + \brief Get GEOM materials resource manager + \return materials resource manager +*/ +Material_ResourceMgr* GEOMToolsGUI_MaterialPropertiesDlg::resourceMgr() +{ + if ( !myResMgr ) + myResMgr = new Material_ResourceMgr(); + return myResMgr; +} + +/*! + \brief Initialize dialog box fields from material model + \param model material model +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::fromModel( Material_Model* model) +{ + if ( !model ) return; + + bool isReflectionTypeActive; + + if ( isFrontTabActive() ) { // Fill in front material tab + + // Ambient reflection type + isReflectionTypeActive = model->hasAmbientReflection(); + myAmbientGroupF->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load ambient color + myAmbientColorF->setColor( model->color(Material_Model::Ambient) ); + // Load ambient coefficient + myAmbientCoefntF->setValue( model->coefficient(Material_Model::Ambient) ); + } + + // Diffuse reflection type + isReflectionTypeActive = model->hasDiffuseReflection(); + myDiffuseGroupF->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load diffuse color + myDiffuseColorF->setColor( model->color(Material_Model::Diffuse) ); + // Load diffuse coefficient + myDiffuseCoefntF->setValue( model->coefficient(Material_Model::Diffuse) ); + } + + // Specular reflection type + isReflectionTypeActive = model->hasSpecularReflection(); + mySpecularGroupF->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load specular color + mySpecularColorF->setColor( model->color(Material_Model::Specular) ); + // Load specular coefficient + mySpecularCoefntF->setValue( model->coefficient(Material_Model::Specular) ); + } + + // Emission reflection type + isReflectionTypeActive = model->hasEmissionReflection(); + myEmissionGroupF->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load emission color + myEmissionColorF->setColor( model->color(Material_Model::Emission) ); + // Load emission coefficient + myEmissionCoefntF->setValue( model->coefficient(Material_Model::Emission) ); + } + + // Shininess + myShininessF->setValue( model->shininess() ); + + } + else { // Fill in back material tab + + // Ambient reflection type + isReflectionTypeActive = model->hasAmbientReflection(); + myAmbientGroupB->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load ambient color + myAmbientColorB->setColor( model->color(Material_Model::Ambient) ); + // Load ambient coefficient + myAmbientCoefntB->setValue( model->coefficient(Material_Model::Ambient) ); + } + + // Diffuse reflection type + isReflectionTypeActive = model->hasDiffuseReflection(); + myDiffuseGroupB->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load diffuse color + myDiffuseColorB->setColor( model->color(Material_Model::Diffuse) ); + // Load diffuse coefficient + myDiffuseCoefntB->setValue( model->coefficient(Material_Model::Diffuse) ); + } + + // Specular reflection type + isReflectionTypeActive = model->hasSpecularReflection(); + mySpecularGroupB->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load specular color + mySpecularColorB->setColor( model->color(Material_Model::Specular) ); + // Load specular coefficient + mySpecularCoefntB->setValue( model->coefficient(Material_Model::Specular) ); + } + + // Emission reflection type + isReflectionTypeActive = model->hasEmissionReflection(); + myEmissionGroupB->setChecked( isReflectionTypeActive ); + if ( isReflectionTypeActive ) { + // Load emission color + myEmissionColorB->setColor( model->color(Material_Model::Emission) ); + // Load emission coefficient + myEmissionCoefntB->setValue( model->coefficient(Material_Model::Emission) ); + } + + // Shininess + myShininessB->setValue( model->shininess() ); + + } +} + +/*! + \brief Save values from dialog box fields to material model + \param model material model +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::toModel( Material_Model* model ) const +{ + if ( !model ) return; + + if ( isFrontTabActive() ) + toFrontModel( model ); + else + toBackModel( model ); +} + +/*! + \brief Save values from dialog box fields to front material model + \param model front material model to be filled +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::toFrontModel( Material_Model* model ) const +{ + if ( !model ) return; + + // "Ambient" reflection type + if ( myAmbientGroupF->isChecked() ) { + model->setColor( Material_Model::Ambient, myAmbientColorF->color() ); + model->setCoefficient( Material_Model::Ambient, myAmbientCoefntF->value() ); + } + else { + model->removeColor( Material_Model::Ambient ); + model->removeCoefficient( Material_Model::Ambient ); + } + + // "Diffuse" reflection type + if ( myDiffuseGroupF->isChecked() ) { + model->setColor( Material_Model::Diffuse, myDiffuseColorF->color() ); + model->setCoefficient( Material_Model::Diffuse, myDiffuseCoefntF->value() ); + } + else { + model->removeColor( Material_Model::Diffuse ); + model->removeCoefficient( Material_Model::Diffuse ); + } + + // "Specular" reflection type + if ( mySpecularGroupF->isChecked() ) { + model->setColor( Material_Model::Specular, mySpecularColorF->color() ); + model->setCoefficient( Material_Model::Specular, mySpecularCoefntF->value() ); + } + else { + model->removeColor( Material_Model::Specular ); + model->removeCoefficient( Material_Model::Specular ); + } + + // "Emission" reflection type + if ( myEmissionGroupF->isChecked() ) { + model->setColor( Material_Model::Emission, myEmissionColorF->color() ); + model->setCoefficient( Material_Model::Emission, myEmissionCoefntF->value() ); + } + else { + model->removeColor( Material_Model::Emission ); + model->removeCoefficient( Material_Model::Emission ); + } + + // Shininess + model->setShininess( myShininessF->value() ); +} + +/*! + \brief Save values from dialog box fields to back material model + \param model back material model to be filled +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::toBackModel( Material_Model* model ) const +{ + if ( !model ) + return; + + // "Ambient" reflection type + if ( myAmbientGroupB->isChecked() ) { + model->setColor( Material_Model::Ambient, myAmbientColorB->color() ); + model->setCoefficient( Material_Model::Ambient, myAmbientCoefntB->value() ); + } + else { + model->removeColor( Material_Model::Ambient ); + model->removeCoefficient( Material_Model::Ambient ); + } + + // "Diffuse" reflection type + if ( myDiffuseGroupB->isChecked() ) { + model->setColor( Material_Model::Diffuse, myDiffuseColorB->color() ); + model->setCoefficient( Material_Model::Diffuse, myDiffuseCoefntB->value() ); + } + else { + model->removeColor( Material_Model::Diffuse ); + model->removeCoefficient( Material_Model::Diffuse ); + } + + // "Specular" reflection type + if ( mySpecularGroupB->isChecked() ) { + model->setColor( Material_Model::Specular, mySpecularColorB->color() ); + model->setCoefficient( Material_Model::Specular, mySpecularCoefntB->value() ); + } + else { + model->removeColor( Material_Model::Specular ); + model->removeCoefficient( Material_Model::Specular ); + } + + // "Emission" reflection type + if ( myEmissionGroupB->isChecked() ) { + model->setColor( Material_Model::Emission, myEmissionColorB->color() ); + model->setCoefficient( Material_Model::Emission, myEmissionCoefntB->value() ); + } + else { + model->removeColor( Material_Model::Emission ); + model->removeCoefficient( Material_Model::Emission ); + } + + // Shininess + model->setShininess( myShininessB->value() ); +} + +/*! + \brief Find unique name for the material name + \param name material name template + \param item if not 0, used to be ignored when browsing through items list + \param addSuffix if \c true, the integrer suffix is always added to the material name (otherwise + suffix is added only if item name is not unique) + \return new unique material name +*/ +QString GEOMToolsGUI_MaterialPropertiesDlg::findUniqueName( const QString& name, QListWidgetItem* item, bool addSuffix ) +{ + bool found = false; + int idx = 0; + for( int i = 2; i < myMaterialList->count(); i++ ) { + if ( item == myMaterialList->item( i ) ) continue; + QString iname = myMaterialList->item( i )->text(); + if ( iname == name ) { + found = true; + } + else { + iname = iname.mid( name.length() ).trimmed(); + bool ok = false; + int nx = iname.toInt( &ok ); + if ( ok ) idx = qMax( idx, nx ); + } + } + return found || addSuffix ? QString( "%1 %2" ).arg( name ).arg( idx+1 ) : name; +} + +/*! + \brief Check if tab with front material properties is currently active + \return true if front material tab is active +*/ +bool GEOMToolsGUI_MaterialPropertiesDlg::isFrontTabActive() const +{ + return ( myMaterialTab->currentIndex() == 0 ? true : false ); +} + +/*! + \brief Called when "Apply" button is pressed +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onApply() +{ + // save user materials + resourceMgr()->save(); + + toFrontModel( myCurrentModelF ); + if ( myBackMaterialCheck->isChecked() && myIsBTabWasActivated ) + toBackModel( myCurrentModelB ); + + SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() ); + if ( !app ) + return; + LightApp_SelectionMgr* aSelMgr = app->selectionMgr(); + if ( !aSelMgr ) + return; + + SalomeApp_Study* aStudy = dynamic_cast(app->activeStudy()); + + if(!aStudy) + return; + + SALOME_ListIO selected; + aSelMgr->selectedObjects( selected ); + if ( selected.IsEmpty() ) + return; + + Handle(SALOME_InteractiveObject) FirstIOS = selected.First(); + if ( FirstIOS.IsNull() ) + return; + + SUIT_ViewWindow* window = app->desktop()->activeWindow(); + int aMgrId = window->getViewManager()->getGlobalId(); + + // Parse material properties and form a string for persistent purpose + QString aMaterialF = myCurrentModelF->getMaterialProperty(); + QString aMaterialB; + if ( myBackMaterialCheck->isChecked() ) + aMaterialB = myCurrentModelB->getMaterialProperty(); + + if ( myViewerType == VTK ) { + // Get material properties from the current model + /* + vtkProperty* aPropertyF; + if ( !unsetMaterial ) + aPropertyF = myCurrentModelF->getMaterialVTKProperty(); + */ + vtkProperty* aPropertyF = myCurrentModelF->getMaterialVTKProperty(); + vtkProperty* aPropertyB = aPropertyF; + if ( myBackMaterialCheck->isChecked() ) + aPropertyB = myCurrentModelB->getMaterialVTKProperty(); + + SVTK_ViewWindow* vtkVW = dynamic_cast( window ); + if ( !vtkVW ) + return; + SVTK_View* aView = vtkVW->getView(); + + SUIT_OverrideCursor(); + for ( SALOME_ListIteratorOfListIO It( selected ); It.More(); It.Next() ) { + + /* + if ( unsetMaterial || aMaterialF.isEmpty() ) + // Unset material for the selected shape + aisShape->UnsetMaterial(); + else + // Set material for the selected shape + */ + aView->SetMaterial( It.Value(), aPropertyF, aPropertyB ); + + // Persistent + aStudy->setObjectProperty( aMgrId, It.Value()->getEntry(), FRONT_MATERIAL_PROP, aMaterialF ); + aStudy->setObjectProperty( aMgrId, It.Value()->getEntry(), BACK_MATERIAL_PROP, aMaterialB ); + } // for... + aView->Repaint(); + GeometryGUI::Modified(); + } // if ( VTK ) + + else if ( myViewerType == OCC ) { + // Get material properties from the current model + /* + Graphic3d_MaterialAspect aMatF; + if ( !unsetMaterial ) + aMatF = myCurrentModelF->getMaterialOCCAspect(); + */ + Graphic3d_MaterialAspect aMatF = myCurrentModelF->getMaterialOCCAspect(); + Graphic3d_MaterialAspect aMatB = aMatF; + if ( myBackMaterialCheck->isChecked() ) + aMatB = myCurrentModelB->getMaterialOCCAspect(); + + Handle(GEOM_AISShape) aisShape; + + SUIT_OverrideCursor(); + OCCViewer_Viewer* vm = dynamic_cast( window->getViewManager()->getViewModel() ); + if ( !vm ) + return; + + GEOMBase* gb = new GEOMBase(); + + Handle(AIS_InteractiveContext) ic = vm->getAISContext(); + for ( SALOME_ListIteratorOfListIO It( selected ); It.More(); It.Next() ) { + aisShape = gb->ConvertIOinGEOMAISShape( It.Value(), true ); + if ( !aisShape.IsNull() ) { + + if(!aisShape->HasInteractiveContext()) + aisShape->SetContext(ic); + + /* + if ( unsetMaterial || aMaterialF.isEmpty() ) + // Unset material for the selected shape + aisShape->UnsetMaterial(); + else + */ + if ( myBackMaterialCheck->isChecked() ) { + // Set front material for the selected shape + aisShape->SetCurrentFacingModel(Aspect_TOFM_FRONT_SIDE); + aisShape->SetMaterial(aMatF); + // Set back material for the selected shape + aisShape->SetCurrentFacingModel(Aspect_TOFM_BACK_SIDE); + aisShape->SetMaterial(aMatB); + // Return to the default facing mode + aisShape->SetCurrentFacingModel(Aspect_TOFM_BOTH_SIDE); + } + else { + // Set the same front and back (is equal to front) materials for the selected shape + aisShape->SetMaterial(aMatF); + } + + if (aisShape->DisplayMode() != AIS_Shaded/*aisShape->DisplayMode() == GEOM_AISShape::ShadingWithEdges*/) + ic->RecomputePrsOnly( aisShape, Standard_False ); + + // Persistent + aStudy->setObjectProperty( aMgrId, It.Value()->getEntry(), FRONT_MATERIAL_PROP, aMaterialF ); + aStudy->setObjectProperty( aMgrId, It.Value()->getEntry(), BACK_MATERIAL_PROP, aMaterialB ); + } + } // for... + ic->UpdateCurrentViewer(); + GeometryGUI::Modified(); + } // if ( OCC ) +} + +/*! + \brief Called when "Help" button is pressed +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onHelp() +{ + LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication()); + if (app) { + GeometryGUI* aGeomGUI = dynamic_cast( app->module( "Geometry" ) ); + app->onHelpContextModule(aGeomGUI ? app->moduleName(aGeomGUI->moduleName()) : QString(""), myHelpFileName); + } + else { + QString platform; +#ifdef WIN32 + platform = "winapplication"; +#else + platform = "application"; +#endif + SUIT_MessageBox::warning(0, QObject::tr("WRN_WARNING"), + QObject::tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE"). + arg(app->resourceMgr()->stringValue("ExternalBrowser", platform)).arg(myHelpFileName), + QObject::tr("BUT_OK")); + } +} + +/*! + \brief Called when user check/uncheck "Enable back material" check box + \param theIsChecked the check state of the check box +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onBackMaterialChecked( bool theIsChecked ) +{ + if ( theIsChecked ) { + // Tab with back material properties is displayed + myMaterialTab->addTab( myMaterialBWidget, tr( "Back material" ) ); + + // Create a current model of back material + if ( !myCurrentModelB ) { + myCurrentModelB = new Material_Model(); + myCurrentModelB->fromResources( SUIT_Session::session()->resourceMgr(), "Geometry", false ); + } + + myMaterialListBId = 0; + } + else { + // Tab with back material properties is hidden + myMaterialTab->removeTab( 1 ); + + // Remove the current model for back material + if ( myCurrentModelB ) { + delete myCurrentModelB; + myCurrentModelB = 0; + } + } +} + +/*! + \brief Called when user activates material tab + \param theIndex the index of the tab which was activated by the user +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onCurrentTabChanged(int theIndex) +{ + blockSignals( true ); + + // Change selection in the list of materials + if ( isFrontTabActive() ) + myMaterialList->setCurrentRow( myMaterialListFId ); + else if ( myBackMaterialCheck->isChecked() ) + myMaterialList->setCurrentRow( myMaterialListBId ); + + if ( theIndex == 1 ) + myIsBTabWasActivated = true; + + blockSignals( false ); + + onMaterialChanged(); +} + +/*! + \brief Called when user selects any material item in the materials list +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onMaterialChanged() +{ + blockSignals( true ); + + QListWidgetItem* item = myMaterialList->currentItem(); + int type = item->data( TypeRole ).toInt(); + + Material_Model* model = 0; + + bool isFrontTab = isFrontTabActive(); + + if ( isFrontTab ) + myMaterialListFId = myMaterialList->currentRow(); + else + myMaterialListBId = myMaterialList->currentRow(); + + switch ( type ) { + case Current: + // current material + model = ( isFrontTab ? myCurrentModelF : myCurrentModelB ); + break; + case Default: + // default material + model = new Material_Model(); + model->fromResources( SUIT_Session::session()->resourceMgr(), "Geometry", ( isFrontTab ? true : false ) ); + break; + case Global: + case User: + // global material, user material + model = new Material_Model(); + model->fromResources( resourceMgr(), item->data( NameRole ).toString() ); + break; + default: + break; + } + + fromModel( model ); + if ( type != Current ) + delete model; + + blockSignals( false ); +} + +/*! + \brief Called when any material parameter is changed by the user +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onChanged() +{ + QListWidgetItem* item = myMaterialList->currentItem(); + int type = item->data( TypeRole ).toInt(); + + bool isFrontTab = isFrontTabActive(); + + // for the current and user schemas do not perform any actions + if ( type == Current ) { + Material_Model model = ( isFrontTab ? *( myCurrentModelF ) : *( myCurrentModelB ) ); + toModel( &model ); + model.save( 0, QString(), isFrontTab ); + blockSignals( true ); + fromModel( &model ); + blockSignals( false ); + } + else if ( type == User ) { + Material_Model model; + toModel( &model ); + QString oldName = item->data( NameRole ).toString(), newName = item->text(); + if ( oldName == newName ) { + model.save( resourceMgr(), oldName, isFrontTab ); + } + else { + resourceMgr()->remove( oldName ); + model.save( resourceMgr(), newName, isFrontTab ); + item->setData( NameRole, newName ); + } + blockSignals( true ); + fromModel( &model ); + blockSignals( false ); + } + else { + // if user tries to change global (or default, or no material) material, + // we create a new user material basing on selected one + QString newName = findUniqueName( tr( "CUSTOM_MATERIAL" ), 0, true ); + item = new QListWidgetItem( newName ); + item->setData( TypeRole, QVariant( User ) ); + item->setData( NameRole, QVariant( newName ) ); + item->setFlags( item->flags() | Qt::ItemIsEditable ); + myMaterialList->addItem( item ); + + Material_Model model; + toModel( &model ); + model.save( resourceMgr(), newName, isFrontTab ); + + myMaterialList->setCurrentItem( item ); + + if ( isFrontTab ) + myMaterialListFId = myMaterialList->currentRow(); + else + myMaterialListBId = myMaterialList->currentRow(); + + } +} + +/*! + \brief Called when user material is renamed by the user +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onItemChanged( QListWidgetItem* item ) +{ + QString newName = item->text(); + QString uniqueName = findUniqueName( newName, item ); + if ( uniqueName != newName ) { + myMaterialList->blockSignals( true ); + item->setText( uniqueName ); + myMaterialList->blockSignals( false ); + } + onChanged(); +} + +/*! + \brief Called when widget effect is changed +*/ +void GEOMToolsGUI_MaterialPropertiesDlg::onReflectionTypeToggled( bool theIsOn ) +{ + QGroupBox* anObj = (QGroupBox*)sender(); + + // Set an empty values for color and coefficient + // of the checked/unchecked reflection type + QColor c; + + + // Make changes on front material tab + if ( anObj == myAmbientGroupF ) { + myAmbientColorF->setColor( c ); + myAmbientCoefntF->setValue( 0.0 ); + } + else if ( anObj == myDiffuseGroupF ) { + myDiffuseColorF->setColor( c ); + myDiffuseCoefntF->setValue( 0.0 ); + } + else if ( anObj == mySpecularGroupF ) { + mySpecularColorF->setColor( c ); + mySpecularCoefntF->setValue( 0.0 ); + } + else if ( anObj == myEmissionGroupF ) { + myEmissionColorF->setColor( c ); + myEmissionCoefntF->setValue( 0.0 ); + } + + // Make changes on back material tab + if ( anObj == myAmbientGroupB ) { + myAmbientColorB->setColor( c ); + myAmbientCoefntB->setValue( 0.0 ); + } + else if ( anObj == myDiffuseGroupB ) { + myDiffuseColorB->setColor( c ); + myDiffuseCoefntB->setValue( 0.0 ); + } + else if ( anObj == mySpecularGroupB ) { + mySpecularColorB->setColor( c ); + mySpecularCoefntB->setValue( 0.0 ); + } + else if ( anObj == myEmissionGroupB ) { + myEmissionColorB->setColor( c ); + myEmissionCoefntB->setValue( 0.0 ); + } + + emit( changed() ); +} diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.h b/src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.h new file mode 100644 index 000000000..77c4b263c --- /dev/null +++ b/src/GEOMToolsGUI/GEOMToolsGUI_MaterialPropertiesDlg.h @@ -0,0 +1,163 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : GEOMToolsGUI_MaterialPropertiesDlg.h +// Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com) +// +#ifndef GEOMTOOLSGUI_MATERIALPROPERTIESDLG_H +#define GEOMTOOLSGUI_MATERIALPROPERTIESDLG_H + +#include "GEOM_ToolsGUI.hxx" + +#include +#include +#include + +class QCheckBox; +class QGroupBox; +class QLabel; +class QListWidget; +class QListWidgetItem; +class QPushButton; +class QSpinBox; +class QTabWidget; + +class QtxColorButton; +class QtxDoubleSpinBox; + +class Material_Model; +class Material_ResourceMgr; + +class GEOMTOOLSGUI_EXPORT GEOMToolsGUI_MaterialPropertiesDlg : public QtxDialog +{ + Q_OBJECT + + enum { Current, Default, Global, User }; + enum { TypeRole = Qt::UserRole + 123, NameRole }; + + //! Enumeration of viewer types + typedef enum { + OCC, //!< OCC viewer + VTK //!< VTK viewer + } ViewerType; + +public: + GEOMToolsGUI_MaterialPropertiesDlg( QWidget* = 0 ); + ~GEOMToolsGUI_MaterialPropertiesDlg(); + + void accept(); + +protected: + void keyPressEvent( QKeyEvent* ); + +private: + Material_ResourceMgr* resourceMgr(); + + void fromModel( Material_Model* ); + void toModel( Material_Model* ) const; + void toFrontModel( Material_Model* ) const; + void toBackModel( Material_Model* ) const; + + QString findUniqueName( const QString&, + QListWidgetItem* = 0, + bool = false ); + + bool isFrontTabActive() const; + +signals: + void materialChanged(); + void changed(); + +private slots: + + void onApply(); + void onHelp(); + + void onBackMaterialChecked( bool ); + void onCurrentTabChanged( int ); + void onMaterialChanged(); + void onChanged(); + void onItemChanged( QListWidgetItem* ); + void onReflectionTypeToggled( bool ); + +private: + + Material_ResourceMgr* myResMgr; + + QCheckBox* myBackMaterialCheck; + + //! Current material model for front material + Material_Model* myCurrentModelF; + + //! Current material model for back material + Material_Model* myCurrentModelB; + + QListWidget* myMaterialList; + int myMaterialListFId; + int myMaterialListBId; + + QTabWidget* myMaterialTab; + QWidget* myMaterialBWidget; + bool myIsBTabWasActivated; + + //! Controls defining front material properties + QGroupBox* myAmbientGroupF; + QtxColorButton* myAmbientColorF; + QtxDoubleSpinBox* myAmbientCoefntF; + + QGroupBox* myDiffuseGroupF; + QtxColorButton* myDiffuseColorF; + QtxDoubleSpinBox* myDiffuseCoefntF; + + QGroupBox* mySpecularGroupF; + QtxColorButton* mySpecularColorF; + QtxDoubleSpinBox* mySpecularCoefntF; + + QGroupBox* myEmissionGroupF; + QtxColorButton* myEmissionColorF; + QtxDoubleSpinBox* myEmissionCoefntF; + + QtxDoubleSpinBox* myShininessF; + + //! Controls defining back material properties + QGroupBox* myAmbientGroupB; + QtxColorButton* myAmbientColorB; + QtxDoubleSpinBox* myAmbientCoefntB; + + QGroupBox* myDiffuseGroupB; + QtxColorButton* myDiffuseColorB; + QtxDoubleSpinBox* myDiffuseCoefntB; + + QGroupBox* mySpecularGroupB; + QtxColorButton* mySpecularColorB; + QtxDoubleSpinBox* mySpecularCoefntB; + + QGroupBox* myEmissionGroupB; + QtxColorButton* myEmissionColorB; + QtxDoubleSpinBox* myEmissionCoefntB; + + QtxDoubleSpinBox* myShininessB; + + QString myHelpFileName; + + ViewerType myViewerType; + +}; + +#endif // GEOMTOOLSGUI_MATERIALPROPERTIESDLG_H diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_TransparencyDlg.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_TransparencyDlg.cxx index 3447f1f97..2de71038a 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI_TransparencyDlg.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI_TransparencyDlg.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/src/GEOMToolsGUI/Makefile.am b/src/GEOMToolsGUI/Makefile.am index 0404e787c..63afb84f2 100644 --- a/src/GEOMToolsGUI/Makefile.am +++ b/src/GEOMToolsGUI/Makefile.am @@ -35,7 +35,8 @@ salomeinclude_HEADERS = \ GEOMToolsGUI_TransparencyDlg.h \ GEOMToolsGUI_DeleteDlg.h \ GEOMToolsGUI_MarkerDlg.h \ - GEOMToolsGUI_PublishDlg.h + GEOMToolsGUI_PublishDlg.h \ + GEOMToolsGUI_MaterialPropertiesDlg.h dist_libGEOMToolsGUI_la_SOURCES = \ GEOMToolsGUI.cxx \ @@ -45,7 +46,8 @@ dist_libGEOMToolsGUI_la_SOURCES = \ GEOMToolsGUI_DeflectionDlg.cxx \ GEOMToolsGUI_DeleteDlg.cxx \ GEOMToolsGUI_MarkerDlg.cxx \ - GEOMToolsGUI_PublishDlg.cxx + GEOMToolsGUI_PublishDlg.cxx \ + GEOMToolsGUI_MaterialPropertiesDlg.cxx MOC_FILES = \ GEOMToolsGUI_TransparencyDlg_moc.cxx \ @@ -53,7 +55,8 @@ MOC_FILES = \ GEOMToolsGUI_DeflectionDlg_moc.cxx \ GEOMToolsGUI_DeleteDlg_moc.cxx \ GEOMToolsGUI_MarkerDlg_moc.cxx \ - GEOMToolsGUI_PublishDlg_moc.cxx + GEOMToolsGUI_PublishDlg_moc.cxx \ + GEOMToolsGUI_MaterialPropertiesDlg_moc.cxx nodist_libGEOMToolsGUI_la_SOURCES = \ $(MOC_FILES) @@ -72,6 +75,7 @@ libGEOMToolsGUI_la_CPPFLAGS = \ $(CORBA_INCLUDES) \ -I$(srcdir)/../OBJECT \ -I$(srcdir)/../GEOMBase \ + -I$(srcdir)/../Material \ -I$(srcdir)/../GEOMGUI \ -I$(srcdir)/../GEOMClient \ -I$(srcdir)/../GEOMImpl \ @@ -79,5 +83,6 @@ libGEOMToolsGUI_la_CPPFLAGS = \ libGEOMToolsGUI_la_LDFLAGS = \ ../GEOMBase/libGEOMBase.la \ + ../Material/libMaterial.la \ ../GEOMGUI/libGEOM.la \ $(GUI_LDFLAGS) -lVTKViewer -lOCCViewer -lsuit -lSalomeApp -lPyConsole diff --git a/src/Makefile.am b/src/Makefile.am index 243974ffa..ad025e3cc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,7 +32,7 @@ if WITH_OPENCV endif if GEOM_ENABLE_GUI - SUBDIRS += OBJECT DlgRef GEOMFiltersSelection GEOMGUI GEOMBase GEOMToolsGUI \ + SUBDIRS += OBJECT DlgRef GEOMFiltersSelection Material GEOMGUI GEOMBase GEOMToolsGUI \ DisplayGUI BasicGUI PrimitiveGUI GenerationGUI EntityGUI BuildGUI \ BooleanGUI TransformationGUI OperationGUI RepairGUI MeasureGUI \ GroupGUI BlocksGUI AdvancedGUI GEOM_SWIG_WITHIHM diff --git a/src/Material/Makefile.am b/src/Material/Makefile.am new file mode 100644 index 000000000..5c1931345 --- /dev/null +++ b/src/Material/Makefile.am @@ -0,0 +1,51 @@ +# Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# File : Makefile.am +# Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com) +# Package : Material +# +include $(top_srcdir)/adm_local/unix/make_common_starter.am + +# Libraries targets +lib_LTLIBRARIES = libMaterial.la + +# header files +salomeinclude_HEADERS = \ + Material.h \ + Material_Model.h \ + Material_ResourceMgr.h + +dist_libMaterial_la_SOURCES = \ + Material_Model.cxx \ + Material_ResourceMgr.cxx + +# additional information to compile and link file +libMaterial_la_CPPFLAGS = \ + $(QT_INCLUDES) \ + $(VTK_INCLUDES) \ + $(CAS_CPPFLAGS) \ + $(KERNEL_CXXFLAGS) \ + $(GUI_CXXFLAGS) \ + -I$(srcdir)/../OBJECT + +libMaterial_la_LDFLAGS = \ + $(GUI_LDFLAGS) -lVTKViewer -lOCCViewer -lsuit -lSalomeApp + +dist_salomeres_DATA = resources/SalomeMaterial.xml diff --git a/src/Material/Material.h b/src/Material/Material.h new file mode 100644 index 000000000..3f7a39b3a --- /dev/null +++ b/src/Material/Material.h @@ -0,0 +1,36 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : Material.h +// Author : Margarita KARPUNINA, Open CASCADE S.A.S. +// +#ifndef MATERIAL_H +#define MATERIAL_H + +#if defined WIN32 +# if defined MATERIAL_SALOME_EXPORTS || defined MATERIAL_EXPORTS || defined SalomeMaterial_EXPORTS +# define MATERIAL_SALOME_EXPORT _declspec( dllexport ) +# else +# define MATERIAL_SALOME_EXPORT _declspec( dllimport ) +# endif +#else +# define MATERIAL_SALOME_EXPORT +#endif + +#endif // MATERIAL_H diff --git a/src/Material/Material_Model.cxx b/src/Material/Material_Model.cxx new file mode 100644 index 000000000..e41c1df68 --- /dev/null +++ b/src/Material/Material_Model.cxx @@ -0,0 +1,682 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : Material_Model.cxx +// Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com) +// + +#include "Material_Model.h" +#include "Material_ResourceMgr.h" + +#include + +#include +#include +#include + +// OCCT Includes +#include + +// VTK includes +#include + +/*! + \brief Constructor + + Create new SALOME material model with default properties. +*/ +Material_Model::Material_Model() + : myResourceMgr( 0 ) +{ + myShininess = 0.0; +} + +/*! + \brief Destructor +*/ +Material_Model::~Material_Model() +{ +} + +/*! + \brief Construct material model according to the given list of + material properties + + \param theProps the list of material properties + \return material model object with correspondent properties + \sa getMaterialProperty() +*/ +Material_Model* Material_Model::getMaterialModel( QStringList theProps ) +{ + Material_Model* aModel = new Material_Model(); + + foreach ( QString aProp, theProps ) { + if ( aProp.isNull() ) continue; + + // Set current ambient color + aModel->setColor( aProp, "AmbientColor=", Material_Model::Ambient ); + // Set current ambient coefficient + aModel->setCoefficient( aProp, "AmbientCoefficient=", Material_Model::Ambient ); + + // Set current diffuse color + aModel->setColor( aProp, "DiffuseColor=", Material_Model::Diffuse ); + // Set current diffuse coefficient + aModel->setCoefficient( aProp, "DiffuseCoefficient=", Material_Model::Diffuse ); + + // Set current specular color + aModel->setColor( aProp, "SpecularColor=", Material_Model::Specular ); + // Set current specular coefficient + aModel->setCoefficient( aProp, "SpecularCoefficient=", Material_Model::Specular ); + + // Set current emission color + aModel->setColor( aProp, "EmissionColor=", Material_Model::Emission ); + // Set current emission coefficient + aModel->setCoefficient( aProp, "EmissionCoefficient=", Material_Model::Emission ); + + // Set current shininess + QString aPropName = "Shininess="; + int anId = aProp.indexOf(aPropName); + if ( anId != -1 ) { + bool ok; + double aCoef = aProp.right( aProp.length() - (anId+aPropName.length()) ).toDouble(&ok); + if ( ok ) + aModel->setShininess( aCoef ); + } + } + + return aModel; +} + +/*! + \brief Construct string of material properties for this model object + + \return a string representing a set of material properties + \sa getMaterialModel() +*/ +QString Material_Model::getMaterialProperty() +{ + // Parse material properties of the current model and form a string for persistent purpose + QString aMaterial; + + bool isReflectionTypeActive; + QColor c; + double coef; + + // Ambient reflection + isReflectionTypeActive = hasAmbientReflection(); + if ( isReflectionTypeActive ) { + c = color( Material_Model::Ambient ); + coef = coefficient(Material_Model::Ambient); + // Insert properties into persistent string + aMaterial = "AmbientColor=%1%2AmbientCoefficient=%3"; + aMaterial = aMaterial.arg( Qtx::colorToString(c) ); + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( coef ); + } + // Diffuse reflection + isReflectionTypeActive = hasDiffuseReflection(); + if ( isReflectionTypeActive ) { + c = color( Material_Model::Diffuse ); + coef = coefficient(Material_Model::Diffuse); + // Insert properties into persistent string + aMaterial += "%1DiffuseColor=%2%3DiffuseCoefficient=%4"; + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( Qtx::colorToString(c) ); + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( coef ); + } + // Specular reflection + isReflectionTypeActive = hasSpecularReflection(); + if ( isReflectionTypeActive ) { + c = color( Material_Model::Specular ); + coef = coefficient(Material_Model::Specular); + // Insert properties into persistent string + aMaterial += "%1SpecularColor=%2%3SpecularCoefficient=%4"; + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( Qtx::colorToString(c) ); + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( coef ); + } + // Emission reflection + isReflectionTypeActive = hasEmissionReflection(); + if ( isReflectionTypeActive ) { + c = color( Material_Model::Emission ); + coef = coefficient(Material_Model::Emission); + // Insert properties into persistent string + aMaterial += "%1EmissionColor=%2%3EmissionCoefficient=%4"; + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( Qtx::colorToString(c) ); + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( coef ); + } + if ( !aMaterial.isEmpty() ) { + // Shininess + // Insert properties into persistent string + aMaterial += "%1Shininess=%2"; + aMaterial = aMaterial.arg( DIGIT_SEPARATOR ); + aMaterial = aMaterial.arg( shininess() ); + } + + return aMaterial; +} + +/*! + \brief Construct OCCT material aspect object based on the current model + + \return material aspect object with correspondent properties +*/ +Graphic3d_MaterialAspect Material_Model::getMaterialOCCAspect() +{ + // Get material aspect from the current model + Graphic3d_MaterialAspect aMat; + + bool isReflectionTypeActive; + QColor c; + double coef; + + // Ambient reflection + isReflectionTypeActive = hasAmbientReflection(); + if ( isReflectionTypeActive ) { + aMat.SetReflectionModeOn( Graphic3d_TOR_AMBIENT ); + c = color( Material_Model::Ambient ); + aMat.SetAmbientColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) ); + coef = coefficient( Material_Model::Ambient ); + aMat.SetAmbient( coef ); + } + // Diffuse reflection + isReflectionTypeActive = hasDiffuseReflection(); + if ( isReflectionTypeActive ) { + aMat.SetReflectionModeOn( Graphic3d_TOR_DIFFUSE ); + c = color( Material_Model::Diffuse ); + aMat.SetDiffuseColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) ); + coef = coefficient( Material_Model::Diffuse ); + aMat.SetDiffuse( coef ); + } + // Specular reflection + isReflectionTypeActive = hasSpecularReflection(); + if ( isReflectionTypeActive ) { + aMat.SetReflectionModeOn( Graphic3d_TOR_SPECULAR ); + c = color( Material_Model::Specular ); + aMat.SetSpecularColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) ); + coef = coefficient( Material_Model::Specular ); + aMat.SetSpecular( coef ); + } + // Emission reflection + isReflectionTypeActive = hasEmissionReflection(); + if ( isReflectionTypeActive ) { + aMat.SetReflectionModeOn( Graphic3d_TOR_EMISSION ); + c = color( Material_Model::Emission ); + aMat.SetEmissiveColor( Quantity_Color( c.redF(), c.greenF(), c.blueF(), Quantity_TOC_RGB ) ); + coef = coefficient( Material_Model::Emission ); + aMat.SetEmissive( coef ); + } + // Shininess + aMat.SetShininess( shininess() ); + + return aMat; +} + +/*! + \brief Construct VTK property with properties of material based on the current model + + \return VTK property with correspondent material properties +*/ +vtkProperty* Material_Model::getMaterialVTKProperty() +{ + // Get material properties from the current model + vtkProperty* aProperty = vtkProperty::New(); + + bool isReflectionTypeActive; + QColor c; + double coef; + + // Ambient reflection + isReflectionTypeActive = hasAmbientReflection(); + if ( isReflectionTypeActive ) { + c = color( Material_Model::Ambient ); + aProperty->SetAmbientColor( c.redF(), c.greenF(), c.blueF() ); //SalomeApp_Tools::color( c ) + coef = coefficient( Material_Model::Ambient ); + aProperty->SetAmbient( coef ); + } + // Diffuse reflection + isReflectionTypeActive = hasDiffuseReflection(); + if ( isReflectionTypeActive ) { + c = color( Material_Model::Diffuse ); + aProperty->SetDiffuseColor( c.redF(), c.greenF(), c.blueF() ); + coef = coefficient( Material_Model::Diffuse ); + aProperty->SetDiffuse( coef ); + } + // Specular reflection + isReflectionTypeActive = hasSpecularReflection(); + if ( isReflectionTypeActive ) { + c = color( Material_Model::Specular ); + aProperty->SetSpecularColor( c.redF(), c.greenF(), c.blueF() ); + coef = coefficient( Material_Model::Specular ); + aProperty->SetSpecular( coef ); + } + // Shininess + aProperty->SetSpecularPower( shininess()*100.0 ); + + return aProperty; +} + +/*! + \brief Initialize material model with default values +*/ +void Material_Model::initDefaults() +{ + // Set default ambient color + setColor( Ambient, "#333333" ); + // Set default ambient coefficient + setCoefficient( Ambient, 0.3 ); + + // Set default diffuse color + setColor( Diffuse, "#000000" ); + // Set default diffuse coefficient + setCoefficient( Diffuse, 0.65 ); + + // Set default specular color + setColor( Specular, "#ffffff" ); + // Set default specular coefficient + setCoefficient( Specular, 0.0 ); + + // Set default shininess + setShininess( 0.039 ); +} + +/*! + \brief Clear current content of this material model +*/ +void Material_Model::clearModel() +{ + myColors.clear(); + myCoefficients.clear(); + myShininess = 0.0; +} + +/*! + \brief Initialize material model from the resources + + This function can be used to retrieve material properties from the resource file(s). + Note, that paremeters \a theResMgr and \a theResSection are stored by the model to be used + later with save() method. + + \param theResMgr resources manager + \param theResSection resources section name + \sa save() +*/ +void Material_Model::fromResources( QtxResourceMgr* theResMgr, + const QString& theResSection, + bool theIsFront ) +{ + // Clear current content of the model + // before setting properties from resources + clearModel(); + + myResourceMgr = theResMgr; + myResourceSection = theResSection; + + // init from resource manager + if ( !resourceMgr() ) + return; + + if ( theResSection.compare( "Geometry" ) == 0 ) { + if ( theIsFront ) { + myResourceSection = theResMgr->stringValue("Geometry", "front_material", "Gold"); + } + else { + myResourceSection = theResMgr->stringValue("Geometry", "back_material", ""); + if ( myResourceSection.isEmpty() ) + myResourceSection = theResMgr->stringValue("Geometry", "front_material", "Gold"); + } + + myResourceMgr = new Material_ResourceMgr(); + } + + QString section = resourceSection( theIsFront ); + + // If there is no material preference in XML files, + // use the default material hardcoded in material model + if ( section.isEmpty() ) { + initDefaults(); + return; + } + + // Set ambient color + if ( resourceMgr()->hasValue( section, "ambient-color" ) ) { + setColor( Ambient, resourceMgr()->colorValue( section, "ambient-color" ) ); + } + // Set ambient coefficient + if ( resourceMgr()->hasValue( section, "ambient-coefficient" ) ) { + setCoefficient( Ambient, resourceMgr()->doubleValue( section, "ambient-coefficient" ) ); + } + + // Set diffuse color + if ( resourceMgr()->hasValue( section, "diffuse-color" ) ) { + setColor( Diffuse, resourceMgr()->colorValue( section, "diffuse-color" ) ); + } + // Set diffuse coefficient + if ( resourceMgr()->hasValue( section, "diffuse-coefficient" ) ) { + setCoefficient( Diffuse, resourceMgr()->doubleValue( section, "diffuse-coefficient" ) ); + } + + // Set specular color + if ( resourceMgr()->hasValue( section, "specular-color" ) ) { + setColor( Specular, resourceMgr()->colorValue( section, "specular-color" ) ); + } + // Set specular coefficient + if ( resourceMgr()->hasValue( section, "specular-coefficient" ) ) { + setCoefficient( Specular, resourceMgr()->doubleValue( section, "specular-coefficient" ) ); + } + + // Set emission color + if ( resourceMgr()->hasValue( section, "emission-color" ) ) { + setColor( Emission, resourceMgr()->colorValue( section, "emission-color" ) ); + } + // Set emission coefficient + if ( resourceMgr()->hasValue( section, "emission-coefficient" ) ) { + setCoefficient( Emission, resourceMgr()->doubleValue( section, "emission-coefficient" ) ); + } + + // Set shininess + if ( resourceMgr()->hasValue( section, "shininess" ) ) { + setShininess( resourceMgr()->doubleValue( section, "shininess" ) ); + } +} + +/*! + \brief Save material properties to the resource file. + + If paremeters \a theResMgr and \a theResSection are not specified, default ones + (those passed to the fromResources() function) are used instead. + + \param theResMgr resources manager + \param theResSection resources section name + \sa fromResources() +*/ +void Material_Model::save( QtxResourceMgr* theResMgr, + const QString& theResSection, + bool theIsFront ) +{ + if ( !theResMgr ) + theResMgr = resourceMgr(); + if ( !theResMgr ) + return; + + QString section = theResSection.isEmpty() ? resourceSection( theIsFront ) : theResSection; + myResourceSection = section; + + if ( hasAmbientReflection() ) { + // Save ambient color + theResMgr->setValue( section, "ambient-color", color( Ambient ) ); + // Save ambient coefficient + theResMgr->setValue( section, "ambient-coefficient", coefficient( Ambient ) ); + } + else { + // Remove ambient color + theResMgr->remove( section, "ambient-color" ); + // Remove ambient coefficient + theResMgr->remove( section, "ambient-coefficient" ); + } + + if ( hasDiffuseReflection() ) { + // Save diffuse color + theResMgr->setValue( section, "diffuse-color", color( Diffuse ) ); + // Save diffuse coefficient + theResMgr->setValue( section, "diffuse-coefficient", coefficient( Diffuse ) ); + } + else { + // Remove diffuse color + theResMgr->remove( section, "diffuse-color" ); + // Remove diffuse coefficient + theResMgr->remove( section, "diffuse-coefficient" ); + } + + if ( hasSpecularReflection() ) { + // Save specular color + theResMgr->setValue( section, "specular-color", color( Specular ) ); + // Save specular coefficient + theResMgr->setValue( section, "specular-coefficient", coefficient( Specular ) ); + } + else { + // Remove specular color + theResMgr->remove( section, "specular-color" ); + // Remove specular coefficient + theResMgr->remove( section, "specular-coefficient" ); + } + + if ( hasEmissionReflection() ) { + // Save emission color + theResMgr->setValue( section, "emission-color", color( Emission ) ); + // Save emission coefficient + theResMgr->setValue( section, "emission-coefficient", coefficient( Emission ) ); + } + else { + // Remove emission color + theResMgr->remove( section, "emission-color" ); + // Remove emission coefficient + theResMgr->remove( section, "emission-coefficient" ); + } + + // Save shininess + theResMgr->setValue( section, "shininess", shininess() ); +} + +/*! + \brief Get resource manager used by this material model. + + \return pointer to the resource manager passed previously to the fromResources() method + \sa fromResources(), resourceSection() +*/ +QtxResourceMgr* Material_Model::resourceMgr() const +{ + return myResourceMgr; +} + +/*! + \brief Get resources section name + + If section name is empty, default material name from "Geometry" section + is returned ("front_material" or "back_material" is used depending on + the parameter value) + + \param theIsFront the flag indicating that section of front or back material + is required + \return resource section name passed previously to the fromResources() method + \sa fromResources(), resourceMgr() +*/ +QString Material_Model::resourceSection( bool theIsFront ) const +{ + return !myResourceSection.isEmpty() ? myResourceSection : + SUIT_Session::session()->resourceMgr()->stringValue("Geometry", + ( theIsFront ? "front_material" : "back_material" ), + "Gold"); +} + +/*! + \brief Check if ambient reflection type is defined for this material + + \return true if ambient reflection type is defined for this material, + false - otherwise +*/ +bool Material_Model::hasAmbientReflection() +{ + return ( !myColors.isEmpty() && myColors.contains(Ambient) || !myCoefficients.isEmpty() && myCoefficients.contains(Ambient) ); +} + +/*! + \brief Check if diffuse reflection type is defined for this material + + \return true if diffuse reflection type is defined for this material, + false - otherwise +*/ +bool Material_Model::hasDiffuseReflection() +{ + return ( !myColors.isEmpty() && myColors.contains(Diffuse) || !myCoefficients.isEmpty() && myCoefficients.contains(Diffuse) ); +} + +/*! + \brief Check if specular reflection type is defined for this material + + \return true if specular reflection type is defined for this material, + false - otherwise +*/ +bool Material_Model::hasSpecularReflection() +{ + return ( !myColors.isEmpty() && myColors.contains(Specular) || !myCoefficients.isEmpty() && myCoefficients.contains(Specular) ); +} + +/*! + \brief Check if emission reflection type is defined for this material + + \return true if emission reflection type is defined for this material, + false - otherwise +*/ +bool Material_Model::hasEmissionReflection() +{ + return ( !myColors.isEmpty() && myColors.contains(Emission) || !myCoefficients.isEmpty() && myCoefficients.contains(Emission) ); +} + +/*! + \brief Get color value for the given reflection type + \param theReflectionType reflection type + \return a color which should be used by the given reflection type + \sa setColor() +*/ +QColor Material_Model::color( ReflectionType theReflectionType ) const +{ + return myColors[ theReflectionType ]; +} + +/*! + \brief Set color value for the given reflection type + + \param theReflectionType reflection type + \param theColor a color to be used by the given reflection type + \sa color() +*/ +void Material_Model::setColor( ReflectionType theReflectionType, + const QColor& theColor ) +{ + myColors[ theReflectionType ] = theColor; +} + +/*! + \brief Set color of the current material from the given string + \param theProp the considered property + \param theColorName the name of the color property + \param theReflectionType the type of reflection +*/ +void Material_Model::setColor( QString theProp, + QString theColorName, + ReflectionType theReflectionType ) +{ + int anId = theProp.indexOf( theColorName ); + if ( anId != -1 ) { + QColor c; + if ( Qtx::stringToColor( theProp.right( theProp.length() - ( anId + theColorName.length() ) ), c ) ) + setColor( theReflectionType, c ); + } +} + +/*! + \brief Remove color value for the given reflection type + + \param theReflectionType reflection type + \sa color(), setColor() +*/ +void Material_Model::removeColor( ReflectionType theReflectionType ) +{ + myColors.remove( theReflectionType ); +} + +/*! + \brief Get coefficient value for the given reflection type + \param theReflectionType reflection type + \return a coefficient which should be used by the given reflection type + \sa setCoefficient() +*/ +double Material_Model::coefficient( ReflectionType theReflectionType ) const +{ + return myCoefficients[ theReflectionType ]; +} + +/*! + \brief Set coefficient value for the given reflection type + + \param theReflectionType reflection type + \param theCoefficient a coefficient to be used by the given reflection type + \sa coefficient() +*/ +void Material_Model::setCoefficient( ReflectionType theReflectionType, + double theCoefficient ) +{ + myCoefficients[ theReflectionType ] = theCoefficient; +} + +/*! + \brief Set coefficient of the current material from the given string + \param theProp the considered property + \param theCoefName the name of the color property + \param theReflectionType the type of reflection +*/ +void Material_Model::setCoefficient( QString theProp, + QString theCoefName, + ReflectionType theReflectionType ) +{ + int anId = theProp.indexOf( theCoefName ); + if ( anId != -1 ) { + bool ok; + double aCoef = theProp.right( theProp.length() - ( anId + theCoefName.length() ) ).toDouble( &ok ); + if ( ok ) + setCoefficient( theReflectionType, aCoef ); + } +} + +/*! + \brief Remove coefficient value for the given reflection type + + \param theReflectionType reflection type + \sa coefficient(), setCoefficient() +*/ +void Material_Model::removeCoefficient( ReflectionType theReflectionType ) +{ + myCoefficients.remove( theReflectionType ); +} + +/*! + \brief Get shininess value + \return a shininess value of this material + \sa setShininess() +*/ +double Material_Model::shininess() const +{ + return myShininess; +} + +/*! + \brief Set shininess value + + \param theShininess a shininess value of this material + \sa shininess() +*/ +void Material_Model::setShininess( double theShininess) +{ + myShininess = theShininess; +} diff --git a/src/Material/Material_Model.h b/src/Material/Material_Model.h new file mode 100644 index 000000000..8543e7a5c --- /dev/null +++ b/src/Material/Material_Model.h @@ -0,0 +1,108 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : Material_Model.h +// Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com) +// +#ifndef MATERIAL_MODEL_H +#define MATERIAL_MODEL_H + +#include "Material.h" + +#include +#include +#include + +class Graphic3d_MaterialAspect; + +class vtkProperty; + +class QtxResourceMgr; + +class MATERIAL_SALOME_EXPORT Material_Model +{ + +public: + + //! Enumeration of reflection types of material + typedef enum { + Ambient, //!< Ambient + Diffuse, //!< Diffuse + Specular, //!< Specular + Emission //!< Emission + } ReflectionType; + + + Material_Model(); + virtual ~Material_Model(); + + static Material_Model* getMaterialModel( QStringList ); + + QString getMaterialProperty(); + + Graphic3d_MaterialAspect getMaterialOCCAspect(); + vtkProperty* getMaterialVTKProperty(); + + void initDefaults(); + void fromResources( QtxResourceMgr*, const QString& = QString(), bool theIsFront = true ); + void save( QtxResourceMgr* = 0, const QString& = QString(), bool theIsFront = true ); + + QtxResourceMgr* resourceMgr() const; + QString resourceSection( bool theIsFront ) const; + + bool hasAmbientReflection(); + bool hasDiffuseReflection(); + bool hasSpecularReflection(); + bool hasEmissionReflection(); + + QColor color( ReflectionType ) const; + void setColor( ReflectionType, const QColor& ); + void setColor( QString, + QString, + ReflectionType ); + void removeColor( ReflectionType ); + + double coefficient( ReflectionType ) const; + void setCoefficient( ReflectionType, double ); + void setCoefficient( QString, + QString, + ReflectionType ); + void removeCoefficient( ReflectionType ); + + double shininess() const; + void setShininess( double ); + +private: + void clearModel(); + +private: + typedef QMap ColorMap; + typedef QMap CoefficientMap; + + QtxResourceMgr* myResourceMgr; + QString myResourceSection; + + ColorMap myColors; + CoefficientMap myCoefficients; + + double myShininess; + +}; + +#endif // MATERIAL_MODEL_H diff --git a/src/Material/Material_ResourceMgr.cxx b/src/Material/Material_ResourceMgr.cxx new file mode 100644 index 000000000..ccb2cd427 --- /dev/null +++ b/src/Material/Material_ResourceMgr.cxx @@ -0,0 +1,407 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : Material_ResourceMgr.cxx +// Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com) +// +#include "Material_ResourceMgr.h" + +//#include "Qtx.h" // used to print colors of global materials +//#include // used to print colors of global materials + +/*! + \class Material_ResourceMgr + \brief Material properties resources manager. + + This class is used to manage the material properties throughout the application + in the similar way as QtxResourceMgr does it with application preferences. + + Standard material types are stored in the global application settings files + (named as SalomeMaterial.xml). User-defined materials are stored in user's home + directory - in the file .SalomeMaterialrc. + + The Material_ResourceMgr class is used by material properties dialog box + (GEOMToolsGUI_MaterialPropertiesDlg class). +*/ + +/*! + \brief Constructor +*/ +Material_ResourceMgr::Material_ResourceMgr() + : QtxResourceMgr( "SalomeMaterial", "%1Config" ) +{ + if ( dirList().isEmpty() && ::getenv( "GEOM_ROOT_DIR" ) ) + setDirList( QStringList() << Qtx::addSlash( ::getenv( "GEOM_ROOT_DIR" ) ) + "share/salome/resources/geom" ); + setCurrentFormat( "xml" ); + + /* + // Get string equivalent for colors of global materials ----> + QColor c; + QString s; + + // 1. ============= Plastic + std::cout << "---- Plastic:" << std::endl; + // ambient + c.setRgbF(0.2, 0.2, 0.2); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.0, 0.0, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 2. ============= Shiny plastic + std::cout << "---- Shiny plastic:" << std::endl; + // ambient + c.setRgbF(0.2, 0.2, 0.2); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.0, 0.0, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 3. ============= Satin + std::cout << "---- Satin:" << std::endl; + // ambient + c.setRgbF(0.2, 0.2, 0.2); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.0, 0.0, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 4. ============= Metal + std::cout << "---- Metal:" << std::endl; + // diffuse + c.setRgbF(0.0, 0.0, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 5. ============= Brass + std::cout << "---- Brass:" << std::endl; + // ambient + c.setRgbF(0.329412, 0.223529, 0.027451); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.780392, 0.568627, 0.113725); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.992157, 0.941176, 0.807843); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 6. ============= Bronze + std::cout << "---- Bronze:" << std::endl; + // ambient + c.setRgbF(0.2125, 0.1275, 0.054); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.714, 0.4284, 0.18144); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.393548, 0.271906, 0.166721); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 7. ============= Copper + std::cout << "---- Copper:" << std::endl; + // ambient + c.setRgbF(0.33, 0.26, 0.23); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.50, 0.11, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.95, 0.73, 0.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 8. ============= Gold + std::cout << "---- Gold:" << std::endl; + // ambient + c.setRgbF(1.0, 0.76862745, 0.31764706); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(1.0, 0.69, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 0.98, 0.78); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 9. ============= Pewter + std::cout << "---- Pewter:" << std::endl; + // ambient + c.setRgbF(0.105882, 0.058824, 0.113725); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.427451, 0.470588, 0.541176); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.333333, 0.333333, 0.521569); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 10. ============= Plaster + std::cout << "---- Plaster:" << std::endl; + // ambient + c.setRgbF(0.19225, 0.19225, 0.19225); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.50754, 0.50754, 0.50754); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.508273, 0.508273, 0.508273); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 11. ============= Silver + std::cout << "---- Silver:" << std::endl; + // ambient + c.setRgbF(0.19225, 0.19225, 0.19225); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.50754, 0.50754, 0.50754); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.508273, 0.508273, 0.508273); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 12. ============= Steel + std::cout << "---- Steel:" << std::endl; + // ambient + c.setRgbF(0.2, 0.2, 0.2); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.0, 0.0, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 13. ============= Stone + std::cout << "---- Stone:" << std::endl; + // ambient + c.setRgbF(1.0, 0.8, 0.62); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(1.0, 0.8, 0.62); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.98, 1.0, 0.60); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 14. ============= Chrome + std::cout << "---- Chrome:" << std::endl; + // ambient + c.setRgbF(0.35, 0.35, 0.35); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.4, 0.4, 0.4); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.974597, 0.974597, 0.974597); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 15. ============= Neon + std::cout << "---- Neon:" << std::endl; + // ambient + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + // emissive + c.setRgbF(0.0, 1.0, 0.46); + s = Qtx::colorToString( c ); + std::cout << " emissive color: " << s.toStdString().c_str() << std::endl; + + // 16. ============= Aluminium + std::cout << "---- Aluminium:" << std::endl; + // ambient + c.setRgbF(0.30, 0.30, 0.30); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.30, 0.30, 0.30); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.70, 0.70, 0.80); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 17. ============= Obsidian + std::cout << "---- Obsidian:" << std::endl; + // ambient + c.setRgbF(0.05375, 0.05, 0.06625); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.18275, 0.17, 0.22525); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.332741, 0.328634, 0.346435); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 18. ============= Jade + std::cout << "---- Jade:" << std::endl; + // ambient + c.setRgbF(0.135, 0.2225, 0.1575); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.54, 0.89, 0.63); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(0.316228, 0.316228, 0.316228); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // 19. ============= Default material + std::cout << "---- Default material:" << std::endl; + // ambient + c.setRgbF(0.2, 0.2, 0.2); + s = Qtx::colorToString( c ); + std::cout << " ambient color: " << s.toStdString().c_str() << std::endl; + // diffuse + c.setRgbF(0.0, 0.0, 0.0); + s = Qtx::colorToString( c ); + std::cout << " diffuse color: " << s.toStdString().c_str() << std::endl; + // specular + c.setRgbF(1.0, 1.0, 1.0); + s = Qtx::colorToString( c ); + std::cout << " specular color: " << s.toStdString().c_str() << std::endl; + + // Get string equivalent for colors of global materials <---- + */ +} + +/*! + \brief Destructor +*/ +Material_ResourceMgr::~Material_ResourceMgr() +{ +} + +/*! + \brief Get list of avaiable materials + \param theType material type + \param theSort if \c true (default), returns a list of materials sorted by name + \return list of avaiable materials names +*/ +QStringList Material_ResourceMgr::materials( MaterialType theType, bool theSort ) +{ + QStringList sl; + + WorkingMode m = workingMode(); + + switch ( theType ) { + case Global: + setWorkingMode( IgnoreUserValues ); + sl = sections(); + break; + case User: + { + setWorkingMode( AllowUserValues ); + sl = sections(); + setWorkingMode( IgnoreUserValues ); + QMutableListIterator it( sl ); + while ( it.hasNext() ) { + QString s = it.next(); + if ( hasSection( s ) ) it.remove(); + } + } + break; + case All: + setWorkingMode( AllowUserValues ); + sl = sections(); + break; + default: + break; + } + + setWorkingMode( m ); + + if ( theSort ) + qSort( sl ); + + return sl; +} + +/*! + \brief Get list of materials names for preferences dialog + \return list of materials names +*/ +QStringList Material_ResourceMgr::getPreferenceMaterialsNames() +{ + QStringList aMaterialsList = materials( Material_ResourceMgr::All ); + return aMaterialsList; +} diff --git a/src/Material/Material_ResourceMgr.h b/src/Material/Material_ResourceMgr.h new file mode 100644 index 000000000..a78203320 --- /dev/null +++ b/src/Material/Material_ResourceMgr.h @@ -0,0 +1,49 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : Material_ResourceMgr.h +// Author : Margarita KARPUNINA, Open CASCADE S.A.S. (margarita.karpunina@opencascade.com) +// +#ifndef MATERIAL_RESOURCEMGR_H +#define MATERIAL_RESOURCEMGR_H + +#include "Material.h" + +#include + +class MATERIAL_SALOME_EXPORT Material_ResourceMgr : public QtxResourceMgr +{ +public: + //! Material type + typedef enum { + Global, //!< Global materials + User, //!< User materials + All //!< All materials + } MaterialType; + + Material_ResourceMgr(); + ~Material_ResourceMgr(); + + QStringList materials( MaterialType = All, bool = true ); + + QStringList getPreferenceMaterialsNames(); + +}; + +#endif // MATERIAL_RESOURCEMGR_H diff --git a/src/Material/resources/SalomeMaterial.xml b/src/Material/resources/SalomeMaterial.xml new file mode 100644 index 000000000..9741ce641 --- /dev/null +++ b/src/Material/resources/SalomeMaterial.xml @@ -0,0 +1,187 @@ + + +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    + + + + + + + +
    +
    diff --git a/src/OBJECT/GEOM_AISShape.cxx b/src/OBJECT/GEOM_AISShape.cxx index 7a945dc23..dfd5bdb24 100644 --- a/src/OBJECT/GEOM_AISShape.cxx +++ b/src/OBJECT/GEOM_AISShape.cxx @@ -45,9 +45,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -130,6 +132,13 @@ GEOM_AISShape::GEOM_AISShape(const TopoDS_Shape& shape, : SALOME_AISShape(shape), myName(aName), myDisplayVectors(false) { myShadingColor = Quantity_Color( Quantity_NOC_GOLDENROD ); + + storeBoundaryColors(); + + myEdgesInShadingColor = Quantity_Color( Quantity_NOC_GOLDENROD ); + + myUIsoNumber = -1; + myVIsoNumber = -1; } void GEOM_AISShape::setIO(const Handle(SALOME_InteractiveObject)& io){ @@ -170,38 +179,19 @@ void GEOM_AISShape::Compute(const Handle(PrsMgr_PresentationManager3d)& aPresent switch (aMode) { case 0://StdSelect_DM_Wireframe: { + restoreIsoNumbers(); + + // Restore wireframe edges colors + restoreBoundaryColors(); + StdPrs_WFDeflectionShape::Add(aPrs,myshape,myDrawer); break; } case 1://StdSelect_DM_Shading: { - myDrawer->ShadingAspect()->Aspect()->SetDistinguishOn(); - - Graphic3d_MaterialAspect aMatAspect; - aMatAspect.SetAmbient( 0.5 ); - aMatAspect.SetDiffuse( 0.5 ); - aMatAspect.SetEmissive( 0.5 ); - aMatAspect.SetShininess(0.5 ); - aMatAspect.SetSpecular( 0.5 ); - - myDrawer->ShadingAspect()->Aspect()->SetFrontMaterial(aMatAspect); - myDrawer->ShadingAspect()->Aspect()->SetBackMaterial(Graphic3d_NOM_JADE); - - Graphic3d_MaterialAspect FMat = myDrawer->ShadingAspect()->Aspect()->FrontMaterial(); - Graphic3d_MaterialAspect BMat = myDrawer->ShadingAspect()->Aspect()->BackMaterial(); - FMat.SetTransparency(myTransparency); BMat.SetTransparency(myTransparency); - myDrawer->ShadingAspect()->Aspect()->SetFrontMaterial(FMat); - myDrawer->ShadingAspect()->Aspect()->SetBackMaterial(BMat); - - //Handle(Graphic3d_AspectFillArea3d) a4bis = myDrawer->ShadingAspect()->Aspect(); - // P->SetPrimitivesAspect(a4bis); - // G->SetGroupPrimitivesAspect(a4bis); - //a4bis->SetInteriorColor(myShadingColor); - myDrawer->ShadingAspect()->SetColor(myShadingColor); + restoreIsoNumbers(); - // PAL12113: AIS_Shape::Compute() works correctly with shapes containing no faces - //StdPrs_ShadedShape::Add(aPrs,myshape,myDrawer); - AIS_Shape::Compute(aPresentationManager, aPrs, aMode); + shadingMode(aPresentationManager, aPrs, aMode); break; } case 3: //StdSelect_DM_HLR: @@ -211,6 +201,34 @@ void GEOM_AISShape::Compute(const Handle(PrsMgr_PresentationManager3d)& aPresent } } + if ( aMode == ShadingWithEdges ) { + // Temporary store number of iso lines in order to recover its later + // when display mode is achnged to 'Wirefame' or 'Shading'. + // Iso lines are not displayed in 'Shading with edges' mode. + storeIsoNumbers(); + + // Reset number of iso lines to 0 + resetIsoNumbers(); + + //Shaded faces + shadingMode(aPresentationManager, aPrs, AIS_Shaded); + + // Store wireframe edges colors + storeBoundaryColors(); + + // Coloring edges + Handle(Prs3d_LineAspect) anAspect = myDrawer->UnFreeBoundaryAspect(); + anAspect->SetColor( myEdgesInShadingColor ); + myDrawer->SetUnFreeBoundaryAspect( anAspect ); + + anAspect = myDrawer->FreeBoundaryAspect(); + anAspect->SetColor( myEdgesInShadingColor ); + myDrawer->SetFreeBoundaryAspect( anAspect ); + + // Add edges to presentation + StdPrs_WFDeflectionShape::Add(aPrs,myshape,myDrawer); + } + if (isShowVectors()) { const bool isVector = IsKind(STANDARD_TYPE(GEOM_AISVector)); @@ -282,6 +300,11 @@ void GEOM_AISShape::SetShadingColor(const Quantity_Color &aCol) myShadingColor = aCol; } +void GEOM_AISShape::SetEdgesInShadingColor(const Quantity_Color &aCol) +{ + myEdgesInShadingColor = aCol; +} + void GEOM_AISShape::highlightSubShapes(const TColStd_IndexedMapOfInteger& aIndexMap, const Standard_Boolean aHighlight ) { @@ -317,3 +340,92 @@ void GEOM_AISShape::SetDisplayVectors(bool isDisplayed) { myDisplayVectors = isDisplayed; } + +void GEOM_AISShape::shadingMode(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager, + const Handle(Prs3d_Presentation)& aPrs, + const Standard_Integer aMode) +{ + myDrawer->ShadingAspect()->Aspect()->SetDistinguishOn(); + + Graphic3d_MaterialAspect aMatAspect; + if ( !HasMaterial() ) { + aMatAspect.SetAmbient( 0.5 ); + aMatAspect.SetDiffuse( 0.5 ); + aMatAspect.SetEmissive( 0.5 ); + aMatAspect.SetShininess(0.5 ); + aMatAspect.SetSpecular( 0.5 ); + + myDrawer->ShadingAspect()->Aspect()->SetFrontMaterial(aMatAspect); + myDrawer->ShadingAspect()->Aspect()->SetBackMaterial(Graphic3d_NOM_JADE); + } + + Graphic3d_MaterialAspect FMat = myDrawer->ShadingAspect()->Aspect()->FrontMaterial(); + Graphic3d_MaterialAspect BMat = myDrawer->ShadingAspect()->Aspect()->BackMaterial(); + FMat.SetTransparency(myTransparency); BMat.SetTransparency(myTransparency); + myDrawer->ShadingAspect()->Aspect()->SetFrontMaterial(FMat); + myDrawer->ShadingAspect()->Aspect()->SetBackMaterial(BMat); + + //Handle(Graphic3d_AspectFillArea3d) a4bis = myDrawer->ShadingAspect()->Aspect(); + // P->SetPrimitivesAspect(a4bis); + // G->SetGroupPrimitivesAspect(a4bis); + //a4bis->SetInteriorColor(myShadingColor); + myDrawer->ShadingAspect()->SetColor(myShadingColor); + + // PAL12113: AIS_Shape::Compute() works correctly with shapes containing no faces + //StdPrs_ShadedShape::Add(aPrs,myshape,myDrawer); + AIS_Shape::Compute(aPresentationManager, aPrs, aMode); +} + +void GEOM_AISShape::storeIsoNumbers() +{ + myUIsoNumber = myDrawer->UIsoAspect()->Number(); + myVIsoNumber = myDrawer->VIsoAspect()->Number(); +} + +void GEOM_AISShape::restoreIsoNumbers() +{ + if ( myUIsoNumber > 0 ) { + // Restore number of U iso lines + Handle(Prs3d_IsoAspect) anAspect = myDrawer->UIsoAspect(); + anAspect->SetNumber( myUIsoNumber ); + myDrawer->SetUIsoAspect( anAspect ); + } + + if ( myVIsoNumber > 0 ) { + // Restore number of V iso lines + Handle(Prs3d_IsoAspect) anAspect = myDrawer->VIsoAspect(); + anAspect->SetNumber( myVIsoNumber ); + myDrawer->SetVIsoAspect( anAspect ); + } +} + +void GEOM_AISShape::resetIsoNumbers() +{ + Handle(Prs3d_IsoAspect) anAspect = myDrawer->UIsoAspect(); + anAspect->SetNumber( 0 ); + myDrawer->SetUIsoAspect( anAspect ); + + anAspect = myDrawer->VIsoAspect(); + anAspect->SetNumber( 0 ); + myDrawer->SetVIsoAspect( anAspect ); +} + +void GEOM_AISShape::storeBoundaryColors() +{ + Aspect_TypeOfLine aLT; + Standard_Real aW; + + myDrawer->FreeBoundaryAspect()->Aspect()->Values( myFreeBoundaryColor, aLT, aW); + myDrawer->UnFreeBoundaryAspect()->Aspect()->Values( myUnFreeBoundaryColor, aLT, aW); +} + +void GEOM_AISShape::restoreBoundaryColors() +{ + Handle(Prs3d_LineAspect) anAspect = myDrawer->FreeBoundaryAspect(); + anAspect->SetColor( myFreeBoundaryColor ); + myDrawer->SetFreeBoundaryAspect( anAspect ); + + anAspect = myDrawer->UnFreeBoundaryAspect(); + anAspect->SetColor( myUnFreeBoundaryColor ); + myDrawer->SetUnFreeBoundaryAspect( anAspect ); +} diff --git a/src/OBJECT/GEOM_AISShape.hxx b/src/OBJECT/GEOM_AISShape.hxx index fb8edfbfa..1626936fb 100644 --- a/src/OBJECT/GEOM_AISShape.hxx +++ b/src/OBJECT/GEOM_AISShape.hxx @@ -57,6 +57,8 @@ #include +#include + class PrsMgr_PresentationManager3d; class Prs3d_Presentation; class SALOME_InteractiveObject; @@ -66,6 +68,14 @@ class GEOM_OBJECT_EXPORT GEOM_AISShape : public SALOME_AISShape { public: + //! Enumeration of display modes + typedef enum { + //WireFrame, //!< the same as AIS_WireFrame + //Shading, //!< the same as AIS_Shaded + ShadingWithEdges = AIS_Shaded+1, //!< shading with edges + TexturedShape = ShadingWithEdges+1 //!< the same as AIS_ExactHLR + } DispMode; + inline void* operator new(size_t,void* anAddress) { return anAddress; @@ -95,6 +105,7 @@ public: void SetTransparency(const Standard_Real aValue); void SetShadingColor(const Quantity_Color &aCol); + void SetEdgesInShadingColor(const Quantity_Color &aCol); void SetDisplayVectors(bool isShow); virtual void Compute(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager, @@ -109,9 +120,28 @@ public: const Handle(Standard_Type)& DynamicType() const; Standard_Boolean IsKind(const Handle(Standard_Type)&) const; + void storeIsoNumbers(); + void restoreIsoNumbers(); + void resetIsoNumbers(); + protected: + void shadingMode(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager, + const Handle(Prs3d_Presentation)& aPrs, + const Standard_Integer aMode); + + void storeBoundaryColors(); + void restoreBoundaryColors(); + Quantity_Color myShadingColor; + Quantity_Color myFreeBoundaryColor; + Quantity_Color myUnFreeBoundaryColor; + + Quantity_Color myEdgesInShadingColor; + + int myUIsoNumber; + int myVIsoNumber; + private: TCollection_AsciiString myName; bool myDisplayVectors; diff --git a/src/OBJECT/GEOM_Actor.cxx b/src/OBJECT/GEOM_Actor.cxx index eeb5f0dc3..3e2d7a1b1 100644 --- a/src/OBJECT/GEOM_Actor.cxx +++ b/src/OBJECT/GEOM_Actor.cxx @@ -37,6 +37,7 @@ #include "GEOM_EdgeSource.h" #include "GEOM_WireframeFace.h" #include "GEOM_ShadingFace.h" +#include "GEOM_PainterPolyDataMapper.h" #include "SVTK_Actor.h" #include @@ -103,11 +104,17 @@ GEOM_Actor::GEOM_Actor(): myHighlightActor(GEOM_DeviceActor::New(),true), myAppendFilter(vtkAppendPolyData::New(),true), - myPolyDataMapper(vtkPolyDataMapper::New(),true), + // Use mapper as an instance of GEOM_PainterPolyDataMapper class + // to prevent drawing of mappers' content (due to an empty definition + // of GEOM_PainterPolyDataMapper::RenderPiece(...)). + // !!! Presentation of GEOM_Actor is drawing only with help of actors + // defined in this class !!! + myPolyDataMapper(GEOM_PainterPolyDataMapper::New(),true), myHighlightProp(vtkProperty::New()), myPreHighlightProp(vtkProperty::New()), - myShadingFaceProp(vtkProperty::New()) + myShadingFaceProp(vtkProperty::New()), + myShadingBackFaceProp(vtkProperty::New()) { #ifdef MYDEBUG MESSAGE (this<< " GEOM_Actor::GEOM_Actor"); @@ -140,13 +147,13 @@ GEOM_Actor::GEOM_Actor(): aProperty->SetPointSize(3); aProperty->SetColor(1, 1, 0); - myAppendFilter->AddInput(myIsolatedEdgeSource->GetOutput()); + myAppendFilter->AddInput(myIsolatedEdgeSource->GetOutput()); myIsolatedEdgeActor->SetInput(myIsolatedEdgeSource->GetOutput(),false); aProperty = myIsolatedEdgeActor->GetProperty(); aProperty->SetRepresentation(VTK_WIREFRAME); aProperty->SetColor(1, 0, 0); - myAppendFilter->AddInput(myOneFaceEdgeSource->GetOutput()); + myAppendFilter->AddInput(myOneFaceEdgeSource->GetOutput()); myOneFaceEdgeActor->SetInput(myOneFaceEdgeSource->GetOutput(),false); aProperty = myOneFaceEdgeActor->GetProperty(); aProperty->SetRepresentation(VTK_WIREFRAME); @@ -166,7 +173,7 @@ GEOM_Actor::GEOM_Actor(): myShadingFaceActor->SetInput(myShadingFaceSource->GetOutput(),true); - myShadingFaceProp->SetRepresentation(VTK_SURFACE); + myShadingFaceProp->SetRepresentation(VTKViewer::Representation::Surface); myShadingFaceProp->SetInterpolationToGouraud(); myShadingFaceProp->SetAmbient(1.0); myShadingFaceProp->SetDiffuse(1.0); @@ -177,10 +184,14 @@ GEOM_Actor::GEOM_Actor(): myShadingFaceActor->SetProperty(myShadingFaceProp.GetPointer()); + StoreBoundaryColors(); + + myNbIsos[0] = -1; + myNbIsos[1] = -1; + // Toggle display mode setDisplayMode(0); // WIRE FRAME SetVectorMode(0); // - } @@ -192,6 +203,7 @@ GEOM_Actor::~GEOM_Actor() myHighlightProp->Delete(); myPreHighlightProp->Delete(); myShadingFaceProp->Delete(); + myShadingBackFaceProp->Delete(); } GEOM_Actor* @@ -282,8 +294,45 @@ GEOM_Actor:: setDisplayMode(int theMode) { #ifdef MYDEBUG - MESSAGE ( "GEOM_Actor::SetDisplayMode = "<GetProperty(); } + +void +GEOM_DeviceActor:: +SetBackfaceProperty(vtkProperty* theProperty) +{ + myActor->SetBackfaceProperty(theProperty); +} + +vtkProperty* +GEOM_DeviceActor:: +GetBackfaceProperty() +{ + return myActor->GetBackfaceProperty(); +} void GEOM_DeviceActor:: diff --git a/src/OBJECT/GEOM_DeviceActor.h b/src/OBJECT/GEOM_DeviceActor.h index 7aad24d7e..721ee1b6f 100755 --- a/src/OBJECT/GEOM_DeviceActor.h +++ b/src/OBJECT/GEOM_DeviceActor.h @@ -52,6 +52,9 @@ public: void SetProperty(vtkProperty* theProperty); vtkProperty* GetProperty(); + + void SetBackfaceProperty(vtkProperty* theProperty); + vtkProperty* GetBackfaceProperty(); void SetVisibility(int theVisibility); int GetVisibility(); diff --git a/src/OBJECT/GEOM_PainterPolyDataMapper.cxx b/src/OBJECT/GEOM_PainterPolyDataMapper.cxx new file mode 100644 index 000000000..c86d93792 --- /dev/null +++ b/src/OBJECT/GEOM_PainterPolyDataMapper.cxx @@ -0,0 +1,24 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "GEOM_PainterPolyDataMapper.h" + +#include + +vtkStandardNewMacro(GEOM_PainterPolyDataMapper); diff --git a/src/OBJECT/GEOM_PainterPolyDataMapper.h b/src/OBJECT/GEOM_PainterPolyDataMapper.h new file mode 100644 index 000000000..0c738f775 --- /dev/null +++ b/src/OBJECT/GEOM_PainterPolyDataMapper.h @@ -0,0 +1,44 @@ +// Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef GEOM_PAINTERPOLYDATAMAPPER_H +#define GEOM_PAINTERPOLYDATAMAPPER_H + +#include + +/* + * This class can be used to prevent drawing of mappers' content (due to an + * empty definition of GEOM_PainterPolyDataMapper::RenderPiece(...) method). + * It is used as poly data mapper in GEOM_Actor class. + */ +class GEOM_PainterPolyDataMapper: public vtkPainterPolyDataMapper +{ + public: + vtkTypeMacro(GEOM_PainterPolyDataMapper,vtkPainterPolyDataMapper); + static GEOM_PainterPolyDataMapper* New(); + + virtual void RenderPiece(vtkRenderer *ren, vtkActor *act) {} + + protected: + GEOM_PainterPolyDataMapper() {} + ~GEOM_PainterPolyDataMapper() {} + +}; + +#endif //GEOM_PAINTERPOLYDATAMAPPER_H diff --git a/src/OBJECT/GEOM_SmartPtr.h b/src/OBJECT/GEOM_SmartPtr.h index dae9f45e9..12f981bc7 100755 --- a/src/OBJECT/GEOM_SmartPtr.h +++ b/src/OBJECT/GEOM_SmartPtr.h @@ -41,12 +41,14 @@ public: T* Get() const { return this->GetPointer();} }; - class GEOM_DeviceActor; typedef GEOM_SmartPtr PDeviceActor; class vtkPolyDataMapper; -typedef GEOM_SmartPtr PPolyDataMapper; +typedef GEOM_SmartPtr PPolyDataMapper; + +class GEOM_PainterPolyDataMapper; +typedef GEOM_SmartPtr PPolyGeomPainterDataMapper; #endif //GEOM_SMARTPTR_H diff --git a/src/OBJECT/Makefile.am b/src/OBJECT/Makefile.am index 52c23f398..c83d0ea40 100644 --- a/src/OBJECT/Makefile.am +++ b/src/OBJECT/Makefile.am @@ -42,6 +42,7 @@ salomeinclude_HEADERS = \ GEOM_OBJECT_defs.hxx \ GEOM_OCCReader.h \ GEOM_SmartPtr.h \ + GEOM_PainterPolyDataMapper.h \ GEOM_DeviceActor.h # Libraries targets @@ -55,6 +56,7 @@ dist_libGEOMObject_la_SOURCES = \ GEOM_AISTrihedron.cxx \ GEOM_VTKTrihedron.cxx \ GEOM_AISVector.cxx \ + GEOM_PainterPolyDataMapper.cxx \ GEOM_DeviceActor.cxx -- 2.39.2