From 980df1a785e426b5a9a7ee46e822102143d449c2 Mon Sep 17 00:00:00 2001 From: Zac Zhang Date: Wed, 10 Jan 2024 21:40:55 +0100 Subject: [PATCH 1/4] stash --- CHANGELOG.md | 2 + docs/_images/PLACEHOLDER | 1 - docs/_images/PLACEHOLDER.png | Bin 0 -> 31908 bytes docs/api.rst | 15 --- docs/api/compas_viewer.components.rst | 2 +- .../components/{render.rst => renderer.rst} | 18 ++-- docs/api/index.rst | 59 +++++++++++ docs/conf.py | 18 ++-- docs/examples/PLACEHOLDER | 0 docs/{examples.rst => examples/index.rst} | 9 +- docs/index.rst | 67 +++++++++--- docs/license.rst | 5 - docs/tutorials/configuratins.rst | 15 +++ docs/tutorials/file_structure.rst | 99 ------------------ docs/{tutorials.rst => tutorials/index.rst} | 12 +-- src/compas_viewer/actions/__init__.py | 4 +- src/compas_viewer/actions/select_all.py | 2 +- src/compas_viewer/actions/viewmode.py | 8 +- src/compas_viewer/actions/zoom_selected.py | 10 +- src/compas_viewer/components/__init__.py | 2 +- .../{render => renderer}/__init__.py | 2 +- .../components/{render => renderer}/camera.py | 52 ++++----- .../render.py => renderer/renderer.py} | 40 +++---- .../{render => renderer}/selector.py | 44 ++++---- .../{render => renderer}/shaders/__init__.py | 0 .../{render => renderer}/shaders/arrow.frag | 0 .../{render => renderer}/shaders/arrow.vert | 0 .../{render => renderer}/shaders/grid.frag | 0 .../{render => renderer}/shaders/grid.vert | 0 .../shaders/instance.frag | 0 .../shaders/instance.vert | 0 .../{render => renderer}/shaders/model.frag | 0 .../{render => renderer}/shaders/model.vert | 0 .../{render => renderer}/shaders/shader.py | 14 ++- .../{render => renderer}/shaders/tag.frag | 0 .../{render => renderer}/shaders/tag.vert | 0 src/compas_viewer/configurations/config.py | 5 +- .../configurations/controller_config.py | 10 +- .../configurations/render_config.py | 29 +++-- .../configurations/scene_config.py | 10 +- .../configurations/viewer_config.py | 6 +- src/compas_viewer/controller/controller.py | 90 ++++++++-------- src/compas_viewer/scene/boxobject.py | 7 +- src/compas_viewer/scene/brepobject.py | 6 +- src/compas_viewer/scene/capsuleobject.py | 9 +- src/compas_viewer/scene/circleobject.py | 9 +- src/compas_viewer/scene/coneobject.py | 7 +- src/compas_viewer/scene/cylinderobject.py | 9 +- src/compas_viewer/scene/ellipseobject.py | 9 +- src/compas_viewer/scene/frameobject.py | 12 ++- src/compas_viewer/scene/lineobject.py | 7 +- src/compas_viewer/scene/meshobject.py | 12 ++- src/compas_viewer/scene/networkobject.py | 8 +- src/compas_viewer/scene/nurbssurfaceobject.py | 11 +- src/compas_viewer/scene/planeobject.py | 6 +- src/compas_viewer/scene/pointobject.py | 7 +- src/compas_viewer/scene/polygonobject.py | 7 +- src/compas_viewer/scene/polylineobject.py | 7 +- src/compas_viewer/scene/sceneobject.py | 68 ++++++------ src/compas_viewer/scene/sphereobject.py | 7 +- src/compas_viewer/scene/tagobject.py | 14 ++- src/compas_viewer/scene/torusobject.py | 11 +- src/compas_viewer/scene/vectorobject.py | 14 ++- src/compas_viewer/utilities/gl.py | 8 +- src/compas_viewer/utilities/qt.py | 16 +-- src/compas_viewer/viewer.py | 39 ++++--- 66 files changed, 537 insertions(+), 423 deletions(-) delete mode 100644 docs/_images/PLACEHOLDER create mode 100644 docs/_images/PLACEHOLDER.png delete mode 100644 docs/api.rst rename docs/api/components/{render.rst => renderer.rst} (50%) create mode 100644 docs/api/index.rst delete mode 100644 docs/examples/PLACEHOLDER rename docs/{examples.rst => examples/index.rst} (71%) delete mode 100644 docs/license.rst create mode 100644 docs/tutorials/configuratins.rst delete mode 100644 docs/tutorials/file_structure.rst rename docs/{tutorials.rst => tutorials/index.rst} (71%) rename src/compas_viewer/components/{render => renderer}/__init__.py (75%) rename src/compas_viewer/components/{render => renderer}/camera.py (91%) rename src/compas_viewer/components/{render/render.py => renderer/renderer.py} (95%) rename src/compas_viewer/components/{render => renderer}/selector.py (80%) rename src/compas_viewer/components/{render => renderer}/shaders/__init__.py (100%) rename src/compas_viewer/components/{render => renderer}/shaders/arrow.frag (100%) rename src/compas_viewer/components/{render => renderer}/shaders/arrow.vert (100%) rename src/compas_viewer/components/{render => renderer}/shaders/grid.frag (100%) rename src/compas_viewer/components/{render => renderer}/shaders/grid.vert (100%) rename src/compas_viewer/components/{render => renderer}/shaders/instance.frag (100%) rename src/compas_viewer/components/{render => renderer}/shaders/instance.vert (100%) rename src/compas_viewer/components/{render => renderer}/shaders/model.frag (100%) rename src/compas_viewer/components/{render => renderer}/shaders/model.vert (100%) rename src/compas_viewer/components/{render => renderer}/shaders/shader.py (95%) rename src/compas_viewer/components/{render => renderer}/shaders/tag.frag (100%) rename src/compas_viewer/components/{render => renderer}/shaders/tag.vert (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index efea54fb0c..f08e7bc776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added +* Added documentations: index, api, etc. Mockups style is improved. * Added `DataType` as the data type template for generating the buffer. * Added `NetworkObject` for the scene objects. * Added `compas_viewer.scene.ViewerSceneObject.LINEWIDTH_SELECTION_INCREMENTAL` to enhance line width for selection only. @@ -44,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `NetworkObject`. ### Changed +* Typing hints improved, now `compas_viewer` only support Python 3.9+. * Fixed the bug of the `Selector`, drag selection is now more accurate. * More performative instance map and QObject-based selection architecture. * Naming of the keys, mouses, and modifiers are changed. The key string which is the same as what it was called in the PySide6.QtCore.Qt, with lowercases and with prefix&underscores removed. diff --git a/docs/_images/PLACEHOLDER b/docs/_images/PLACEHOLDER deleted file mode 100644 index 48f73ebfcf..0000000000 --- a/docs/_images/PLACEHOLDER +++ /dev/null @@ -1 +0,0 @@ -# container for images to be included in the docs diff --git a/docs/_images/PLACEHOLDER.png b/docs/_images/PLACEHOLDER.png new file mode 100644 index 0000000000000000000000000000000000000000..c7ace8e1b4d816fb259f1f4947b63bf105cf5e41 GIT binary patch literal 31908 zcmeHwXH=8xwyuJT4Ol9INK>(a6oo|#%?9W~KtY-iKw6g42_Zm$s4PY42m}xUN)Z(d zO~#kXOrX8)1synQX7PU($|QOPtHi^Qb-BN7R|ti=w*G z#ZV!MSsRvZ{yQvQcY?4pjjT2YgQ$)D!j?s*)?yX%OqJ6zF&On zw(;&i|4%PB_gejuvio0r>dvoxprX@9b{yyXPoJr~DC2O+;lzI$Y5T7G&Ek`FFC2dP zL;Rn|0fx z-z-XLYf*ph<TXMK4!R!ZrIWp=DB6e4i}YfFsAaH-G$#t?!Iu34T)6Vc@? zcPO%lrP#wsj9B0^BAm4jPB24}Gp{IuXD<{g>MV~XL>A)ND?i2W31>uf*M5BbLB9aVsmNTx1tXdk0R8$BB z7HYRf1NMbUV`j3aGBIoK2`WMKAzUP!62cm(591SwmDI*AEe?2fOsg%LGstiXICyzH zSwt%2XD5>~s5TTZIs(yM?K=leS*vBQ&^nM_2`mbS%@W}(dU5<0HCl0oa_hr_$jT)$ zJrwT4VXsqJrz`_oIl3GzPSqNfNg*OB#5e{iEH3Ph7T;d0L;D}ah4t`{JvpfsWJ$hF z5vnQ{UzaFXI5;*Tuhve|4i-OHb-?7foLX;Qs8dQBMe9M1)xtX-;_>)!+@P&)$jZ+# zW-_DHsd#T-YGuIVsBXBcgb~$$KnNSoA_`xMq_UNsL`d5(KC#< zoNKSN^%61Sug|B5vsVH0_(88USo_&+(xJ_sw!~vgzQaib?VIe7WmX2$P#x$I`&ti} zgzxsM2S?OfE@BmZ&ET#4Z8E||UB;R8g?3H)2jK!tq+e4`T|)TFP71!;($lXyun5MU zf0=NiRc4&7G>@JqVmZ9^Q$6_c8aUT9#SRd0jL}dan<%&XB*#qD7k>i_Ft-?||=YP;; zij^VpfTUNxn}FJ#4LvdT;Nc6^zl>&oj)zWKqd&Q*z^?AM>JU=sWt*##i6v5mNiDKa zpXEul!ffV(uk#g3O{ye1b3osd&9agWAQ95mld5?hi;KG*W0#8bOu8}N5$L^{oHeS; z+!fcLyMCg5rgxKgFPpj>CeQ5OS(hxm`YXob=3(Eui?bWso)#JXP*ap((?2JcWWLX; zYS~c7wPqP%o+IY=O(7-ygUaYfLS(#WL8{jqd#AAATlq$&bvVeZ8PyU)k z&YKHvXKtaAA;{OA8rZ4a&KcrxEr-2I4fl#_?=d3o&D2JyY5{LQ^5(7Y%Lgj;$98L2 z)nAm1sleW|Eq>5b9Jv0JFu+MQW@{|&AmXGY9F-MhqMEEx4+c+{%s{^JIUnaELkGk7 z1fSSL;n6cPDg$iTlzac^#n|@C-zU>?vRy7}zM1XSS0idmMR*^JpTAi>adA6QkDBG= zu=J5}e`kTv1APy_{sjx@lM~-idY$i+`^IJ$Zb(9Gg96QRwgunMd$~s=ATWmb@Mv~n z*%j%=EYZ+&3dt#)5fS{6jD#zoOo;3^h{oCsxxFxACRzgo=PpKOb1^A>7d?+w3{mdo z@>r-wqkWLCdL(a@2zfOMloOvmv=vhhNDt(crJXRe5-R@O;npAyCwnzcV!GXxbh=-& z;L)rhgjd7~i$#7L7g1XN2^-a@_E$i2=>33A!&LU#g)>N7mfcz4m-YTb@USXzkHO5d zB(Y@{1&Lf@(a$nXcy_cXm?Xk!>+7JIUuE=K4tbT#=UZn%0?^ zj`|8pDB>Vmp)jH;R*LR=5;`q&c*eVe3#3H7gb zDaCr0odILDq3^(U>cK2ByrVi{o@F}O%*j|@nCi~!sK)zFwg~HeaF;0}l}wq)?}e$gY;{YYqaRd5)ucc8U7nSE^zy)7g8y7V;J zZaK4WNrfoPI=d45v(q4L;)0;H%}UG1JCgm+s||o)rIvKrWRXaK6OGnThG&)Z5j6+e zKaQeSyG|K2oBN^$PlY$T?DcE*NcZdmKR5gAKCKfvbSQlM82Aq|>1wEmK&p+BWlkCv zF*M+$m|@Bnp;sc8oqUHZ`&ILGYJ#V^fzA*+{hH$zFR$$m0+RHLy!U}>hbgH2Ua z<0y0BY>ti8c_qhv+&1E`KY-ISI=>t6axp?1gCNXI1>hl-JfaCP>mSt08y$PiU%*6N z;8baed#D%(68h$EHw2U3OYZRP4o=H5m`@jYtX1jG@cucG=H-bMUA8d1|2%T+WK~rg z)#R3%hRFrD$O}dc|DQ0$vG15&N=Sd6{vC_*PBsJKI7(5|o>r0~537{VS`*&ZwbmW@I|iP3_^;HFxPXyXO5t62Fl(T3Kz; zK_qG`e6GLZoM00f9WkZThj0o$&KG`^P}5iTL5(?Jv8WkoWg}#dt?n)PpxKxg(}AMQ z&1K!(>t+)LwUhG;Z5N`K6qJsZHX5-EW3^c?g}64{@sQ`+j<9264qm)ATHYCVwx1(g zq8lIib+})MAveClq^%PP2UFTRl5?Nh49>vklu^b}a~&ySKaFEGQeLhqPs|2Ut-O5N zc5C!DTnzna(VK#Wip~p5RHO6OU;py0cn6e*$eSBaA+H(@Rl^HI5D$fTHIrZFNryy= z7;J#*rbG93Ukn|CXub&g41nsfSy^FcuUGGNARuUo;MW4fDknr%_0cIuP*v3}lA|LOS^ptKlG zu+@Ywo(dD*G~}7P$J9>PxUYpo>@2{HA4BNG`3V4Yy^<+l3iEbHMJt_A*0(=E<=sC4S7aBtJhKPkh=WJ)Tfqdo}s0(Sx za_T(AiBsc8gyANq`}gHDb328J3l%!)pX{tAyz!&|VIn?ZU#glq-ij0r1ya%3cr(w> z)vV~sDI-@)5sN0qkOt!|jX4u&)?XEsI|_x|8;v-#3e!n+C+`GI%P-tHf{4%zrsG&K z>_MsEAN98pYc6v`_nQY$;OgbUru65%>s@E_*5(3B>@7*2c8lt3AA@UIwzBtG046=8 zHfZ|r+K68d5uLJVj&7GZTvQTVl>H!{|2>O60~W)=Yxvs-2Fzm#bN$yUM_sXQcx-R4 zayVLS4@4J>E6k0L7bu^LMzfv@%~Ts(gJn!VS>L@!7uL&;Sx-~4^cysY>gAJ>c(3uw z>xmIV)BdQ3524A3><-Rc&o8X)U%zvZOP*eEIV(DH?kfM-E4-WZd_Jma+{Xj_v$T88gD*YB0j>HC)~bClod2A8DXZ( zr?}R)Q{QdhK1~`ikN8FAP6p8mtlv~Jircpfd}h|w=8^Tpvs;K`A&f>5`App^t%=75 zB$=XYlm}es(V;0hamMln?HLDX&ra$i&Cc+b?cEd%O#xIUP!Kbhc1!IhcxSBE?$#nf z1J6m;TrD<=Pf+qhaQGTR-)ku2P?tW~1RSp4`m2FExF(1JvVHXwW?h3_8>Cu%nm(`N zn69iZ(Kv3s=ruT>*q??i!Y+zvyK7BQ3;(iS@X2!;afj({q4G@1$cUHax zXPm&>L-dN!?59G4)Mu?0e|`5@+smuE|3|EhxQj;XenVN;%2b_+_d%qCHGYRAZ^VGzj72#;*x(iu0=Ki*ak61=>>PHg0-X@#q8;#be?5Iu;BSGGkryqU-;9Z0ZYU{l*? zIl z$hcpA;+sdLCDrs(%f5`m$#|F4rOEY!ni0rsl!Ir_&ZI-ZtRbRYe3+%aKh2-B7;Otu z1k#@VUjbZIP!j2Tc64$w=-P!5EIvLB9U~TPz1K?7AVS@mom5e+0lVO3Wp7?Ylst=E z`Y81TIn*vta3%Re&FWk=kq#-*)1i0Wji<^h}=k_KM56k*qK6?Wxj&>?W)vgXbhU z6(M3{7bRCgPdU`3qTPRy`sAm~B4wPV_V|Ta|58mpGw^5a@7$2s2ILvzJkW>eqK7jO zZ&G`>&_&NxZ@-wG1%27s-KTcu#IM@7ec0}1oH)2T>rY}^T6ZadkmNi+bc1bYaVwmD z;#)Cy0{GFdi?6RU?sY8ReXY%ok&%Sq#E;Pt2{!#uJO<8@i7pW};;sVTTJ{`vx$YpuH?(Zu~aLpbKytmKzqWKWVXK?FIm>u1D^(!ag?zmr)S$jB=r8! zX003EtsULba77oY8b>GeT|jtyz`*pr$Adi!!INHW3&vz;b^`6PFo5x88)!QI2*k_V z7q|LOl{t8I;{DQbgaCJJaNaSA{!^U``r3k)+0ZIIgRdTY`2&v(RgbzA5>C%Fg%-A2 zmd?cbPwUAw=7*RV4={xWVxmi8Q=Mu714acZ1WJWSc-?BP@$l^4UIA$$*~KSYNl<7) zAb&2BbL;_fXnRBIZ{kV(sPPj~XTUAWa`K(_9H z*uquMIaWUbM?0C{H}nQB85_D+tg6HAlW7gsrnY4JVzJW^K7~?tf0^kr1nb7;7cPfVnu$0icn%bNG?NcL(0RR!m!6@Z(rO!h=tq zCL^@!$SN7yi1LBj(_q15<&1BnvU-NhoSTy20Yk<+7w!I+TFFJ;$RH~7qL zKYt7tw5hcT?Pm37`n(3P$ixjj>!$|{blZ@-r8g8#?-Edb`2ZF~EH!mjAERf^zs~Qw zf*GxL>1($W8}0~L=_1)9$@64DeGD6>j0;6tMOZd<9BN)K9!)mJ$P1KQOEzlK@skj1 zhwKY8lQ;HT7asZ`;xdN^MZ|Mu({Sp{VCX*XAsTQENN?3RbACqX*KDV5gtQVb*c3wyxM9?(!gOrhb#>GpZ^}Bb6FQ1uUNl z3A*JqBN;>eU+67e?Is+An~#f z_5oJ~M$u*)I~cPSlydg~3L|hRnAvu(2|v0zu13Y;6LNj>u=KIFnYU#Cqz1`yk@|$l z0bV{})kl%*YjbeCTU9eL<788C3N zdgbhAh44Fm!m)O>wWVLxB}%7)Lw{xKqFIwX~CYBEsB%WsDBLS7>oeFmzvLc87oCjik?9$8pRarz%Yf;{HPd23HbTw+& zHkpdiHY(Zg<5!D`!0^pnVcoZpFP8<7$wSw_>Ra^$wX@T_=C_L37 z&1T_s`@+l=sI@V4cnjh*;E>9I$na-^W)3)u6O>Xm%qk{ZK8xWi8~hooii711j5fup zQM$)o=bn+y&NuV=Y&31jg}_-ge`^%kM``#CA$<_H$DeeXsto_;=aGUW+dToNrNf2K zXma2G&1jlyyL?oxSB~-gX}hDCOvT!ztl8t^DY!zA#Mo=(HyUF!R(ELa?y&ffIwaMs z39jYpM1v|i!eI5|pKzUl*2m|M4V8rtWgIvofw04gn`CI+TMiCYK01|}TC)i}3Mvz~x_XXod zy_`#bb}skNf9+3OJa`B|c==@Bof{?G`ggm8iaw9k&^$sVpJ=KY(fdF6Pw-g8j0~+@ zqhpNRG$Wqd=ta0G`|)Frc4TOaad8!d5j!VV*l~x@Qfq1>5?+lBhmeD{;tw6H&?!@m zaqZ>!=BtN`IB{Jij2pp6d>H4wi?;79fUz8>Z9zYPoD98|)`j7R79y59!alvF^E272 z^ormnp;dikGE@#Yw1uc)K;olVw9Y=Q5qg%dz2+(kYl5)H5=@@hM@q9+h>;O7`1nK0 z22`3kgN5hd##hJ320AHv+|ap^q9jE|Y=HMHV%<+74SntSD;hL6GJjN=3{c1ZWgyxa z$WtyL?tvH7N)oe2y~f(sCWAfJzo@v8>g?jR>*gK4sYr>tSq^&4l&rbEZXp|V=;DseUVsy!zo&mZ*nkPKkvsn3 z5AR%VG#nm%K5p-YUtj!j`D<}JC9^$Q5;1coK-O?~>EO?I_`7?CXMKO)GrUB*M7X3v zy~rng`?T;zcq*G+NKm7o1uxpnMmry3WrQoFRTkpCh%$$ZT@`+5m7Kx`&6bh;6;(YB zPYoI|a85|Mv`UH&UDZc-2xBzZ)DeDJ;GG8GRX0x%{&q3>6HSF;u4ePgM%0iX`*NC`r^Pa#jPx`nwHp> zDoq@Xk#W=xT?=5Y?=UbBI61WxQ-vv95z}a%PZaz_&^9EkcT8@u`1>1DY>QrFT|MB} z<<0jjuPCv+76Ruec%-)h z9Y_`K=v)Dj_3aUsdZgMU5-won$45aMw!SeQ4YSi+_*a&>PBNj+Cusc~I}Q;Xl~~2K z1`onWl{u^5-{Ir4ZditYnhXXX25PC_CJ-Of&D??fbH83e2n!YzsB`1EY~#Btk$S0S zrjrD9e`M_%LU8#8wTNU-3iadGh6~rktS|R5)Ewb{wRVS7M>T8hLxH-X2$v7Jarw|~ z1=$UQ>jCfqcMBK%V-T9!qZrDFM0KFoKe*PMW)^*AtaFp%Z(ac5xS^ihiw#&9v31lK z?ir0s-XWt3o6s^O6b^7EJmKtJuB-26sY#PIfkXo=xMAWA)pvlkjX9k<#*U zYO=;-p$-{?c;P2p2#P3{^(6RFr6@edLwfb;6|MEKuT_u}nN= zJhe+}kpgSiE09a2fjYg$N~VM!U~8Mei;6RMd}~>EPa!<_d8f6lRild9E60KhL(Xsm z2N4Jy8#kO3y#vBEqcPuF_3UharT^#gyI{l1I_#xUF^Ky#!`^WtDd}_91a_2s_v}E;8jMSGsVC8wD7&yt>N%epdE-T`v^Nf zZ2;6~;llaX@YDOMthE{sO<=KEp3EXxix|@%eS3MGMFIFWLLN-c3V?}5ScS(LEuQJW zZ@UG;W?$r#^h47a?E9q}y1TavUJJ+L?ntskQRiw1BUxZCCCELRD;TUGRD zAee>rfNQv@lvnLvD(c<@ucke-urVOn%nhU~p>o9~41?x>Q2}`=8Z^Cy^xoo-8D(RUuw?*Iwy~Kba zOMw<%IncF`Jo2#^c}^lldG7iLJwLy+p>m>Y?6vxwk2VMBDBS(4$@kz*a~_ed=Ok|X47gR~kDgOB(x-Yxc3(hW zR1cMVEdG_-UBg2hYuGr-#o3zQ!n+F^^V=)xH8Mhf!mFYRYgg{Gx(~BJPeK|m&qd{( z!}JF(_)dNTQFzaloD88qxR@E1epOg zrROm)hxGf@9wH!G>+B4>s#+~sjJ!+Q_ed0^Y_Prv!yO~Y6e|z9`K>RGgCy2BTq2Dt zIy8=t{F&Yi2p5)!eBG~>D7{$!V)#Q9hVS_mkUSRn$17sCTiB%80Owt4Kw0BGn+U4` ze}}dYeBXfN0#2`+w$0N1cn=CD%^wf!Hz4Z9-7g~c+k$}lsdd%+@POi~!UnksH~aT)}^KV}+%S-;^r zZK0985du6c3yyd&l;+cv9Wl*=y$cP}(8V`vFpr$j-?zV|Ik&FaMc1$hZ2P*fp^S?G=E*lNC#`=@ZYo@1X zXoJk@*WRFE4pDC+C&tD28NdR4Dw{D^qy=VQ7f*VLGg;96jkr%oM z^Yz8dXK`Wu#{qkJnd%NKuC7X?NT{$JnXl8JZ`?F(wdg-{dK&E2V<6uIsGv(Tc_qQ; z4IfoYD$%jli|%MEWg*X)XWTY0XOJEib#(%y?c9eTWjOk%IA%;vD{1>5TEJ+F0iT`; zx|fK%VqkB^jdw=ecy|IC4>-m{sDcAbq_D(xCQ(&lw#CHw#{fdH2ov)_YfQ45bDPwa zfn)7xX3fcdOYfQrlK{h{BP`K+1-fg)f*+giq7u4Xd-L<$mTe}guTUc}j~q~ibaF_~ zLdogX-zAyWrb2Vm``5ZN*&o~_xhGcMG57OdtXa4S8)@0s%1Vr|B&&5Jbc*uK?!E3n zr!f>Dh>Y_|?awhC=&a`7JJ9hw?R!ZL!g>W}XYFAA)y|mahy2;K26h5|@<>Czw#o6X zW(dfV)k4Y33V3|*l4%Fb5Ql<>}cZtlYWc=E=0wN+eAa(panAG%pQ>mQhi&p`# z8wbu&0)JBH*4SYDc4?DP#LvlF11xn{4d;oL)>Mg1X>dM5=t7su*RroQ`NR)yoaUIA zq63PWt}mpyF*P#CHCd}6U-rx>UG!P^VJ@}=srmr?DF`kH~CPRWl^6;c6-~*Cy|PdT~*w)W*SrFKq0+z^hYHR-ctl_+m$l=3M3M$mLIy=>D>2 zuGNam?1Hl;XO@4UDRb$@{R_)xA9NO#bBX0p0iB6$(P_Rcu0Svj)UC;Q7jULL`h$&p zb1SjBlD<-~JljWGIRH%R?|mq@)O@Ko>-w_-%2s4-rLjfj*y})x;k^OVxcAs}P<7F~ zcSYlA9C(!n{254Go~)9kyIlNx!d6=w^V1@%mW}fUFD0LHMh}_Y?9X=?=$lQPd|`qW z_)W^5PJ~yg>ep-@@$5-^QuW8)NR}KgIM!ouV+*Fh1f@qn9 zur*<|uE3(%{(a}->1%-WSP@e0*9434k*w3VUq$Fgz!WuY0b4Q$PIFv*ZyZ|Ub@Hm3 z$MUfZHx(v?3Tc-K1{15hlLpH~EKVq%#zwrEilf;|;>P#nSHUMGM=_UeK(iptLW{I> zT$?iBYF>}WE_0z8m@lw#NouLhHbXe9~N9IlHNyl*I)Q-hs)b4ZYF`;P?v|ZxVm|sE!P9ajl7K)nukQutD+tUmJ95W>kD6r=M|*| zo%@`qs^EQ9jCNMb$5!FShG5ituN+O*`>Lq15ggEdmXS6P%pL=2&~0DOI|2oHzK?~R zTk#DhSRMmpj8lY_eaJ%3kB(vpFlz;A=ItipA41nlW;`M_6dS|lKB_30z~Pg&?a(P5 z!%l{3rUv;-m2kz9+%q9)xnHUeT|xMiX^!!6TDdB-8KGR(*ZZiuz4M+ul?|=ka zEIywX%tUwk@IFub6w}dFR!~qKQ06%HxdNJr(K_$WSmZQ@C(OK!*S=kneoU{^PcAp% z6xdT{&D}?t1!P2Os{1YOWoWONK;h6K$^0FkO-jCs{#2u zslG=>tu!0oBp09d#TXfQXrRh^U ziGK>2b^tgQYOWwWZmE+;Jys&)!<#xO)tV)(pXjeB9}n}7 ztS;&$3fTY>>4rA;`{ySL$P#N#}N3#&-K zxkLUKLAcDPS#tg9F^7G;GBfT~2IT#XVe-b;YVIk|zgOKxQP!6-j&Ex>dG)bo^{XNG zi~rIfXI#DuMeMSfeVD{=V1Q&pWgJeGz#Cg6u3A4YwiIbF5`>?Fhd3)crIoMpYvo?6 zAkLg=lRP-}J#gjcR9w2N87m3;;?OC`*)B-JLK4tgl{t78FyK4?p-1Sf13=Hs0zOuo zZm0Q*4n{owh+xfWD~h)%!SnXX5w#7d<8hBljRKlh53Flk^U;)ekzH7fxn|in$t(OE z$Pj#6rrs+H6)H#*=@vG|DOolGy`pGM?jnT#VRxo4w@iwCfXX?X@^#`=Q`S9~;5ZL1 z`|Mz0Q$2=^MY?~J@aSXSe;p1w&SxXXFpBs8S@w;g`2&z?jeMdDEDAcN;HW8M6BX|AUxw&FDK#c#)eUpLQ*OGc_=d(_=d(=C1*eFH(n(sO^v>P8sZywVisTy*qM^|eu8bP)Lg4fo~6k_TM-$7HaoxTB0ebZ zSfCx4b<9{y+)Iye$q4liHXE9+xuQQixX((NauX6b^;@2#OTxHla(}=PQLigeHf*ly zJWToyMqP(=(^GLd7k_mUxdpmwAUWqFyYriSkgg5mHrE05{_cP`>w;i*fIBFtM^(OJ zuhWsbjbYb4r@LWExfk=>x|ds*XOy*4oaK~XPyHf>1~f5geyzZH=jntiW=qE5W3og9 z640NhWGm%XXdiQiG1^2Nn;Sp%m|nwd{~>Ot&@F|dyx{WQ>CGf}QR(G_h3OigR%%uk zv~fa%!xayZVJN8=nHG1mO0l$c{$1K7cBAXpx--f%~i!6`_QW*CoZV zpon>i(yt1uxb%3}u(^*e1b|&bSAj;;48`&O zEGH#Sdn-EiO6gTvBDGp5$yDh2LrlJU%9;x@KkC+Amu&o~WPI{3_Q8zC#=_8reCp1Q z7_A9P0@5D!u00^Dkh|k6n>)^Z{;Zl}g?tOreoC;}W&Zid zx;gmH6sVUG5my&E(jDs*S6> zWr2h3-^h4XMZ|yy^1V%W`G%!u{Wc=BcuMqeGucH_+b>E=@Hn5MVqtBK&f$2$iui^^ z@x{Oo)K`HmUWa+hd;ohtrrh~2ZtxXR2Kda@O})T#SpV}!u>R>D=B+!G|9;K%)WB8kYYyrjpi$Jl2pY6ZIzwP2~-bgix}du6+^aS$bV-zTZCoT z7XR8}#|~R$|Hu{;Y(c?RqI~4v01AF=7r1>j_<8=KEAX@9+pg;wU&UN@c=Ue&hnzln literal 0 HcmV?d00001 diff --git a/docs/api.rst b/docs/api.rst deleted file mode 100644 index db4b9a233a..0000000000 --- a/docs/api.rst +++ /dev/null @@ -1,15 +0,0 @@ -******************************************************************************** -API Reference -******************************************************************************** - -.. toctree:: - :maxdepth: 1 - - api/compas_viewer.viewer - api/compas_viewer.layout - api/compas_viewer.components - api/compas_viewer.scene - api/compas_viewer.configurations - api/compas_viewer.controller - api/compas_viewer.actions - api/compas_viewer.utilities diff --git a/docs/api/compas_viewer.components.rst b/docs/api/compas_viewer.components.rst index 460201ab39..d11e0cffa9 100644 --- a/docs/api/compas_viewer.components.rst +++ b/docs/api/compas_viewer.components.rst @@ -5,5 +5,5 @@ compas_viewer.components .. toctree:: :maxdepth: 1 - components/render + components/renderer diff --git a/docs/api/components/render.rst b/docs/api/components/renderer.rst similarity index 50% rename from docs/api/components/render.rst rename to docs/api/components/renderer.rst index 3915052c9b..04f4af5b2c 100644 --- a/docs/api/components/render.rst +++ b/docs/api/components/renderer.rst @@ -1,8 +1,8 @@ ******************************************************************************* -compas_viewer.components.render +compas_viewer.components.renderer ******************************************************************************* -.. currentmodule:: compas_viewer.components.render +.. currentmodule:: compas_viewer.components.renderer Classes ======= @@ -11,14 +11,14 @@ Classes :toctree: ./generated :nosignatures: - Render + Renderer Camera Shader Selector - Render.mouseMoveEvent - Render.mousePressEvent - Render.mouseReleaseEvent - Render.wheelEvent - Render.keyPressEvent - Render.keyReleaseEvent + Renderer.mouseMoveEvent + Renderer.mousePressEvent + Renderer.mouseReleaseEvent + Renderer.wheelEvent + Renderer.keyPressEvent + Renderer.keyReleaseEvent diff --git a/docs/api/index.rst b/docs/api/index.rst new file mode 100644 index 0000000000..28cd3b562d --- /dev/null +++ b/docs/api/index.rst @@ -0,0 +1,59 @@ + +******************************************************************************** +API Reference +******************************************************************************** + +This pacakge provides a viewer for COMPAS. + +.. Viewer +.. ------ + +.. .. toctree:: +.. :maxdepth: 1 +.. :titlesonly: + +.. compas_viewer.viewer + + +.. Scene and Objects +.. ----------------- + +.. .. toctree:: +.. :maxdepth: 1 +.. :titlesonly: + +.. compas_viewer.scene + + +.. Controller and Actions +.. ---------------------- + +.. .. toctree:: +.. :maxdepth: 1 +.. :titlesonly: + +.. compas_viewer.controller +.. compas_viewer.actions + + +.. Components and Configurations +.. ----------------------------- + +.. .. toctree:: +.. :maxdepth: 1 +.. :titlesonly: + +.. compas_viewer.components +.. compas_viewer.configurations + + +Layout and Utilities +-------------------- +.. toctree:: + :maxdepth: 1 + :titlesonly: + + compas_viewer.utilities + + + .. compas_viewer.layout diff --git a/docs/conf.py b/docs/conf.py index f38073e75b..c45a4dd946 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,6 @@ # -*- coding: utf-8 -*- import sphinx_compas2_theme - from sphinx.writers import html from sphinx.writers import html5 @@ -77,10 +76,9 @@ def setup(app): plot_formats = ["png"] # intersphinx options - intersphinx_mapping = { "python": ("https://docs.python.org/", None), - "compas": ("https://compas.dev/compas/latest/", None) + "compas": ("https://compas.dev/compas/latest/", None), } # linkcode @@ -89,7 +87,11 @@ def setup(app): # extlinks -extlinks = {} +extlinks = { + "gl": ("https://pyopengl.sourceforge.net/documentation/manual-3.0/%s.html", "%s"), + "QtCore": ("https://doc.qt.io/qtforpython-6/PySide6/QtCore/Qt.html#PySide6.QtCore.%s", "%s"), + # "QtCore": ("https://doc.qt.io/qtforpython-6/PySide6/QtCore/Qt.html#%s", "%s"), +} # from pytorch @@ -97,8 +99,8 @@ def setup(app): sphinx_compas2_theme.replace(html5.HTML5Translator) # -- Options for HTML output ---------------------------------------------- - -html_theme = "sidebaronly" +html_sidebars = {"index": []} +html_theme = "multisection" html_title = project favicons = [ @@ -109,6 +111,9 @@ def setup(app): ] html_theme_options = { + "external_links": [ + {"name": "COMPAS Framework", "url": "https://compas.dev"}, + ], "icon_links": [ { "name": "GitHub", @@ -138,6 +143,7 @@ def setup(app): "image_dark": "_static/compas_icon_white.png", # relative to parent of conf.py "text": project, }, + "navigation_depth": 2, } html_context = { diff --git a/docs/examples/PLACEHOLDER b/docs/examples/PLACEHOLDER deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/docs/examples.rst b/docs/examples/index.rst similarity index 71% rename from docs/examples.rst rename to docs/examples/index.rst index f65d96ae8d..3a84825364 100644 --- a/docs/examples.rst +++ b/docs/examples/index.rst @@ -1,10 +1,11 @@ + ******************************************************************************** Examples ******************************************************************************** .. toctree:: - :maxdepth: 2 - :titlesonly: - :glob: + :maxdepth: 1 + :titlesonly: + :caption: Basic Examples - examples/basics + basics diff --git a/docs/index.rst b/docs/index.rst index d374a09799..0bb34abf28 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,33 +1,70 @@ +:html_theme.sidebar_secondary.remove: true + ******************************************************************************** -compas_viewer +COMPAS Viewer ******************************************************************************** - +.. _compas.geomery: https://compas.dev/compas//latest/api/compas.geometry.html .. rst-class:: lead -Standalone viewer for COMPAS +Standalone viewer for COMPAS 2.0 with features: + +* **Fully COMPAS Support**: Full support for all :compas:`compas.geometry` (primitives, shapes, network, mesh, assembly, model, etc.) based on :compas:`compas.scene` structure ... +* **Universal Architecture**: Full support Mac, Windows, and Linux with Python 3.9+. More various platforms are coming soon ... +* **Installation Friendly**: Depend only on COMPAS, OpenGL and PySide6. Installation with pip is fast and easy ... +* **Flexible Customization**: Flexible customize your own UI layout with buttons, render display with colors, action with keyboard preferences ... +* **Data-driven Visualization**: Visualize your assembly data, mesh data, network data, and more with :compas:`compas.datastructures` ... +* **Easy-to-use Interaction**: Action-based interaction with mouse and keyboard, and easy-to-use API for your own interaction ... -.. .. figure:: /_images/ +.. figure:: /_images/PLACEHOLDER.png :figclass: figure :class: figure-img img-fluid +Installation +============ + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + installation + + +Tutorials +========= + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + tutorials/index + -Table of Contents -================= +Examples +======== .. toctree:: - :maxdepth: 3 - :titlesonly: + :maxdepth: 2 + :titlesonly: + + examples/index + + +API Reference +============= + +.. toctree:: + :maxdepth: 2 + + api/index - Introduction - installation - tutorials - examples - api - license +History +======= +COMPAS Viewer is the next generation of :mod:`compas_view2` which is beased on the 1.0 version of :mod:`compas`. +Experiencing years' iteraions, this new version of COMPAS Viewer is stabliy designed for wider senarios and use cases. Indices and tables ================== * :ref:`genindex` -* :ref:`modindex` +* :ref:`search` diff --git a/docs/license.rst b/docs/license.rst deleted file mode 100644 index e6a80ce019..0000000000 --- a/docs/license.rst +++ /dev/null @@ -1,5 +0,0 @@ -******************************************************************************** -License -******************************************************************************** - -.. literalinclude:: ../LICENSE diff --git a/docs/tutorials/configuratins.rst b/docs/tutorials/configuratins.rst new file mode 100644 index 0000000000..99b805a990 --- /dev/null +++ b/docs/tutorials/configuratins.rst @@ -0,0 +1,15 @@ +******************************************************************************** +File Structure +******************************************************************************** + +::`compas_viewer` reads its customized ::`.viewer` file. The file architecture is designed for better data exchange, collaboration, and communication. + +Concept +=========== + +1. **Folder-based** : ::`.viewer` file is a `.zip` folder (archive) that contains files in various formats. + +2. **Extendability** : ::`.viewer` file could contain any type of files. The core functions of viewer are `.json` based and the invoking functions are dictionary-find based, meaning that only missing parameters will cause the loading failure while redundant parameters will only be ignored. + +Quick Look +========== diff --git a/docs/tutorials/file_structure.rst b/docs/tutorials/file_structure.rst deleted file mode 100644 index e21464f49f..0000000000 --- a/docs/tutorials/file_structure.rst +++ /dev/null @@ -1,99 +0,0 @@ -******************************************************************************** -File Structure -******************************************************************************** - -::`compas_viewer` reads its customized ::`.viewer` file. The file architecture is designed for better data exchange, collaboration, and communication. - -Concept -=========== - -1. **Folder-based** : ::`.viewer` file is a `.zip` folder (archive) that contains files in various formats. - -2. **Extendability** : ::`.viewer` file could contain any type of files. The core functions of viewer are `.json` based and the invoking functions are dictionary-find based, meaning that only missing parameters will cause the loading failure while redundant parameters will only be ignored. - -Quick Look -========== - -.. figure:: _images/diagrams/generated/file_structure.svg - :figclass: figure - :class: figure-img img-fluid - - -Structure -========= - -- **FILENAME.viewer**: ::`.viewer` file is a `.zip` based folder that collect rich format of files ... - - - **viewer.json**: The viewer.json contains all the settings about the viewer application it self: with, height, fullscreen, ... - - - **about**: Basic info. | *str* | `"about": "Hello."` - - **title**: The title of the viewer. | *str* | `"title": "COMPAS Viewer"` - - **width**: The width of the viewer. | *int* | `"width": 1280` - - **height**: The height of the viewer. | *int* | `"height ": 720` - - **fullscreen**: Full screen option. | *bool* | `"fullscreen ": false` - - - **scene.json**: The scene.json contains all the settings about the scene: background color, grid, ... - - - **show_grid**: Show grid option. | *bool* | `"show_grid ": true` - - **view_mode**: View mode option. | *str* | `"view_mode ": "shaded"` - - **background_color**: Background color option. | *List* | `"background_color ": [1, 1, 1, 1]` - - **selection_color**: Selection color option. | *List* | `"selection_color ": [1.0, 1.0, 0.0]` - - - **ui.json**: The ui.json contains all the settings about the ui: sidedock, sidebar, statusbar, ... - - - **statusbar**: The statusbar key controls the statusbar behavior. | *Dict* | - - - **texts**: Controls the text in the statusbar. | *str* | `"texts": "Ready"` - - **show_fps**: Controls the fps status in the statusbar. | *bool* | `"show_fps": true` - - - **menubar**: The menubar key controls the menubar behavior. | *Dict* | - - - **enable_menubar**: If the menubar is displayed. false means no further menubar settings will not be applied. | *bool* | `"enable_menubar": true` - - **items**: An *ordered List* of items as *Dictionary* to put in the menubar ... | *List[Dict]* | - - - **text**: The name displayed on the menu item. | *type* | `"text": "View"` - - **items**: An *ordered List* of items to put inside the menu item. | *List[Dict]* | - - - **type**: The type of this group of item: "radio", "action", "separator" ... | *str* | `"type": "radio"` - - **text**: The menu item name displayed inside the menu. | *str* | `"text": "Shaded"` - - **action**: Function name to trigger when the menu item is clicked. | *str* | `"action": "view_shaded"` - - **...**: Other keys depending on the type. - - - **toolbar**: The toolbar key controls the toolbar behavior. | *Dict* | - - - **enable_toolbar**: If the toolbar is displayed. false means no further toolbar settings will not be applied. | *bool* | `"enable_toolbar": true` - - **items**: An *ordered List* of items as *Dictionary* to put in the toolbar ... | *List[Dict]* | - - - **type**: The type of this item: "action", "separator" ... | *str* | `"type": "action"` - - **text**: The toolbar item name displayed on the toolbar. | *str* | `"text": "Capture"` - - **action**: Function name to trigger when the toolbar item is clicked. | *str* | `"action": "view_capture"` - - - **sidebar**: The sidebar key controls the sidebar behavior. | *Dict* | - - - **enable_sidebar**: If the sidebar is displayed. false means no further sidebar settings will not be applied. | *bool* | `"enable_sidebar": true` - - **items**: An *ordered List* of items as *Dictionary* to put in the toolbar ... | *List[Dict]* | - - - **type**: The type of this item: "checkbox", "slider", "button" ... | *str* | `"type": "checkbox"` - - **text**: The sidebar item name displayed on the sidebar. | *str* | `"text": "Slide Point"` - - **...**: Other keys depending on the type. - - - **sidedocks**: ::`compas_viewer` provides sidedocks as the addition to the sidebar. Every single sidedock in this *list* of dideocks follow the basic configuration rule of the sidebar | *list* | - - - **controller.json**: The controller.json contains all the settings about controlling the viewer: mouse, keys, ... - - - **mouse**: The mouse-based control functions. The keys(functions) are fixed but items(bindings) are customizable. | *Dict* | - - - **pan**: The pan function. | *Dict* | `{"mouse": "r", "key": "shift"}` - - **rotate**: The rotate function. | *Dict* | `{"mouse": "r", "key": ""}` - - **box_selection**: The box_selection function. | *Dict* | `{"mouse": "l", "key": ""}` - - **drag_deselection**: The box_selection function. | *Dict* | `{"mouse": "l", "key": "control"}` - - **selection**: The box_selection function. | *Dict* | `{"mouse": "l", "key": ""}` - - **multi_selection**: The box_selection function. | *Dict* | `{"mouse": "l", "key": "shift"}` - - **deselection**: The box_selection function. | *Dict* | `{"mouse": "l", "key": "control"}` - - - **keys**: The key-based control functions. Both keys and items are customizable. Extended actions put in the actions folder | *Dict* | `{"zoom_selected": ["f"],"view_top": ["control", "f1"]}` - - - **actions**: Folder for containing the extended actions. - - **geometries.json**: The geometries.json is *dictionary* data that indicate all the geometry pointers and their relations. - - **geometry_data.json**: The geometry_data.json contains all the geometry information ( items are parsed `compas.geometry`, directory of a geometry file inside this folder, or URL directory). This is the targets of the pointers in the geometries.json - - **flow.json**: The flow function is a `ryven` based visual scripting tool. The documentation and development of flow will be developed later on ... diff --git a/docs/tutorials.rst b/docs/tutorials/index.rst similarity index 71% rename from docs/tutorials.rst rename to docs/tutorials/index.rst index 4c171c5684..6f8141445a 100644 --- a/docs/tutorials.rst +++ b/docs/tutorials/index.rst @@ -1,11 +1,11 @@ + ******************************************************************************** Tutorials ******************************************************************************** -.. toctree:: - :maxdepth: 1 - :titlesonly: - - tutorials/file_structure - +.. toctree:: + :maxdepth: 1 + :titlesonly: + :caption: Tutorials + configuratins diff --git a/src/compas_viewer/actions/__init__.py b/src/compas_viewer/actions/__init__.py index 9c40c7a36f..ad90e72d50 100644 --- a/src/compas_viewer/actions/__init__.py +++ b/src/compas_viewer/actions/__init__.py @@ -1,8 +1,8 @@ from collections import defaultdict -from typing import Any, Callable, Dict +from typing import Any, Callable -ITEM_ACTIONS: Dict[str, Callable] = defaultdict() +ITEM_ACTIONS: dict[str, Callable] = defaultdict() def register(name: str, action_class: Callable): diff --git a/src/compas_viewer/actions/select_all.py b/src/compas_viewer/actions/select_all.py index 62496e7a63..49a7efe1e6 100644 --- a/src/compas_viewer/actions/select_all.py +++ b/src/compas_viewer/actions/select_all.py @@ -7,4 +7,4 @@ class SelectAll(Action): def pressed_action(self): for obj in self.viewer.objects: obj.is_selected = True - self.viewer.render.update() + self.viewer.renderer.update() diff --git a/src/compas_viewer/actions/viewmode.py b/src/compas_viewer/actions/viewmode.py index 5bcecf3d04..ce2d18c6d8 100644 --- a/src/compas_viewer/actions/viewmode.py +++ b/src/compas_viewer/actions/viewmode.py @@ -5,25 +5,25 @@ class ViewTop(Action): """Switch to top.""" def pressed_action(self): - self.viewer.render.viewmode = "top" + self.viewer.renderer.viewmode = "top" class ViewPerspective(Action): """Switch to perspective.""" def pressed_action(self): - self.viewer.render.viewmode = "perspective" + self.viewer.renderer.viewmode = "perspective" class ViewFront(Action): """Switch to front.""" def pressed_action(self): - self.viewer.render.viewmode = "front" + self.viewer.renderer.viewmode = "front" class ViewRight(Action): """Switch to right.""" def pressed_action(self): - self.viewer.render.viewmode = "right" + self.viewer.renderer.viewmode = "right" diff --git a/src/compas_viewer/actions/zoom_selected.py b/src/compas_viewer/actions/zoom_selected.py index be6eb7a2e5..872d5a6bf7 100644 --- a/src/compas_viewer/actions/zoom_selected.py +++ b/src/compas_viewer/actions/zoom_selected.py @@ -26,9 +26,9 @@ def pressed_action(self): center = (max_corner + min_corner) / 2 distance = max(norm(max_corner - min_corner), 1) - self.viewer.render.camera.target = center - vec = (self.viewer.render.camera.target - self.viewer.render.camera.position) / norm( - self.viewer.render.camera.target - self.viewer.render.camera.position + self.viewer.renderer.camera.target = center + vec = (self.viewer.renderer.camera.target - self.viewer.renderer.camera.position) / norm( + self.viewer.renderer.camera.target - self.viewer.renderer.camera.position ) - self.viewer.render.camera.position = self.viewer.render.camera.target - vec * distance * 1.5 - self.viewer.render.update() + self.viewer.renderer.camera.position = self.viewer.renderer.camera.target - vec * distance * 1.5 + self.viewer.renderer.update() diff --git a/src/compas_viewer/components/__init__.py b/src/compas_viewer/components/__init__.py index f3c377aa5c..136372f48e 100644 --- a/src/compas_viewer/components/__init__.py +++ b/src/compas_viewer/components/__init__.py @@ -1 +1 @@ -from .render import Render # noqa: F401 +from .renderer import Renderer # noqa: F401 diff --git a/src/compas_viewer/components/render/__init__.py b/src/compas_viewer/components/renderer/__init__.py similarity index 75% rename from src/compas_viewer/components/render/__init__.py rename to src/compas_viewer/components/renderer/__init__.py index 0bce97d457..f3309443e7 100644 --- a/src/compas_viewer/components/render/__init__.py +++ b/src/compas_viewer/components/renderer/__init__.py @@ -1,4 +1,4 @@ -from .render import Render # noqa: F401 +from .renderer import Renderer # noqa: F401 from .camera import Camera # noqa: F401 from .shaders.shader import Shader # noqa: F401 from .selector import Selector # noqa: F401 diff --git a/src/compas_viewer/components/render/camera.py b/src/compas_viewer/components/renderer/camera.py similarity index 91% rename from src/compas_viewer/components/render/camera.py rename to src/compas_viewer/components/renderer/camera.py index cce5752d16..18c0402d70 100644 --- a/src/compas_viewer/components/render/camera.py +++ b/src/compas_viewer/components/renderer/camera.py @@ -3,9 +3,9 @@ from math import tan from typing import TYPE_CHECKING from typing import Callable -from typing import List + from typing import Optional -from typing import Tuple + from compas.geometry import Rotation from compas.geometry import Transformation @@ -21,7 +21,7 @@ if TYPE_CHECKING: # https://peps.python.org/pep-0484/#runtime-or-type-checking - from .render import Render + from .renderer import Renderer class Position(Vector): @@ -30,14 +30,14 @@ class Position(Vector): Parameters ---------- - vector : Tuple[float, float, float] + vector : tuple[float, float, float] The position of the camera. on_update : Callable A callback function that is called when the position changes. """ - def __init__(self, vector: Tuple[float, float, float], on_update: Optional[Callable] = None): + def __init__(self, vector: tuple[float, float, float], on_update: Optional[Callable] = None): self.on_update = on_update self.pause_update = True super().__init__(*vector) @@ -91,8 +91,8 @@ class Camera: Parameters ---------- - render : :class:`compas_viewer.components.render.Render`, - The parent render of the camera. + renderer : :class:`compas_viewer.components.renderer.Renderer`, + The parent renderer of the camera. Attributes ---------- @@ -109,11 +109,11 @@ class Camera: The location of the "near" clipping plane. far : float The location of the "far" clipping plane. - position : :class:`compas_viewer.components.render.camera.Position` + position : :class:`compas_viewer.components.renderer.camera.Position` The location the camera. - rotation : :class:`compas_viewer.components.render.camera.RotationEuler` + rotation : :class:`compas_viewer.components.renderer.camera.RotationEuler` The euler rotation of camera. - target : :class:`compas_viewer.components.render.camera.Position` + target : :class:`compas_viewer.components.renderer.camera.Position` The viewing target. Default is the origin of the world coordinate system. distance : float @@ -128,9 +128,9 @@ class Camera: The scale factor for camera's near, far and pan_delta. """ - def __init__(self, render: "Render"): - self.render = render - self.config = render.config.camera + def __init__(self, renderer: "Renderer"): + self.renderer = renderer + self.config = renderer.config.camera self._position = Position((0.0, 0.0, 10.0 * self.config.scale), on_update=self._on_position_update) self._rotation = RotationEuler((0, 0, 0), on_update=self._on_rotation_update) self._target = Position((0, 0, 0), on_update=self._on_target_update) @@ -139,7 +139,7 @@ def __init__(self, render: "Render"): self._target.pause_update = False # Camera position only modifiable in perspective view mode. self.reset_position() - if self.render.config.viewmode == "perspective": + if self.renderer.config.viewmode == "perspective": self.position = Position(self.config.position) self.target = Position(self.config.target) @@ -307,13 +307,13 @@ def _on_target_update(self, target: Position): def reset_position(self): """Reset the position of the camera based current view type.""" self.target.set(0, 0, 0, False) - if self.render.viewmode == "perspective": + if self.renderer.viewmode == "perspective": self.rotation.set(pi / 4, 0, -pi / 4, False) - if self.render.viewmode == "top": + if self.renderer.viewmode == "top": self.rotation.set(0, 0, 0, False) - if self.render.viewmode == "front": + if self.renderer.viewmode == "front": self.rotation.set(pi / 2, 0, 0, False) - if self.render.viewmode == "right": + if self.renderer.viewmode == "right": self.rotation.set(pi / 2, 0, pi / 2, False) def rotate(self, dx: float, dy: float): @@ -331,10 +331,10 @@ def rotate(self, dx: float, dy: float): Notes ----- Camera rotations are only available if the current view mode - is a perspective view (``camera.render.config.viewmode == "perspective"``). + is a perspective view (``camera.renderer.config.viewmode == "perspective"``). """ - if self.render.config.viewmode == "perspective": + if self.renderer.config.viewmode == "perspective": self.rotation += [-self.config.rotationdelta * dy, 0, -self.config.rotationdelta * dx] def pan(self, dx: float, dy: float): @@ -364,12 +364,12 @@ def zoom(self, steps: int = 1): ---------- steps : int The number of zoom increments, with each increment the size - of :attr:`compas_viewer.components.render.Camera.config.zoomdelta`. + of :attr:`compas_viewer.components.renderer.Camera.config.zoomdelta`. """ self.distance -= steps * self.config.zoomdelta * self.distance - def projection(self, width: int, height: int) -> List[List[float]]: + def projection(self, width: int, height: int) -> list[list[float]]: """Compute the projection matrix corresponding to the current camera settings. Parameters @@ -381,7 +381,7 @@ def projection(self, width: int, height: int) -> List[List[float]]: Returns ------- - List[List[float]] + list[list[float]] The transformation matrix as a `numpy` array in column-major order. Notes @@ -390,7 +390,7 @@ def projection(self, width: int, height: int) -> List[List[float]]: """ aspect = width / height - if self.render.viewmode == "perspective": + if self.renderer.viewmode == "perspective": P = self.perspective( self.config.fov, aspect, self.config.near * self.config.scale, self.config.far * self.config.scale ) @@ -404,12 +404,12 @@ def projection(self, width: int, height: int) -> List[List[float]]: ) return list(asfortranarray(P, dtype=float32)) - def viewworld(self) -> List[List[float]]: + def viewworld(self) -> list[list[float]]: """Compute the view-world matrix corresponding to the current camera settings. Returns ------- - List[List[float]] + list[list[float]] The transformation matrix in column-major order. Notes diff --git a/src/compas_viewer/components/render/render.py b/src/compas_viewer/components/renderer/renderer.py similarity index 95% rename from src/compas_viewer/components/render/render.py rename to src/compas_viewer/components/renderer/renderer.py index c133de9a70..563dde56c0 100644 --- a/src/compas_viewer/components/render/render.py +++ b/src/compas_viewer/components/renderer/renderer.py @@ -2,7 +2,7 @@ from math import ceil from typing import TYPE_CHECKING from typing import Any -from typing import List + from compas.geometry import transform_points_numpy from numpy import float32 @@ -28,9 +28,9 @@ from compas_viewer import Viewer -class Render(QOpenGLWidget): +class Renderer(QOpenGLWidget): """ - Render class for 3D rendering of COMPAS geometry. + Renderer class for 3D rendering of COMPAS geometry. We constantly use OpenGL version 2.1 and GLSL 120 with a Compatibility Profile at the moment. The width and height are not in its configuration since they are set by the parent layout. @@ -39,7 +39,7 @@ class Render(QOpenGLWidget): viewer : :class:`compas_viewer.viewer.Viewer` The viewer instance. config : :class:`compas_viewer.configurations.RenderConfig` - The render configuration. + The renderer configuration. """ def __init__(self, viewer: "Viewer", config: RenderConfig): @@ -72,11 +72,11 @@ def __init__(self, viewer: "Viewer", config: RenderConfig): @property def rendermode(self): """ - The render mode of the view. + The renderer mode of the view. Returns ------- - The render mode of the view. + The renderer mode of the view. """ return self._rendermode @@ -344,7 +344,7 @@ def keyReleaseEvent(self, event: QKeyEvent): # ========================================================================== def init(self): - """Initialize the render.""" + """Initialize the renderer.""" # Init the grid self.grid.init() @@ -405,9 +405,9 @@ def update_projection(self, w=None, h=None): Parameters ---------- w : int, optional - The width of the render, by default None. + The width of the renderer, by default None. h : int, optional - The height of the render, by default None. + The height of the renderer, by default None. """ w = w or self.viewer.config.width h = h or self.viewer.config.height @@ -436,25 +436,25 @@ def update_projection(self, w=None, h=None): def resize(self, w: int, h: int): """ - Resize the render. + Resize the renderer. Parameters ---------- w : int - The width of the render. + The width of the renderer. h : int - The height of the render. + The height of the renderer. """ self.update_projection(w, h) - def sort_objects_from_viewworld(self, objects: List[MeshObject], viewworld: List[List[float]]): + def sort_objects_from_viewworld(self, objects: list[MeshObject], viewworld: list[list[float]]): """Sort objects by the distances from their bounding box centers to camera location Parameters ---------- - objects : List[:class:`compas_viewer.scene.meshobject.MeshObject`] + objects : list[:class:`compas_viewer.scene.meshobject.MeshObject`] The objects to be sorted. - viewworld : List[List[float]] + viewworld : list[list[float]] The viewworld matrix. Returns @@ -479,9 +479,9 @@ def sort_objects_from_viewworld(self, objects: List[MeshObject], viewworld: List def paint(self): """ - Paint all the items in the render, which only be called by the paintGL function + Paint all the items in the renderer, which only be called by the paintGL function and determines the performance of the renders - This function introduces decision tree for different render modes and settings. + This function introduces decision tree for different renderer modes and settings. """ # Matrix update @@ -557,18 +557,18 @@ def paint(self): def paint_instance_map(self): """ - Paint the instance map for the selection or the instance render mode. + Paint the instance map for the selection or the instance renderer mode. Notes ----- The instance map is used by the selector to identify selected objects. - The mechanism of a :class:`compas_viewer.components.render.selector.Selector` + The mechanism of a :class:`compas_viewer.components.renderer.selector.Selector` is picking the color from instance map and then find the corresponding object. Anti aliasing, which is always force opened in many machines, can cause color picking inaccuracy. See Also -------- - :func:`compas_viewer.components.render.selector.Selector.ANTI_ALIASING_FACTOR` + :func:`compas_viewer.components.renderer.selector.Selector.ANTI_ALIASING_FACTOR` """ GL.glDisable(GL.GL_POINT_SMOOTH) GL.glDisable(GL.GL_LINE_SMOOTH) diff --git a/src/compas_viewer/components/render/selector.py b/src/compas_viewer/components/renderer/selector.py similarity index 80% rename from src/compas_viewer/components/render/selector.py rename to src/compas_viewer/components/renderer/selector.py index cd7fffd1d7..10767dce9f 100644 --- a/src/compas_viewer/components/render/selector.py +++ b/src/compas_viewer/components/renderer/selector.py @@ -14,7 +14,7 @@ from scipy.ndimage import zoom if TYPE_CHECKING: - from .render import Render + from .renderer import Renderer class Selector(QObject): @@ -22,13 +22,13 @@ class Selector(QObject): Parameters ---------- - render : :class:`compas_viewer.components.render.Render` - The render instance. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer instance. Attributes ---------- - render : :class:`compas_viewer.components.render.Render` - The render instance. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer instance. enable_selector : bool Enable the selector. selectioncolor : :class:`compas.colors.Color` @@ -52,16 +52,16 @@ class Selector(QObject): def __init__( self, - render: "Render", + renderer: "Renderer", ): - self.enable_selector = render.config.selector.enable_selector + self.enable_selector = renderer.config.selector.enable_selector if not self.enable_selector: return super().__init__() - self.render = render - self.viewer = render.viewer - self.controller = render.viewer.controller - self.selectioncolor = render.config.selector.selectioncolor + self.renderer = renderer + self.viewer = renderer.viewer + self.controller = renderer.viewer.controller + self.selectioncolor = renderer.config.selector.selectioncolor # Drag selection self.on_drag_selection: bool = False @@ -78,14 +78,14 @@ def select_action(self): """Select the object under the mouse cursor.""" # Deselect all objects first - for _, obj in self.render.viewer.instance_colors.items(): + for _, obj in self.renderer.viewer.instance_colors.items(): obj.is_selected = False x = self.controller.mouse.last_pos.x() y = self.controller.mouse.last_pos.y() instance_color = tuple(self.read_instance_map()[y][x]) - selected_obj = self.render.viewer.instance_colors.get(instance_color) # type: ignore + selected_obj = self.renderer.viewer.instance_colors.get(instance_color) # type: ignore if selected_obj: selected_obj.is_selected = True @@ -95,7 +95,7 @@ def deselect_action(self): y = self.controller.mouse.last_pos.y() instance_color = tuple(self.read_instance_map()[y][x]) - selected_obj = self.render.viewer.instance_colors.get(instance_color) # type: ignore + selected_obj = self.renderer.viewer.instance_colors.get(instance_color) # type: ignore if selected_obj: selected_obj.is_selected = False @@ -104,14 +104,14 @@ def multiselect_action(self): See Also -------- - :func:`compas_viewer.components.render.selector.Selector.select_action` + :func:`compas_viewer.components.renderer.selector.Selector.select_action` """ x = self.controller.mouse.last_pos.x() y = self.controller.mouse.last_pos.y() instance_color = tuple(self.read_instance_map()[y][x]) - selected_obj = self.render.viewer.instance_colors.get(instance_color) # type: ignore + selected_obj = self.renderer.viewer.instance_colors.get(instance_color) # type: ignore if selected_obj: selected_obj.is_selected = not selected_obj.is_selected @@ -119,7 +119,7 @@ def drag_selection_action(self): """Drag select the objects in the rectangle area.""" # Deselect all objects first - for _, obj in self.render.viewer.instance_colors.items(): + for _, obj in self.renderer.viewer.instance_colors.items(): obj.is_selected = False instance_map = self.read_instance_map() @@ -133,7 +133,7 @@ def drag_selection_action(self): [unique_colors[0][i] for i, count in enumerate(unique_colors[1]) if count > self.ANTI_ALIASING_FACTOR] ) - for color, obj in self.render.viewer.instance_colors.items(): + for color, obj in self.renderer.viewer.instance_colors.items(): if any(all(color == unique_colors, axis=1)): obj.is_selected = True continue @@ -143,7 +143,7 @@ def drag_deselection_action(self): See Also -------- - :func:`compas_viewer.components.render.selector.Selector.drag_selection_action` + :func:`compas_viewer.components.renderer.selector.Selector.drag_selection_action` """ instance_map = self.read_instance_map() @@ -157,7 +157,7 @@ def drag_deselection_action(self): [unique_colors[0][i] for i, count in enumerate(unique_colors[1]) if count > self.ANTI_ALIASING_FACTOR] ) - for color, obj in self.render.viewer.instance_colors.items(): + for color, obj in self.renderer.viewer.instance_colors.items(): if color in unique_colors: obj.is_selected = False continue @@ -183,10 +183,10 @@ def read_instance_map(self) -> NDArray: ---------- * https://doc.qt.io/qt-6/qscreen.html#devicePixelRatio-prop """ - r = self.render.devicePixelRatio() + r = self.renderer.devicePixelRatio() x_ratio = self.viewer.config.width / ceil(r * self.viewer.config.width) y_ratio = self.viewer.config.height / ceil(r * self.viewer.config.height) - instance_map = frombuffer(buffer=self.render.instance_buffer, dtype=uint8).reshape( + instance_map = frombuffer(buffer=self.renderer.instance_buffer, dtype=uint8).reshape( ceil(r * self.viewer.config.height), ceil(r * self.viewer.config.width), 3 ) instance_map = zoom(instance_map, (x_ratio, y_ratio, 1), order=1) diff --git a/src/compas_viewer/components/render/shaders/__init__.py b/src/compas_viewer/components/renderer/shaders/__init__.py similarity index 100% rename from src/compas_viewer/components/render/shaders/__init__.py rename to src/compas_viewer/components/renderer/shaders/__init__.py diff --git a/src/compas_viewer/components/render/shaders/arrow.frag b/src/compas_viewer/components/renderer/shaders/arrow.frag similarity index 100% rename from src/compas_viewer/components/render/shaders/arrow.frag rename to src/compas_viewer/components/renderer/shaders/arrow.frag diff --git a/src/compas_viewer/components/render/shaders/arrow.vert b/src/compas_viewer/components/renderer/shaders/arrow.vert similarity index 100% rename from src/compas_viewer/components/render/shaders/arrow.vert rename to src/compas_viewer/components/renderer/shaders/arrow.vert diff --git a/src/compas_viewer/components/render/shaders/grid.frag b/src/compas_viewer/components/renderer/shaders/grid.frag similarity index 100% rename from src/compas_viewer/components/render/shaders/grid.frag rename to src/compas_viewer/components/renderer/shaders/grid.frag diff --git a/src/compas_viewer/components/render/shaders/grid.vert b/src/compas_viewer/components/renderer/shaders/grid.vert similarity index 100% rename from src/compas_viewer/components/render/shaders/grid.vert rename to src/compas_viewer/components/renderer/shaders/grid.vert diff --git a/src/compas_viewer/components/render/shaders/instance.frag b/src/compas_viewer/components/renderer/shaders/instance.frag similarity index 100% rename from src/compas_viewer/components/render/shaders/instance.frag rename to src/compas_viewer/components/renderer/shaders/instance.frag diff --git a/src/compas_viewer/components/render/shaders/instance.vert b/src/compas_viewer/components/renderer/shaders/instance.vert similarity index 100% rename from src/compas_viewer/components/render/shaders/instance.vert rename to src/compas_viewer/components/renderer/shaders/instance.vert diff --git a/src/compas_viewer/components/render/shaders/model.frag b/src/compas_viewer/components/renderer/shaders/model.frag similarity index 100% rename from src/compas_viewer/components/render/shaders/model.frag rename to src/compas_viewer/components/renderer/shaders/model.frag diff --git a/src/compas_viewer/components/render/shaders/model.vert b/src/compas_viewer/components/renderer/shaders/model.vert similarity index 100% rename from src/compas_viewer/components/render/shaders/model.vert rename to src/compas_viewer/components/renderer/shaders/model.vert diff --git a/src/compas_viewer/components/render/shaders/shader.py b/src/compas_viewer/components/renderer/shaders/shader.py similarity index 95% rename from src/compas_viewer/components/render/shaders/shader.py rename to src/compas_viewer/components/renderer/shaders/shader.py index be04e13f64..f54fbdf01e 100644 --- a/src/compas_viewer/components/render/shaders/shader.py +++ b/src/compas_viewer/components/renderer/shaders/shader.py @@ -1,7 +1,5 @@ from pathlib import Path from typing import Any -from typing import List -from typing import Tuple from typing import Union from numpy import array @@ -15,14 +13,14 @@ def __init__(self, name: str = "mesh"): self.program = make_shader_program(name) self.locations = {} - def uniform4x4(self, name: str, value: List[List[float]]): + def uniform4x4(self, name: str, value: list[list[float]]): """Store a uniform 4x4 transformation matrix in the shader program at a named location. Parameters ---------- name : str The name of the location in the shader program. - value : List[List[float]] + value : list[list[float]] A 4x4 transformation matrix. """ _value = array(value) @@ -55,14 +53,14 @@ def uniform1f(self, name: str, value: float): location = GL.glGetUniformLocation(self.program, name) GL.glUniform1f(location, value) - def uniform3f(self, name: str, value: Union[Tuple[float, float, float], List[float]]): + def uniform3f(self, name: str, value: Union[tuple[float, float, float], list[float]]): """Store a uniform list of 3 floats in the shader program at a named location. Parameters ---------- name : str The name of the location in the shader program. - value : Union[Tuple[float, float, float], List[float]] + value : Union[tuple[float, float, float], list[float]] An iterable of 3 floats. """ location = GL.glGetUniformLocation(self.program, name) @@ -245,12 +243,12 @@ def draw_arrows(self, elements: Any, n: int, width: float, background: bool = Fa GL.glDrawArrays(GL.GL_LINES, 0, GL.GL_BUFFER_SIZE) GL.glEnable(GL.GL_POINT_SMOOTH) - def draw_2d_box(self, box_coords: Tuple[float, float, float, float], width: int, height: int): + def draw_2d_box(self, box_coords: tuple[float, float, float, float], width: int, height: int): """Draw a 2D box. Mostly used for box selection. Parameters ---------- - box_coords : Tuple[float, float, float, float] + box_coords : tuple[float, float, float, float] The coordinates of the box. The coordinates are in the format of (x1, y1, x2, y2). width : int The width of the viewport. diff --git a/src/compas_viewer/components/render/shaders/tag.frag b/src/compas_viewer/components/renderer/shaders/tag.frag similarity index 100% rename from src/compas_viewer/components/render/shaders/tag.frag rename to src/compas_viewer/components/renderer/shaders/tag.frag diff --git a/src/compas_viewer/components/render/shaders/tag.vert b/src/compas_viewer/components/renderer/shaders/tag.vert similarity index 100% rename from src/compas_viewer/components/render/shaders/tag.vert rename to src/compas_viewer/components/renderer/shaders/tag.vert diff --git a/src/compas_viewer/configurations/config.py b/src/compas_viewer/configurations/config.py index 7d1939a60a..ad5206295e 100644 --- a/src/compas_viewer/configurations/config.py +++ b/src/compas_viewer/configurations/config.py @@ -1,4 +1,3 @@ -from typing import Dict from typing import TypedDict from typing import Union @@ -10,12 +9,12 @@ class Config(Data): The abstract class for different configurations. """ - def __init__(self, config: Union[TypedDict, Dict]): + def __init__(self, config: Union[TypedDict, dict]): super(Config, self).__init__() self.config = config @property - def data(self): # -> Dict[str, Any]: + def data(self): # -> dict[str, Any]: return self.config @classmethod diff --git a/src/compas_viewer/configurations/controller_config.py b/src/compas_viewer/configurations/controller_config.py index 2fc30f106f..3fd4212bbf 100644 --- a/src/compas_viewer/configurations/controller_config.py +++ b/src/compas_viewer/configurations/controller_config.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Dict + from typing import Optional from typing import TypedDict @@ -40,7 +40,7 @@ class ControllerConfigType(TypedDict): drag_deselection: MouseConfigType multiselect: MouseConfigType deselect: MouseConfigType - actions: Dict[str, ActionConfigType] + actions: dict[str, ActionConfigType] class ActionConfig: @@ -102,13 +102,17 @@ def __init__(self, config: MouseConfigType): class ControllerConfig(Config): """ The class representation for the `controller.json` of - the class :class:`compas_viewer.controller.controller.Controller` + the class Controller. The controller.json contains all the settings about controlling the viewer: mouse, keys, ... Parameters ---------- config : :class:`ControllerConfigType` A TypedDict with defined keys and types. + + See Also + -------- + :class:`compas_viewer.components.controller.Controller` """ def __init__(self, config: ControllerConfigType): diff --git a/src/compas_viewer/configurations/render_config.py b/src/compas_viewer/configurations/render_config.py index 82b3aa5164..33960a6c4c 100644 --- a/src/compas_viewer/configurations/render_config.py +++ b/src/compas_viewer/configurations/render_config.py @@ -1,6 +1,5 @@ from pathlib import Path from typing import Literal -from typing import Tuple from typing import TypedDict from compas.colors import Color @@ -16,7 +15,7 @@ class SelectorConfigType(TypedDict): class SelectorConfig(Config): """ - The class representation of a selector class :class:`compas_viewer.components.render.selector.Selector` + The class representation of a selector class Selector. It contains all the settings about the selector: enable_selector, selectioncolor, ... Parameters @@ -24,6 +23,10 @@ class SelectorConfig(Config): config : SelectorConfigType A TypedDict with defined keys and types. + See Also + -------- + :class:`compas_viewer.components.renderer.selector.Selector` + """ def __init__(self, config: SelectorConfigType): @@ -42,8 +45,8 @@ class CameraConfigType(TypedDict): fov: float near: float far: float - position: Tuple[float, float, float] - target: Tuple[float, float, float] + position: tuple[float, float, float] + target: tuple[float, float, float] scale: float zoomdelta: float rotationdelta: float @@ -52,7 +55,7 @@ class CameraConfigType(TypedDict): class CameraConfig(Config): """ - The class representation of a camera class :class:`compas_viewer.components.render.camera.Camera` + The class representation of a camera class Camera. It contains all the settings about the camera: fov, near, far, position, target, ... Parameters @@ -60,6 +63,10 @@ class CameraConfig(Config): config : CameraConfigType A TypedDict with defined keys and types. + See Also + -------- + :class:`compas_viewer.components.renderer.camera.Camera` + """ def __init__(self, config: CameraConfigType): @@ -83,7 +90,7 @@ def from_json(cls, filepath) -> "CameraConfig": class RenderConfigType(TypedDict): show_grid: bool - gridsize: Tuple[float, int, float, int] + gridsize: tuple[float, int, float, int] show_gridz: bool viewmode: Literal["front", "right", "top", "perspective"] rendermode: Literal["wireframe", "shaded", "ghosted", "lighted", "instance"] @@ -95,14 +102,18 @@ class RenderConfigType(TypedDict): class RenderConfig(Config): """ - The class representation for the `render.json` of the class :class:`compas_viewer.components.render.Render` - The render.json contains all the settings about the render: background color, selection color, ... + The class representation for the `renderer.json` of the class Renderer. + The renderer.json contains all the settings about the renderer: background color, selection color, ... Parameters ---------- config : :class:`RenderConfigType` A TypedDict with defined keys and types. + See Also + -------- + :class:`compas_viewer.components.renderer.Renderer` + """ def __init__(self, config: RenderConfigType): @@ -122,7 +133,7 @@ def from_default(cls) -> "RenderConfig": """ Load the default configuration. """ - render_config = RenderConfig.from_json(Path(DATA, "default_config", "render.json")) + render_config = RenderConfig.from_json(Path(DATA, "default_config", "renderer.json")) assert isinstance(render_config, RenderConfig) return render_config diff --git a/src/compas_viewer/configurations/scene_config.py b/src/compas_viewer/configurations/scene_config.py index 8a47c61c99..3420bdf433 100644 --- a/src/compas_viewer/configurations/scene_config.py +++ b/src/compas_viewer/configurations/scene_config.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Tuple + from typing import TypedDict from compas.colors import Color @@ -24,14 +24,14 @@ class SceneConfigType(TypedDict): opacity: float hide_coplanaredges: bool use_vertexcolors: bool - framesize: Tuple[float, int, float, int] + framesize: tuple[float, int, float, int] show_framez: bool vectorsize: float class SceneConfig(Config): """ - The class representation for the `scene.json` of the class :class:`compas_viewer.scene.ViewerSceneObject` + The class representation for the `scene.json` of the class ViewerSceneObject. The scene.json contains all the settings about the general (default) appearance of the scene objects. Parameters @@ -39,6 +39,10 @@ class SceneConfig(Config): config : :class:`SceneConfigType` A TypedDict with defined keys and types. + See Also + -------- + :class:`compas_viewer.scene.ViewerSceneObject` + """ def __init__(self, config: SceneConfigType): diff --git a/src/compas_viewer/configurations/viewer_config.py b/src/compas_viewer/configurations/viewer_config.py index 2aee5b2a53..2eadc93097 100644 --- a/src/compas_viewer/configurations/viewer_config.py +++ b/src/compas_viewer/configurations/viewer_config.py @@ -21,7 +21,7 @@ class ViewerConfigType(TypedDict): class ViewerConfig(Config): """ - The class representation for the `viewer.json` of the class :class:`compas_viewer.viewer.Viewer` + The class representation for the `viewer.json` of the class Viewer. The viewer.json contains all the settings about the viewer application it self: width, height, fullscreen, ... Parameters @@ -29,6 +29,10 @@ class ViewerConfig(Config): config : :class:`ViewerConfigType` A TypedDict with defined keys and types. + See Also + -------- + :class:`compas_viewer.viewer.Viewer` + """ def __init__(self, config: ViewerConfigType): diff --git a/src/compas_viewer/controller/controller.py b/src/compas_viewer/controller/controller.py index a61f0e6f5a..ff885cbc89 100644 --- a/src/compas_viewer/controller/controller.py +++ b/src/compas_viewer/controller/controller.py @@ -1,5 +1,5 @@ from typing import TYPE_CHECKING -from typing import Dict + from PySide6.QtCore import Qt from PySide6.QtGui import QKeyEvent @@ -13,7 +13,7 @@ from .mouse import Mouse if TYPE_CHECKING: - from compas_viewer.components import Render + from compas_viewer.components import Renderer from compas_viewer.viewer import Viewer @@ -43,7 +43,7 @@ def __init__(self, viewer: "Viewer", config: ControllerConfig): self.viewer = viewer self.config = config self.mouse = Mouse() - self.actions: Dict[str, Action] = {} + self.actions: dict[str, Action] = {} for k, v in self.config.actions.items(): self.actions[k] = Action(k, self.viewer, v) @@ -51,15 +51,15 @@ def __init__(self, viewer: "Viewer", config: ControllerConfig): # Actions # ============================================================================== - def mouse_move_action(self, render: "Render", event: QMouseEvent): + def mouse_move_action(self, renderer: "Renderer", event: QMouseEvent): """ - The mouse move action of the render object. + The mouse move action of the renderer object. This function introduces elif for different actions, meaning only one action can be performed at a time. Parameters ---------- - render : :class:`compas_viewer.components.render.Render` - The render object. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer object. event : :class:`PySide6.QtGui.QMouseEvent` The Qt event. """ @@ -75,32 +75,32 @@ def mouse_move_action(self, render: "Render", event: QMouseEvent): event.buttons() == self.config.drag_selection.mouse and event.modifiers() == self.config.drag_selection.modifier ): - render.selector.on_drag_selection = True + renderer.selector.on_drag_selection = True # Drag deselection elif ( event.buttons() == self.config.drag_deselection.mouse and event.modifiers() == self.config.drag_deselection.modifier ): - render.selector.on_drag_selection = True + renderer.selector.on_drag_selection = True # Pan elif event.buttons() == self.config.pan.mouse and event.modifiers() == self.config.pan.modifier: - render.camera.pan(dx, dy) + renderer.camera.pan(dx, dy) # Rotate elif event.buttons() == self.config.rotate.mouse and event.modifiers() == self.config.rotate.modifier: - render.camera.rotate(dx, dy) + renderer.camera.rotate(dx, dy) # Record mouse position self.mouse.last_pos = event.pos() - def mouse_press_action(self, render: "Render", event: QMouseEvent): + def mouse_press_action(self, renderer: "Renderer", event: QMouseEvent): """ - The mouse press action of the render object. + The mouse press action of the renderer object. This function introduces elif for different actions, meaning only one action can be performed at a time. Parameters ---------- - render : :class:`compas_viewer.components.render.Render` - The render object. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer object. event : :class:`PySide6.QtGui.QMouseEvent` The Qt event. """ @@ -111,23 +111,23 @@ def mouse_press_action(self, render: "Render", event: QMouseEvent): event.buttons() == self.config.drag_selection.mouse and event.modifiers() == self.config.drag_selection.modifier ): - render.selector.drag_start_pt = event.pos() + renderer.selector.drag_start_pt = event.pos() # Drag deselection elif ( event.buttons() == self.config.drag_deselection.mouse and event.modifiers() == self.config.drag_deselection.modifier ): - render.selector.drag_start_pt = event.pos() + renderer.selector.drag_start_pt = event.pos() # Select: single left click. if event.buttons() == Qt.MouseButton.LeftButton and event.modifiers() == Qt.KeyboardModifier.NoModifier: - render.selector.select.emit() + renderer.selector.select.emit() # Multiselect elif event.buttons() == self.config.multiselect.mouse and event.modifiers() == self.config.multiselect.modifier: - render.selector.multiselect.emit() + renderer.selector.multiselect.emit() # Deselect elif event.buttons() == self.config.deselect.mouse and event.modifiers() == self.config.deselect.modifier: - render.selector.deselect.emit() + renderer.selector.deselect.emit() # Pan elif ( event.buttons() == self.config.pan.mouse @@ -139,58 +139,58 @@ def mouse_press_action(self, render: "Render", event: QMouseEvent): elif event.buttons() == self.config.rotate.mouse and event.modifiers() == self.config.rotate.modifier: QApplication.setOverrideCursor(Qt.CursorShape.SizeAllCursor) - def mouse_release_action(self, render: "Render", event: QMouseEvent): + def mouse_release_action(self, renderer: "Renderer", event: QMouseEvent): """ - The mouse release action of the render object. + The mouse release action of the renderer object. This function introduces elif for different actions, meaning only one action can be performed at a time. Parameters ---------- - render : :class:`compas_viewer.components.render.Render` - The render object. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer object. event : :class:`PySide6.QtGui.QMouseEvent` The Qt event. """ # Drag selection - if event.modifiers() == self.config.drag_selection.modifier and render.selector.on_drag_selection: - render.selector.on_drag_selection = False - render.selector.drag_end_pt = event.pos() - render.selector.drag_selection.emit() + if event.modifiers() == self.config.drag_selection.modifier and renderer.selector.on_drag_selection: + renderer.selector.on_drag_selection = False + renderer.selector.drag_end_pt = event.pos() + renderer.selector.drag_selection.emit() # Drag deselection - elif event.modifiers() == self.config.drag_deselection.modifier and render.selector.on_drag_selection: - render.selector.on_drag_selection = False - render.selector.drag_end_pt = event.pos() - render.selector.drag_deselection.emit() + elif event.modifiers() == self.config.drag_deselection.modifier and renderer.selector.on_drag_selection: + renderer.selector.on_drag_selection = False + renderer.selector.drag_end_pt = event.pos() + renderer.selector.drag_deselection.emit() if event.buttons() == Qt.KeyboardModifier.NoModifier or event.buttons() == Qt.MouseButton.NoButton: QApplication.restoreOverrideCursor() - def wheel_action(self, render: "Render", event: QWheelEvent): + def wheel_action(self, renderer: "Renderer", event: QWheelEvent): """ - The wheel action of the render object. + The wheel action of the renderer object. It is used from zooming action only. Parameters ---------- - render : :class:`compas_viewer.components.render.Render` - The render object. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer object. event : :class:`PySide6.QtGui.QWheelEvent` The Qt event. """ degrees = event.angleDelta().y() / 8 steps = degrees / 15 - render.camera.zoom(int(steps)) + renderer.camera.zoom(int(steps)) - def key_press_action(self, render: "Render", event: QKeyEvent): + def key_press_action(self, renderer: "Renderer", event: QKeyEvent): """ - The key press action of the render object. + The key press action of the renderer object. This function introduces break for different actions, meaning only one action can be performed at a time. Parameters ---------- - render : :class:`compas_viewer.components.render.Render` - The render object. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer object. event : :class:`PySide6.QtGui.QKeyEvent` The Qt event. """ @@ -199,15 +199,15 @@ def key_press_action(self, render: "Render", event: QKeyEvent): action.pressed.emit() break - def key_release_action(self, render: "Render", event: QKeyEvent): + def key_release_action(self, renderer: "Renderer", event: QKeyEvent): """ - The key release action of the render object. + The key release action of the renderer object. This function introduces break for different actions, meaning only one action can be performed at a time. Parameters ---------- - render : :class:`compas_viewer.components.render.Render` - The render object. + renderer : :class:`compas_viewer.components.renderer.Renderer` + The renderer object. event : :class:`PySide6.QtGui.QKeyEvent` The Qt event. """ diff --git a/src/compas_viewer/scene/boxobject.py b/src/compas_viewer/scene/boxobject.py index cd2e0466fb..e6ab65b653 100644 --- a/src/compas_viewer/scene/boxobject.py +++ b/src/compas_viewer/scene/boxobject.py @@ -5,7 +5,12 @@ class BoxObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Box` geometry.""" + """Viewer scene object for displaying COMPAS Box geometry. + + See Also + -------- + :class:`compas.geometry.Box` + """ def __init__(self, box: Box, **kwargs): super(BoxObject, self).__init__(mesh=Mesh.from_shape(box), **kwargs) diff --git a/src/compas_viewer/scene/brepobject.py b/src/compas_viewer/scene/brepobject.py index 988d24d0e1..498bb270c7 100644 --- a/src/compas_viewer/scene/brepobject.py +++ b/src/compas_viewer/scene/brepobject.py @@ -8,7 +8,7 @@ from compas_occ.brep import BRep class BRepObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas_occ.brep.Brep` geometry. + """Viewer scene object for displaying COMPAS BRep geometry. Attributes ---------- @@ -16,6 +16,10 @@ class BRepObject(MeshObject): The compas_occ Brep object. mesh : :class:`compas.datastructures.Mesh` The tesselation mesh representation of the Brep. + + See Also + -------- + :class:`compas_occ.brep.Brep` """ def __init__(self, brep: BRep, **kwargs): diff --git a/src/compas_viewer/scene/capsuleobject.py b/src/compas_viewer/scene/capsuleobject.py index 79269ec648..19c900a463 100644 --- a/src/compas_viewer/scene/capsuleobject.py +++ b/src/compas_viewer/scene/capsuleobject.py @@ -7,9 +7,14 @@ class CapsuleObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Capsule` geometry.""" + """Viewer scene object for displaying COMPAS Capsule geometry. + + See Also + -------- + :class:`compas.geometry.Capsule` + """ def __init__(self, capsule: Capsule, **kwargs): - self.u =kwargs.get("u", int(2 * pi * capsule.radius / self.LINEARDEFLECTION)) + self.u = kwargs.get("u", int(2 * pi * capsule.radius / self.LINEARDEFLECTION)) super(CapsuleObject, self).__init__(mesh=Mesh.from_shape(capsule, u=self.u), **kwargs) diff --git a/src/compas_viewer/scene/circleobject.py b/src/compas_viewer/scene/circleobject.py index ed99143ff0..9a9e71f092 100644 --- a/src/compas_viewer/scene/circleobject.py +++ b/src/compas_viewer/scene/circleobject.py @@ -9,11 +9,16 @@ class CircleObject(ViewerSceneObject, GeometryObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Circle` geometry.""" + """Viewer scene object for displaying COMPAS Circle geometry. + + See Also + -------- + :class:`compas.geometry.Circle` + """ def __init__(self, circle: Circle, **kwargs): self.geometry: Circle - self.u = kwargs.get("u",int(circle.circumference / self.LINEARDEFLECTION)) + self.u = kwargs.get("u", int(circle.circumference / self.LINEARDEFLECTION)) self.u_points = self._calculate_circle_points(circle) super().__init__(geometry=circle, **kwargs) diff --git a/src/compas_viewer/scene/coneobject.py b/src/compas_viewer/scene/coneobject.py index 55726cc48e..cb4d417d7b 100644 --- a/src/compas_viewer/scene/coneobject.py +++ b/src/compas_viewer/scene/coneobject.py @@ -7,7 +7,12 @@ class ConeObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Cone` geometry.""" + """Viewer scene object for displaying COMPAS Cone geometry. + + See Also + -------- + :class:`compas.geometry.Cone` + """ def __init__(self, cone: Cone, **kwargs): self.u = kwargs.get("u", int(2 * pi * cone.radius / self.LINEARDEFLECTION)) diff --git a/src/compas_viewer/scene/cylinderobject.py b/src/compas_viewer/scene/cylinderobject.py index 12ae8af9c4..1822a50684 100644 --- a/src/compas_viewer/scene/cylinderobject.py +++ b/src/compas_viewer/scene/cylinderobject.py @@ -7,9 +7,14 @@ class CylinderObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Cylinder` geometry.""" + """Viewer scene object for displaying COMPAS Cylinder geometry. + + See Also + -------- + :class:`compas.geometry.Cylinder` + """ def __init__(self, cylinder: Cylinder, **kwargs): - self.u =kwargs.get("u", int(2 * pi * cylinder.radius / self.LINEARDEFLECTION)) + self.u = kwargs.get("u", int(2 * pi * cylinder.radius / self.LINEARDEFLECTION)) super(CylinderObject, self).__init__(mesh=Mesh.from_shape(cylinder, u=self.u), **kwargs) diff --git a/src/compas_viewer/scene/ellipseobject.py b/src/compas_viewer/scene/ellipseobject.py index ce09892c51..25645769df 100644 --- a/src/compas_viewer/scene/ellipseobject.py +++ b/src/compas_viewer/scene/ellipseobject.py @@ -13,11 +13,16 @@ class EllipseObject(ViewerSceneObject, GeometryObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Ellipse` geometry.""" + """Viewer scene object for displaying COMPAS Ellipse geometry. + + See Also + -------- + :class:`compas.geometry.Ellipse` + """ def __init__(self, ellipse: Ellipse, **kwargs): self.geometry = ellipse - self.u = kwargs.get("u",int(self._proximate_circumference / self.LINEARDEFLECTION)) + self.u = kwargs.get("u", int(self._proximate_circumference / self.LINEARDEFLECTION)) self.u_points = self._calculate_ellipse_points(ellipse) super().__init__(geometry=ellipse, close=True, **kwargs) diff --git a/src/compas_viewer/scene/frameobject.py b/src/compas_viewer/scene/frameobject.py index 6c4344a2d0..a0bca5e2c4 100644 --- a/src/compas_viewer/scene/frameobject.py +++ b/src/compas_viewer/scene/frameobject.py @@ -1,5 +1,5 @@ from typing import Optional -from typing import Tuple + from compas.colors import Color from compas.geometry import Frame @@ -13,14 +13,14 @@ class FrameObject(ViewerSceneObject, GeometryObject): """ - The scene object of the :class:`compas.geometry.Frame` geometry. + The scene object of the COMPAS Frame geometry. With its modifiable cell size and dimension, the world grid is also created from this class. Parameters ---------- frame : :class:`compas.geometry.Frame` The frame geometry. - framesize : Tuple[float, int, float, int] + framesize : tuple[float, int, float, int] The size of the grid in [dx, nx, dy, ny] format. Notice that the `nx` and `ny` must be even numbers. show_framez : bool @@ -44,12 +44,16 @@ class FrameObject(ViewerSceneObject, GeometryObject): Notes ----- The frame object is always unselectable. + + See Also + -------- + :class:`compas.geometry.Frame` """ def __init__( self, frame: Frame, - framesize: Optional[Tuple[float, int, float, int]] = None, + framesize: Optional[tuple[float, int, float, int]] = None, show_framez: Optional[bool] = None, **kwargs ): diff --git a/src/compas_viewer/scene/lineobject.py b/src/compas_viewer/scene/lineobject.py index 4d87d4c9cf..8fc298b46b 100644 --- a/src/compas_viewer/scene/lineobject.py +++ b/src/compas_viewer/scene/lineobject.py @@ -6,7 +6,12 @@ class LineObject(ViewerSceneObject, GeometryObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Line` geometry.""" + """Viewer scene object for displaying COMPAS Line geometry. + + See Also + -------- + :class:`compas.geometry.Line` + """ def __init__(self, line: Line, **kwargs): super(LineObject, self).__init__(geometry=line, **kwargs) diff --git a/src/compas_viewer/scene/meshobject.py b/src/compas_viewer/scene/meshobject.py index 70befde199..c380fddf7d 100644 --- a/src/compas_viewer/scene/meshobject.py +++ b/src/compas_viewer/scene/meshobject.py @@ -12,7 +12,7 @@ class MeshObject(ViewerSceneObject, BaseMeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.datastructures.Mesh` geometry. + """Viewer scene object for displaying COMPAS Mesh geometry. Parameters ---------- @@ -22,22 +22,26 @@ class MeshObject(ViewerSceneObject, BaseMeshObject): True to hide the coplanar edges. It will override the value in the config file. use_vertexcolors : bool, optional True to use vertex color. It will override the value in the config file. - **kwargs : Dict, optional + **kwargs : dict, optional Additional options for the :class:`compas_viewer.scene.ViewerSceneObject`. Attributes ---------- mesh : :class:`compas.datastructures.Mesh` The mesh data structure. - vertex_xyz : Dict[int, List[float]] + vertex_xyz : dict[int, list[float]] View coordinates of the vertices. Defaults to the real coordinates. - vertexcolor : :class:`compas.colors.ColorDict` + vertexcolor : :class:`compas.colors.Colordict` Vertex colors. use_vertexcolors : bool True to use vertex color. Defaults to False. hide_coplanaredges : bool True to hide the coplanar edges. + + See Also + -------- + :class:`compas.datastructures.Mesh` """ def __init__( diff --git a/src/compas_viewer/scene/networkobject.py b/src/compas_viewer/scene/networkobject.py index f4727bc8e0..e686aea1dd 100644 --- a/src/compas_viewer/scene/networkobject.py +++ b/src/compas_viewer/scene/networkobject.py @@ -6,16 +6,20 @@ class NetworkObject(ViewerSceneObject, BaseNetworkObject): - """Viewer scene object for displaying COMPAS :class:`compas.datastructures.Network` data. + """Viewer scene object for displaying COMPAS Network data. Parameters ---------- network : :class:`compas.datastructures.Network` The network data structure. - **kwargs : Dict, optional + **kwargs : dict, optional Additional options for the :class:`compas_viewer.scene.ViewerSceneObject`. + See Also + -------- + :class:`compas.datastructures.Network` + """ def __init__(self, network: Network, **kwargs): diff --git a/src/compas_viewer/scene/nurbssurfaceobject.py b/src/compas_viewer/scene/nurbssurfaceobject.py index 383981115b..807f5edbe5 100644 --- a/src/compas_viewer/scene/nurbssurfaceobject.py +++ b/src/compas_viewer/scene/nurbssurfaceobject.py @@ -8,14 +8,19 @@ class NurbsSurfaceObject(ViewerSceneObject, GeometryObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.NurbsSurface` geometry.""" + """Viewer scene object for displaying COMPAS NurbsSurface geometry. + + See Also + -------- + :class:`compas.geometry.NurbsSurface` + """ def __init__(self, surface: NurbsSurface, **kwargs): super().__init__(geometry=surface, **kwargs) # LINEARDEFLECTION not implemented in NurbsSurface. - self.u = kwargs.get("u",int(16 + (0 * self.LINEARDEFLECTION))) - self.v = kwargs.get("v",int(16 + (0 * self.LINEARDEFLECTION))) + self.u = kwargs.get("u", int(16 + (0 * self.LINEARDEFLECTION))) + self.v = kwargs.get("v", int(16 + (0 * self.LINEARDEFLECTION))) self._triangles = [list(point) for triangle in surface.to_triangles(nu=self.u, nv=self.v) for point in triangle] diff --git a/src/compas_viewer/scene/planeobject.py b/src/compas_viewer/scene/planeobject.py index b36267fb3a..8332530a25 100644 --- a/src/compas_viewer/scene/planeobject.py +++ b/src/compas_viewer/scene/planeobject.py @@ -9,7 +9,7 @@ class PlaneObject(ViewerSceneObject, GeometryObject): """ - Viewer scene object for displaying COMPAS :class:`compas.geometry.Plane` geometry. + Viewer scene object for displaying COMPAS Plane geometry. Parameters ---------- @@ -18,6 +18,10 @@ class PlaneObject(ViewerSceneObject, GeometryObject): planesize : float The size of the plane. Default is 1. + + See Also + -------- + :class:`compas.geometry.Plane` """ def __init__(self, plane: Plane, planesize: float = 1, **kwargs): diff --git a/src/compas_viewer/scene/pointobject.py b/src/compas_viewer/scene/pointobject.py index 59e42c81ed..27394b8e02 100644 --- a/src/compas_viewer/scene/pointobject.py +++ b/src/compas_viewer/scene/pointobject.py @@ -6,7 +6,12 @@ class PointObject(ViewerSceneObject, GeometryObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Point` geometry.""" + """Viewer scene object for displaying COMPAS Point geometry. + + See Also + -------- + :class:`compas.geometry.Point` + """ def __init__(self, point: Point, **kwargs): super(PointObject, self).__init__(geometry=point, **kwargs) diff --git a/src/compas_viewer/scene/polygonobject.py b/src/compas_viewer/scene/polygonobject.py index 007015f6f7..c5778d99ab 100644 --- a/src/compas_viewer/scene/polygonobject.py +++ b/src/compas_viewer/scene/polygonobject.py @@ -5,7 +5,12 @@ class PolygonObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Polygon` geometry.""" + """Viewer scene object for displaying COMPAS Polygon geometry. + + See Also + -------- + :class:`compas.geometry.Polygon` + """ def __init__(self, polygon: Polygon, **kwargs): super(PolygonObject, self).__init__(mesh=Mesh.from_shape(polygon), **kwargs) diff --git a/src/compas_viewer/scene/polylineobject.py b/src/compas_viewer/scene/polylineobject.py index f0a995e1c8..4e3e1f784a 100644 --- a/src/compas_viewer/scene/polylineobject.py +++ b/src/compas_viewer/scene/polylineobject.py @@ -7,7 +7,12 @@ class PolylineObject(ViewerSceneObject, GeometryObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Polyline` geometry.""" + """Viewer scene object for displaying COMPAS Polyline geometry. + + See Also + -------- + :class:`compas.geometry.Polyline` + """ def __init__(self, polyline: Polyline, **kwargs): super(PolylineObject, self).__init__(geometry=polyline, **kwargs) diff --git a/src/compas_viewer/scene/sceneobject.py b/src/compas_viewer/scene/sceneobject.py index 6cf782a09f..7309f768a7 100644 --- a/src/compas_viewer/scene/sceneobject.py +++ b/src/compas_viewer/scene/sceneobject.py @@ -1,11 +1,10 @@ -from abc import abstractmethod from random import randint from typing import TYPE_CHECKING from typing import Any -from typing import Dict -from typing import List + + from typing import Optional -from typing import Tuple + from typing import Union from compas.colors import Color @@ -26,14 +25,15 @@ if TYPE_CHECKING: from compas_viewer import Viewer - from compas_viewer.components.render.shaders import Shader + from compas_viewer.components.renderer.shaders import Shader # Type template of point/line/face data for generating the buffers. -DataType = Tuple[List[Point], List[Color], List[List[int]]] +DataType = tuple[list[Point], list[Color], list[list[int]]] class ViewerSceneObject(SceneObject): - """Base class for all Viewer scene objects + """ + Base class for all Viewer scene objects which also includes the GL buffer creation and drawing methods. Parameters @@ -52,11 +52,11 @@ class ViewerSceneObject(SceneObject): Whether to show lines/edges of the object. It will override the value in the config file. show_faces : bool, optional Whether to show faces of the object. It will override the value in the config file. - pointscolor : Union[:class:`compas.colors.Color`, Dict[Any, :class:`compas.colors.Color`]], optional + pointscolor : Union[:class:`compas.colors.Color`, dict[Any, :class:`compas.colors.Color`]], optional The color or the dict of colors of the points. It will override the value in the config file. - linescolor : Union[:class:`compas.colors.Color`, Dict[Any, :class:`compas.colors.Color`]], optional + linescolor : Union[:class:`compas.colors.Color`, dict[Any, :class:`compas.colors.Color`]], optional The color or the dict of colors of the lines. It will override the value in the config file. - facescolor : Union[:class:`compas.colors.Color`, Dict[Any, :class:`compas.colors.Color`]], optional + facescolor : Union[:class:`compas.colors.Color`, dict[Any, :class:`compas.colors.Color`]], optional The color or the dict of colors the faces. It will override the value in the config file. lineswidth : float, optional The line width to be drawn on screen. It will override the value in the config file. @@ -68,7 +68,7 @@ class ViewerSceneObject(SceneObject): The configuration of the scene object. Defaults to None. It should be assigned though the :class:`compas_viewer.viewer.Viewer.add` method. Otherwise a exception will be raised. - **kwargs : Dict, optional + **kwargs : dict, optional Additional visualization options for specific objects. Attributes @@ -86,11 +86,11 @@ class ViewerSceneObject(SceneObject): Whether to show lines/edges of the object. show_faces : bool Whether to show faces of the object. - pointscolor : Dict[Any, :class:`compas.colors.Color`] + pointscolor : dict[Any, :class:`compas.colors.Color`] The color of the points. - linescolor : Dict[Any, :class:`compas.colors.Color`] + linescolor : dict[Any, :class:`compas.colors.Color`] The color of the lines. - facescolor : Dict[Any, :class:`compas.colors.Color`] + facescolor : dict[Any, :class:`compas.colors.Color`] The color of the faces. lineswidth : float The line width to be drawn on screen @@ -100,11 +100,15 @@ class ViewerSceneObject(SceneObject): The opacity of the object. background : bool Whether the object is drawn on the background with depth test disabled. - bounding_box : List[float], read-only + bounding_box : list[float], read-only The min and max corners of object bounding box, as a numpy array of shape (2, 3). bounding_box_center : :class:`compas.geometry.Point`, read-only The center of object bounding box, as a point. + See Also + -------- + :class:`compas.scene.SceneObject` + """ # Enhance line width for selection only. @@ -121,9 +125,9 @@ def __init__( show_points: Optional[bool] = None, show_lines: Optional[bool] = None, show_faces: Optional[bool] = None, - pointscolor: Optional[Union[Color, Dict[Any, Color]]] = None, - linescolor: Optional[Union[Color, Dict[Any, Color]]] = None, - facescolor: Optional[Union[Color, Dict[Any, Color]]] = None, + pointscolor: Optional[Union[Color, dict[Any, Color]]] = None, + linescolor: Optional[Union[Color, dict[Any, Color]]] = None, + facescolor: Optional[Union[Color, dict[Any, Color]]] = None, lineswidth: Optional[float] = None, pointssize: Optional[float] = None, opacity: Optional[float] = None, @@ -182,8 +186,8 @@ def __init__( # Geometric self.transformation: Optional[Transformation] = None - self._matrix_buffer: Optional[List[List[float]]] = None - self._bounding_box: Optional[List[float]] = None + self._matrix_buffer: Optional[list[list[float]]] = None + self._bounding_box: Optional[list[float]] = None self._bounding_box_center: Optional[Point] = None self._is_collection = False @@ -192,10 +196,10 @@ def __init__( self._lines_data: Optional[DataType] = None self._frontfaces_data: Optional[DataType] = None self._backfaces_data: Optional[DataType] = None - self._points_buffer: Optional[Dict[str, Any]] = None - self._lines_buffer: Optional[Dict[str, Any]] = None - self._frontfaces_buffer: Optional[Dict[str, Any]] = None - self._backfaces_buffer: Optional[Dict[str, Any]] = None + self._points_buffer: Optional[dict[str, Any]] = None + self._lines_buffer: Optional[dict[str, Any]] = None + self._frontfaces_buffer: Optional[dict[str, Any]] = None + self._backfaces_buffer: Optional[dict[str, Any]] = None @property def bounding_box(self): @@ -242,17 +246,17 @@ def _update_matrix(self): # buffer # ========================================================================== - def make_buffer_from_data(self, data: DataType) -> Dict[str, Any]: + def make_buffer_from_data(self, data: DataType) -> dict[str, Any]: """Create buffers from point/line/face data. Parameters ---------- - data : Tuple[List[:class:`compas.geometry.Point`], List[:class:`compas.colors.Color`], List[int]] + data : tuple[list[:class:`compas.geometry.Point`], list[:class:`compas.colors.Color`], list[int]] Contains positions, colors, elements for the buffer. Returns ------- - buffer_dict : Dict[str, Any] + buffer_dict : dict[str, Any] A dict with created buffer indexes. """ positions, colors, elements = data @@ -266,7 +270,7 @@ def make_buffer_from_data(self, data: DataType) -> Dict[str, Any]: def update_buffer_from_data( self, data: DataType, - buffer: Dict[str, Any], + buffer: dict[str, Any], update_positions: bool, update_colors: bool, update_elements: bool, @@ -275,9 +279,9 @@ def update_buffer_from_data( Parameters ---------- - data : Tuple[List[:class:`compas.geometry.Point`], List[:class:`compas.colors.Color`], List[int]] + data : tuple[list[:class:`compas.geometry.Point`], list[:class:`compas.colors.Color`], list[int]] Contains positions, colors, elements for the buffer. - buffer : Dict[str, Any] + buffer : dict[str, Any] The dict with created buffer indexes update_positions : bool Whether to update positions in the buffer dict. @@ -348,9 +352,9 @@ def update(self): """Update the object""" self._update_matrix() self.update_buffers() - self.viewer.render.update() + self.viewer.renderer.update() - def _update_bounding_box(self, positions: Optional[List[Point]] = None): + def _update_bounding_box(self, positions: Optional[list[Point]] = None): """Update the bounding box of the object""" if positions is None: positions = [] diff --git a/src/compas_viewer/scene/sphereobject.py b/src/compas_viewer/scene/sphereobject.py index a98b360582..56405980bc 100644 --- a/src/compas_viewer/scene/sphereobject.py +++ b/src/compas_viewer/scene/sphereobject.py @@ -7,7 +7,12 @@ class SphereObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Sphere` geometry.""" + """Viewer scene object for displaying COMPAS Sphere geometry. + + See Also + -------- + :class:`compas.geometry.Sphere` + """ def __init__(self, sphere: Sphere, **kwargs): self.u = kwargs.get("u", int(2 * pi * sphere.radius / self.LINEARDEFLECTION)) diff --git a/src/compas_viewer/scene/tagobject.py b/src/compas_viewer/scene/tagobject.py index 3176f7d6e2..c491fc25fb 100644 --- a/src/compas_viewer/scene/tagobject.py +++ b/src/compas_viewer/scene/tagobject.py @@ -1,7 +1,7 @@ from os import PathLike from os import path from typing import Optional -from typing import Tuple + from typing import Union from compas.colors import Color @@ -31,7 +31,7 @@ class Tag(Geometry): ---------- text : str The text of the tag. - position : Union[:class:`compas.geometry.Point`, Tuple[float, float, float]] + position : Union[:class:`compas.geometry.Point`, tuple[float, float, float]] The position of the tag. color : :class:`compas.colors.Color`, optional The color of the tag. @@ -76,7 +76,7 @@ def __eq__(self, other): def __init__( self, text: str, - position: Union[Point, Tuple[float, float, float]], + position: Union[Point, tuple[float, float, float]], color: Color = Color(0.0, 0.0, 0.0), height: float = 50, absolute_height: bool = False, @@ -104,15 +104,19 @@ def transform(self, transformation): class TagObject(ViewerSceneObject, GeometryObject): """ - The scene object of the :class:`compas_viewer.scene.Tag` geometry. + The scene object of the viewer tag geometry. Unlike :class:`compas_viewer.scene.TextObject`, tag object is a sprite always facing the camera. Parameters ---------- tag : :class:`compas_viewer.scene.Tag` The tag geometry. - **kwargs : Dict, optional + **kwargs : dict, optional Additional options for the :class:`compas_viewer.scene.ViewerSceneObject`. + + See Also + -------- + :class:`compas_viewer.scene.Tag` """ def __init__(self, tag: Tag, **kwargs): diff --git a/src/compas_viewer/scene/torusobject.py b/src/compas_viewer/scene/torusobject.py index 6a72d8fb53..1d35c5a5ab 100644 --- a/src/compas_viewer/scene/torusobject.py +++ b/src/compas_viewer/scene/torusobject.py @@ -7,10 +7,15 @@ class TorusObject(MeshObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Torus` geometry.""" + """Viewer scene object for displaying COMPAS Torus geometry. + + See Also + -------- + :class:`compas.geometry.Torus` + """ def __init__(self, torus: Torus, **kwargs): - self.u = kwargs.get("u",int(2 * pi * torus.radius_axis / self.LINEARDEFLECTION)) - self.v = kwargs.get("v",int(2 * pi * torus.radius_pipe / self.LINEARDEFLECTION)) + self.u = kwargs.get("u", int(2 * pi * torus.radius_axis / self.LINEARDEFLECTION)) + self.v = kwargs.get("v", int(2 * pi * torus.radius_pipe / self.LINEARDEFLECTION)) super(TorusObject, self).__init__(mesh=Mesh.from_shape(torus, u=self.u, v=self.v), **kwargs) diff --git a/src/compas_viewer/scene/vectorobject.py b/src/compas_viewer/scene/vectorobject.py index e127475f6d..f3c2b87c34 100644 --- a/src/compas_viewer/scene/vectorobject.py +++ b/src/compas_viewer/scene/vectorobject.py @@ -1,18 +1,18 @@ from typing import Any -from typing import Dict + from compas.geometry import Point from compas.geometry import Vector from compas.scene import GeometryObject -from compas_viewer.components.render.shaders.shader import Shader +from compas_viewer.components.renderer.shaders.shader import Shader from .sceneobject import DataType from .sceneobject import ViewerSceneObject class VectorObject(ViewerSceneObject, GeometryObject): - """Viewer scene object for displaying COMPAS :class:`compas.geometry.Vector` geometry. + """Viewer scene object for displaying COMPAS Vector geometry. Parameters ---------- @@ -21,7 +21,7 @@ class VectorObject(ViewerSceneObject, GeometryObject): anchor : :class:`compas.geometry.Point`, optional The anchor point of the vector. Default is the origin point. - **kwargs : Dict, optional + **kwargs : dict, optional Additional options for the :class:`compas_viewer.scene.ViewerSceneObject`. Notes @@ -31,6 +31,10 @@ class VectorObject(ViewerSceneObject, GeometryObject): that controls the width of the vector, the :attr:`compas_viewer.scene.vectorobject.VectorObject.config.vectorsize` (float 0-1) controls the size of the arrow. + + See Also + -------- + :class:`compas.geometry.Vector` """ # Fixed indices for the arrow faces: @@ -39,7 +43,7 @@ class VectorObject(ViewerSceneObject, GeometryObject): def __init__(self, vector: Vector, anchor: Point = Point(0, 0, 0), **kwargs): self._anchor = anchor super(VectorObject, self).__init__(geometry=vector, **kwargs) - self.arrow_buffer: Dict[str, Any] + self.arrow_buffer: dict[str, Any] def _read_lines_data(self) -> DataType: arrow_end = self._anchor + self.geometry * (1 - self.config.vectorsize) diff --git a/src/compas_viewer/utilities/gl.py b/src/compas_viewer/utilities/gl.py index bb683ca169..ad57e8a8b3 100644 --- a/src/compas_viewer/utilities/gl.py +++ b/src/compas_viewer/utilities/gl.py @@ -38,7 +38,7 @@ def make_vertex_buffer(data, dynamic=False): Parameters ---------- - data : List[float] + data : list[float] A flat list of floats. dynamic : bool, optional If True, the buffer is optimized for dynamic access. @@ -71,7 +71,7 @@ def make_index_buffer(data, dynamic=False): Parameters ---------- - data : List[int] + data : list[int] A flat list of ints. dynamic : bool, optional If True, the buffer is optimized for dynamic access. @@ -104,7 +104,7 @@ def update_vertex_buffer(data, buffer): Parameters ---------- - data : List[float] + data : list[float] A flat list of floats. buffer : int The ID of the buffer. @@ -123,7 +123,7 @@ def update_index_buffer(data, buffer): Parameters ---------- - data : List[int] + data : list[int] A flat list of ints. buffer : int The ID of the buffer. diff --git a/src/compas_viewer/utilities/qt.py b/src/compas_viewer/utilities/qt.py index 4a7dfbc28a..525028b8c2 100644 --- a/src/compas_viewer/utilities/qt.py +++ b/src/compas_viewer/utilities/qt.py @@ -14,19 +14,19 @@ def key_mapper( Parameters ---------- key : str - The key string which is the same as what it was called in the :class:`PySide6.QtCore.Qt`, + The key string which is the same as what it was called in the :QtCore:`PySide6.QtCore.Qt`, with **lowercases and with prefix&underscores removed**. Check out the reference page to find out the supported keys and the original names. type : Literal[0, 1, 2] The type of the key for mapping. - * 0 for :class:`PySide6.QtCore.Qt.Key`, - * 1 for :class:`PySide6.QtCore.Qt.KeyboardModifier`, - * 2 for :class:`PySide6.QtCore.Qt.MouseButton`. + * 0 for :QtCore:`PySide6.QtCore.Qt.Key`, + * 1 for :QtCore:`PySide6.QtCore.Qt.KeyboardModifier`, + * 2 for :QtCore:`PySide6.QtCore.Qt.MouseButton`. Returns ------- - Literal[:class:`Qt.Key`, :class:`Qt.KeyboardModifier`, :class:`Qt.MouseButton`] + Literal[:QtCore:`PySide6.QtCore.Qt.Key`, :QtCore:`PySide6.QtCore.Qt.KeyboardModifier`, :QtCore:`PySide6.QtCore.Qt.MouseButton`] The mapped Qt key. Notes @@ -36,9 +36,9 @@ def key_mapper( This function handles: - * :class:`PySide6.QtCore.Qt.Key` - * :class:`PySide6.QtCore.Qt.KeyboardModifier` - * :class:`PySide6.QtCore.Qt.MouseButton` + * :QtCore:`PySide6.QtCore.Qt.Key` + * :QtCore:`PySide6.QtCore.Qt.KeyboardModifier` + * :QtCore:`PySide6.QtCore.Qt.MouseButton` Examples -------- diff --git a/src/compas_viewer/viewer.py b/src/compas_viewer/viewer.py index e0578e460c..7e0df6fcd5 100644 --- a/src/compas_viewer/viewer.py +++ b/src/compas_viewer/viewer.py @@ -4,11 +4,8 @@ from typing import TYPE_CHECKING from typing import Any from typing import Callable -from typing import Dict -from typing import List from typing import Literal from typing import Optional -from typing import Tuple from typing import Union from compas.colors import Color @@ -25,7 +22,7 @@ from compas_viewer import DATA from compas_viewer.actions import Action from compas_viewer.actions import register -from compas_viewer.components import Render +from compas_viewer.components import Renderer from compas_viewer.configurations import ActionConfig from compas_viewer.configurations import ActionConfigType from compas_viewer.configurations import ControllerConfig @@ -133,7 +130,7 @@ def __init__( self.controller_config = ControllerConfig.from_default() else: self.config = ViewerConfig.from_json(Path(configpath, "viewer.json")) - self.render_config = RenderConfig.from_json(Path(configpath, "render.json")) + self.render_config = RenderConfig.from_json(Path(configpath, "renderer.json")) self.scene_config = SceneConfig.from_json(Path(configpath, "scene.json")) self.controller_config = ControllerConfig.from_json(Path(configpath, "controller.json")) @@ -161,10 +158,10 @@ def __init__( self.frame_count: int = 0 # Selection - self.instance_colors: Dict[Tuple[int, int, int], ViewerSceneObject] = {} + self.instance_colors: dict[tuple[int, int, int], ViewerSceneObject] = {} # Primitive - self.objects: List[ViewerSceneObject] + self.objects: list[ViewerSceneObject] self._init() @@ -200,8 +197,8 @@ def _init(self): is_visible=True, config=self.scene_config, ) - self.render = Render(self, self.render_config) - self._window.setCentralWidget(self.render) + self.renderer = Renderer(self, self.render_config) + self._window.setCentralWidget(self.renderer) self._window.setContentsMargins(0, 0, 0, 0) self._app.references.add(self._window) # type: ignore self._window.resize(self.config.width, self.config.height) @@ -399,17 +396,17 @@ def rotate(frame): raise ValueError("Must specify either interval or timeout.") def outer(func: Callable): - def render(): + def renderer(): func(self.frame_count) - self.render.update() + self.renderer.update() self.frame_count += 1 if frames is not None and self.frame_count >= frames: self.timer.stop() if interval: - self.timer = Timer(interval=interval, callback=render) + self.timer = Timer(interval=interval, callback=renderer) if timeout: - self.timer = Timer(interval=timeout, callback=render, singleshot=True) + self.timer = Timer(interval=timeout, callback=renderer, singleshot=True) self.frame_count = 0 @@ -429,9 +426,9 @@ def add( show_points: Optional[bool] = None, show_lines: Optional[bool] = None, show_faces: Optional[bool] = None, - pointscolor: Optional[Union[Color, Dict[Any, List[float]]]] = None, - linescolor: Optional[Union[Color, Dict[Any, List[float]]]] = None, - facescolor: Optional[Union[Color, Dict[Any, List[float]]]] = None, + pointscolor: Optional[Union[Color, dict[Any, list[float]]]] = None, + linescolor: Optional[Union[Color, dict[Any, list[float]]]] = None, + facescolor: Optional[Union[Color, dict[Any, list[float]]]] = None, lineswidth: Optional[float] = None, pointssize: Optional[float] = None, opacity: Optional[float] = None, @@ -467,13 +464,13 @@ def add( show_faces : bool, optional Whether to show faces of the object. It will override the value in the scene config file. - pointscolor : Union[:class:`compas.colors.Color`, Dict[Any, :class:`compas.colors.Color`], optional + pointscolor : Union[:class:`compas.colors.Color`, dict[Any, :class:`compas.colors.Color`], optional The color or the dict of colors of the points. It will override the value in the scene config file. - linescolor : Union[:class:`compas.colors.Color`, Dict[Any, :class:`compas.colors.Color`], optional + linescolor : Union[:class:`compas.colors.Color`, dict[Any, :class:`compas.colors.Color`], optional The color or the dict of colors of the lines. It will override the value in the scene config file. - facescolor : Union[:class:`compas.colors.Color`, Dict[Any, :class:`compas.colors.Color`], optional + facescolor : Union[:class:`compas.colors.Color`, dict[Any, :class:`compas.colors.Color`], optional The color or the dict of colors the faces. It will override the value in the scene config file. lineswidth : float, optional @@ -491,7 +488,7 @@ def add( use_vertexcolors : bool, optional Whether to use vertex color. It will override the value in the scene config file. - **kwargs : Dict, optional + **kwargs : dict, optional The other possible parameters to be passed to the object. Returns @@ -583,7 +580,7 @@ def add_action( name = pressed_action.__name__ if modifier is None: modifier = "no" - config: ActionConfigType = {"key": key, "modifier": modifier} + config = ActionConfigType({"key": key, "modifier": modifier}) class CustomAction(Action): def pressed_action(self): From 3bbadc27146a7be8332acac5df3be248be133794 Mon Sep 17 00:00:00 2001 From: Zac Zhang Date: Thu, 11 Jan 2024 09:59:52 +0100 Subject: [PATCH 2/4] update ready for the review --- CHANGELOG.md | 2 + docs/api/index.rst | 66 +++++++++++-------- docs/conf.py | 5 +- docs/index.rst | 2 +- docs/installation.rst | 31 +++++++++ docs/tutorials/configuratins.rst | 15 ----- docs/tutorials/configurations.rst | 15 +++++ docs/tutorials/index.rst | 2 +- src/compas_viewer/actions/action.py | 4 +- .../components/renderer/renderer.py | 21 +++--- .../configurations/controller_config.py | 8 +-- src/compas_viewer/controller/controller.py | 12 ++-- src/compas_viewer/controller/mouse.py | 4 +- src/compas_viewer/utilities/qt.py | 3 +- 14 files changed, 119 insertions(+), 71 deletions(-) delete mode 100644 docs/tutorials/configuratins.rst create mode 100644 docs/tutorials/configurations.rst diff --git a/CHANGELOG.md b/CHANGELOG.md index f08e7bc776..3bd921a423 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added +* Added `installation` documentation. * Added documentations: index, api, etc. Mockups style is improved. * Added `DataType` as the data type template for generating the buffer. * Added `NetworkObject` for the scene objects. @@ -45,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `NetworkObject`. ### Changed +* The `Index` page. * Typing hints improved, now `compas_viewer` only support Python 3.9+. * Fixed the bug of the `Selector`, drag selection is now more accurate. * More performative instance map and QObject-based selection architecture. diff --git a/docs/api/index.rst b/docs/api/index.rst index 28cd3b562d..490829091e 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -3,57 +3,65 @@ API Reference ******************************************************************************** -This pacakge provides a viewer for COMPAS. +This package provides a viewer for COMPAS. -.. Viewer -.. ------ +Viewer +------ -.. .. toctree:: -.. :maxdepth: 1 -.. :titlesonly: +.. toctree:: + :maxdepth: 1 + :titlesonly: -.. compas_viewer.viewer + compas_viewer.viewer -.. Scene and Objects -.. ----------------- +Scene and Objects +----------------- -.. .. toctree:: -.. :maxdepth: 1 -.. :titlesonly: +.. toctree:: + :maxdepth: 1 + :titlesonly: -.. compas_viewer.scene + compas_viewer.scene -.. Controller and Actions -.. ---------------------- +Controller and Actions +---------------------- -.. .. toctree:: -.. :maxdepth: 1 -.. :titlesonly: +.. toctree:: + :maxdepth: 1 + :titlesonly: -.. compas_viewer.controller -.. compas_viewer.actions + compas_viewer.controller + compas_viewer.actions -.. Components and Configurations -.. ----------------------------- +Components and Configurations +----------------------------- -.. .. toctree:: -.. :maxdepth: 1 -.. :titlesonly: +.. toctree:: + :maxdepth: 1 + :titlesonly: -.. compas_viewer.components -.. compas_viewer.configurations + compas_viewer.components + compas_viewer.configurations -Layout and Utilities +Layout and UI -------------------- .. toctree:: :maxdepth: 1 :titlesonly: + compas_viewer.layout + + +Utilities +--------- +.. toctree:: + :maxdepth: 1 + :titlesonly: + compas_viewer.utilities - .. compas_viewer.layout diff --git a/docs/conf.py b/docs/conf.py index c45a4dd946..7c0192243d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -88,9 +88,10 @@ def setup(app): # extlinks extlinks = { - "gl": ("https://pyopengl.sourceforge.net/documentation/manual-3.0/%s.html", "%s"), + "GL": ("https://pyopengl.sourceforge.net/documentation/manual-3.0/%s.html", "%s"), "QtCore": ("https://doc.qt.io/qtforpython-6/PySide6/QtCore/Qt.html#PySide6.QtCore.%s", "%s"), - # "QtCore": ("https://doc.qt.io/qtforpython-6/PySide6/QtCore/Qt.html#%s", "%s"), + "PySide6": ("https://doc.qt.io/qtforpython-6/%s.html", "%s"), + "compas": ("https://compas.dev/compas//latest/api/%s.html", "%s"), } # from pytorch diff --git a/docs/index.rst b/docs/index.rst index 0bb34abf28..bd6f6c29a9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,11 +3,11 @@ ******************************************************************************** COMPAS Viewer ******************************************************************************** -.. _compas.geomery: https://compas.dev/compas//latest/api/compas.geometry.html .. rst-class:: lead Standalone viewer for COMPAS 2.0 with features: + * **Fully COMPAS Support**: Full support for all :compas:`compas.geometry` (primitives, shapes, network, mesh, assembly, model, etc.) based on :compas:`compas.scene` structure ... * **Universal Architecture**: Full support Mac, Windows, and Linux with Python 3.9+. More various platforms are coming soon ... * **Installation Friendly**: Depend only on COMPAS, OpenGL and PySide6. Installation with pip is fast and easy ... diff --git a/docs/installation.rst b/docs/installation.rst index a2d3ef9c94..6c452f84e0 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -1,3 +1,34 @@ ******************************************************************************** Installation ******************************************************************************** +COMPAS Viewer can be easily installed on multiple platforms, using popular package managers such as conda or pip. + +If you do not have COMPAS installed +=================================== +Check out the COMPAS installation instructions at https://compas.dev/compas/latest/userguide/installation.html + +If you have COMPAS installed +============================ +Activate your COMPAS environment install COMPAS Viewer from `pip`. + +.. code-block:: bash + + pip install pyside freetype-py pyopengl PySide6 + pip install compas_viewer + +Verify the installation +======================= +COMPAS Viewer can be simply lunched by the following command in your terminal: + +.. code-block:: bash + + python -m compas_viewer + +Update with pip +=============== +Update COMPAS Viewer to the latest version with pip. + +.. code-block:: bash + + pip install --upgrade compas_viewer + diff --git a/docs/tutorials/configuratins.rst b/docs/tutorials/configuratins.rst deleted file mode 100644 index 99b805a990..0000000000 --- a/docs/tutorials/configuratins.rst +++ /dev/null @@ -1,15 +0,0 @@ -******************************************************************************** -File Structure -******************************************************************************** - -::`compas_viewer` reads its customized ::`.viewer` file. The file architecture is designed for better data exchange, collaboration, and communication. - -Concept -=========== - -1. **Folder-based** : ::`.viewer` file is a `.zip` folder (archive) that contains files in various formats. - -2. **Extendability** : ::`.viewer` file could contain any type of files. The core functions of viewer are `.json` based and the invoking functions are dictionary-find based, meaning that only missing parameters will cause the loading failure while redundant parameters will only be ignored. - -Quick Look -========== diff --git a/docs/tutorials/configurations.rst b/docs/tutorials/configurations.rst new file mode 100644 index 0000000000..bf22680b3b --- /dev/null +++ b/docs/tutorials/configurations.rst @@ -0,0 +1,15 @@ +******************************************************************************** +File Structure +******************************************************************************** + +.. ::`compas_viewer` reads its customized ::`.viewer` file. The file architecture is designed for better data exchange, collaboration, and communication. + +.. Concept +.. =========== + +.. 1. **Folder-based** : ::`.viewer` file is a `.zip` folder (archive) that contains files in various formats. + +.. 2. **Extendability** : ::`.viewer` file could contain any type of files. The core functions of viewer are `.json` based and the invoking functions are dictionary-find based, meaning that only missing parameters will cause the loading failure while redundant parameters will only be ignored. + +.. Quick Look +.. ========== diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst index 6f8141445a..ab546e2e7f 100644 --- a/docs/tutorials/index.rst +++ b/docs/tutorials/index.rst @@ -8,4 +8,4 @@ Tutorials :titlesonly: :caption: Tutorials - configuratins + configurations diff --git a/src/compas_viewer/actions/action.py b/src/compas_viewer/actions/action.py index 67911197ea..ccb2c2f942 100644 --- a/src/compas_viewer/actions/action.py +++ b/src/compas_viewer/actions/action.py @@ -33,9 +33,9 @@ class Action(QObject): The viewer object. config : :class:`compas_viewer.configurations.controller_config.ActionConfig` The action configuration. - key : :class:`PySide6.QtCore.Qt.Key` + key : :QtCore:`PySide6.QtCore.Qt.Key` The key of the action. - modifier : :class:`PySide6.QtCore.Qt.KeyboardModifier` + modifier : :QtCore:`PySide6.QtCore.Qt.KeyboardModifier` The modifier of the action. References diff --git a/src/compas_viewer/components/renderer/renderer.py b/src/compas_viewer/components/renderer/renderer.py index 563dde56c0..495987e5d1 100644 --- a/src/compas_viewer/components/renderer/renderer.py +++ b/src/compas_viewer/components/renderer/renderer.py @@ -135,7 +135,12 @@ def opacity(self) -> float: # ========================================================================== def clear(self): - """Clear the view.""" + """Clear the view. + + See Also + -------- + :GL:`glClear` + """ GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) # type: ignore def initializeGL(self): @@ -218,12 +223,12 @@ def paintGL(self): def mouseMoveEvent(self, event: QMouseEvent): """ Callback for the mouse move event which passes the event to the controller. - Inherited from :class:`PySide6.QtOpenGLWidgets.QOpenGLWidget`. + Inherited from :PySide6:`PySide6/QtOpenGLWidgets/QOpenGLWidget`. Parameters ---------- - event : :class:`PySide6.QtGui.QMouseEvent` + event : :PySide6:`PySide6/QtGui/QMouseEvent` The Qt event. See Also @@ -244,7 +249,7 @@ def mousePressEvent(self, event: QMouseEvent): Parameters ---------- - event : :class:`PySide6.QtGui.QMouseEvent` + event : :PySide6:`PySide6/QtGui/QMouseEvent` The Qt event. See Also @@ -265,7 +270,7 @@ def mouseReleaseEvent(self, event: QMouseEvent): Parameters ---------- - event : :class:`PySide6.QtGui.QMouseEvent` + event : :PySide6:`PySide6/QtGui/QMouseEvent` The Qt event. See Also @@ -286,7 +291,7 @@ def wheelEvent(self, event: QWheelEvent): Parameters ---------- - event : :class:`PySide6.QtGui.QWheelEvent` + event : :PySide6:`PySide6/QtGui/QWheelEvent` The Qt event. See Also @@ -307,7 +312,7 @@ def keyPressEvent(self, event: QKeyEvent): Parameters ---------- - event : :class:`PySide6.QtGui.QKeyEvent` + event : :PySide6:`PySide6/QtGui/QKeyEvent` The Qt event. See Also @@ -326,7 +331,7 @@ def keyReleaseEvent(self, event: QKeyEvent): Parameters ---------- - event : :class:`PySide6.QtGui.QKeyEvent` + event : :PySide6:`PySide6/QtGui/QKeyEvent` The Qt event. See Also diff --git a/src/compas_viewer/configurations/controller_config.py b/src/compas_viewer/configurations/controller_config.py index 3fd4212bbf..0a7decac35 100644 --- a/src/compas_viewer/configurations/controller_config.py +++ b/src/compas_viewer/configurations/controller_config.py @@ -57,9 +57,9 @@ class ActionConfig: ---------- config : :class:`ActionConfigType` A TypedDict with defined keys and types. - key : :class:`PySide6.QtCore.Qt.Key` + key : :QtCore:`PySide6.QtCore.Qt.Key` The Qt key. - modifier : :class:`PySide6.QtCore.Qt.KeyboardModifier` + modifier : :QtCore:`PySide6.QtCore.Qt.KeyboardModifier` The Qt modifier. """ @@ -85,9 +85,9 @@ class MouseConfig: ---------- config : :class:`MouseConfigType` A TypedDict with defined keys and types. - mouse : :class:`PySide6.QtCore.Qt.MouseButton` + mouse : :QtCore:`PySide6.QtCore.Qt.MouseButton` The Qt mouse. - modifier : :class:`PySide6.QtCore.Qt.KeyboardModifier` + modifier : :QtCore:`PySide6.QtCore.Qt.KeyboardModifier` The Qt modifier. """ diff --git a/src/compas_viewer/controller/controller.py b/src/compas_viewer/controller/controller.py index ff885cbc89..1b77583ce1 100644 --- a/src/compas_viewer/controller/controller.py +++ b/src/compas_viewer/controller/controller.py @@ -60,7 +60,7 @@ def mouse_move_action(self, renderer: "Renderer", event: QMouseEvent): ---------- renderer : :class:`compas_viewer.components.renderer.Renderer` The renderer object. - event : :class:`PySide6.QtGui.QMouseEvent` + event : :PySide6:`PySide6/QtGui/QMouseEvent` The Qt event. """ @@ -101,7 +101,7 @@ def mouse_press_action(self, renderer: "Renderer", event: QMouseEvent): ---------- renderer : :class:`compas_viewer.components.renderer.Renderer` The renderer object. - event : :class:`PySide6.QtGui.QMouseEvent` + event : :PySide6:`PySide6/QtGui/QMouseEvent` The Qt event. """ self.mouse.last_pos = event.pos() @@ -148,7 +148,7 @@ def mouse_release_action(self, renderer: "Renderer", event: QMouseEvent): ---------- renderer : :class:`compas_viewer.components.renderer.Renderer` The renderer object. - event : :class:`PySide6.QtGui.QMouseEvent` + event : :PySide6:`PySide6/QtGui/QMouseEvent` The Qt event. """ @@ -175,7 +175,7 @@ def wheel_action(self, renderer: "Renderer", event: QWheelEvent): ---------- renderer : :class:`compas_viewer.components.renderer.Renderer` The renderer object. - event : :class:`PySide6.QtGui.QWheelEvent` + event : :PySide6:`PySide6/QtGui/QWheelEvent` The Qt event. """ degrees = event.angleDelta().y() / 8 @@ -191,7 +191,7 @@ def key_press_action(self, renderer: "Renderer", event: QKeyEvent): ---------- renderer : :class:`compas_viewer.components.renderer.Renderer` The renderer object. - event : :class:`PySide6.QtGui.QKeyEvent` + event : :PySide6:`PySide6/QtGui/QKeyEvent` The Qt event. """ for action in self.actions.values(): @@ -208,7 +208,7 @@ def key_release_action(self, renderer: "Renderer", event: QKeyEvent): ---------- renderer : :class:`compas_viewer.components.renderer.Renderer` The renderer object. - event : :class:`PySide6.QtGui.QKeyEvent` + event : :PySide6:`PySide6/QtGui/QKeyEvent` The Qt event. """ for action in self.actions.values(): diff --git a/src/compas_viewer/controller/mouse.py b/src/compas_viewer/controller/mouse.py index 217126f0ee..39c10525d2 100644 --- a/src/compas_viewer/controller/mouse.py +++ b/src/compas_viewer/controller/mouse.py @@ -7,9 +7,9 @@ class Mouse: Attributes ---------- - pos : :class:`PySide6.QtCore.QPoint` + pos : :PySide6:`PySide6/QtCore/QPoint` The current position of the mouse on the screen. - last_pos : :class:`PySide6.QtCore.QPoint` + last_pos : :PySide6:`PySide6/QtCore/QPoint` The last recorded position of the mouse on the screen. """ diff --git a/src/compas_viewer/utilities/qt.py b/src/compas_viewer/utilities/qt.py index 525028b8c2..f4e76755f2 100644 --- a/src/compas_viewer/utilities/qt.py +++ b/src/compas_viewer/utilities/qt.py @@ -26,7 +26,8 @@ def key_mapper( Returns ------- - Literal[:QtCore:`PySide6.QtCore.Qt.Key`, :QtCore:`PySide6.QtCore.Qt.KeyboardModifier`, :QtCore:`PySide6.QtCore.Qt.MouseButton`] + Literal[:QtCore:`PySide6.QtCore.Qt.Key`, :QtCore:`PySide6.QtCore.Qt.KeyboardModifier`, + :QtCore:`PySide6.QtCore.Qt.MouseButton`] The mapped Qt key. Notes From 6f27b8543bd5df4b064c2cbb299f2fe3488c277f Mon Sep 17 00:00:00 2001 From: Zac Zhang Date: Thu, 11 Jan 2024 10:05:20 +0100 Subject: [PATCH 3/4] patch --- docs/installation.rst | 7 +++---- requirements.txt | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index 6c452f84e0..02c7c0c9cc 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -3,17 +3,16 @@ Installation ******************************************************************************** COMPAS Viewer can be easily installed on multiple platforms, using popular package managers such as conda or pip. -If you do not have COMPAS installed +If you don't have COMPAS installed =================================== Check out the COMPAS installation instructions at https://compas.dev/compas/latest/userguide/installation.html If you have COMPAS installed ============================ -Activate your COMPAS environment install COMPAS Viewer from `pip`. +Activate your COMPAS environment and install COMPAS Viewer from `pip`. .. code-block:: bash - pip install pyside freetype-py pyopengl PySide6 pip install compas_viewer Verify the installation @@ -29,6 +28,6 @@ Update with pip Update COMPAS Viewer to the latest version with pip. .. code-block:: bash - + pip install --upgrade compas_viewer diff --git a/requirements.txt b/requirements.txt index af76855b1a..fc534577f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -compas @ git+https://github.com/compas-dev/compas@main freetype-py pyopengl PySide6 From d2a3a634e2b5983bdf1e20a2547ee20e1f0481ba Mon Sep 17 00:00:00 2001 From: Zac Zhang Date: Thu, 11 Jan 2024 10:19:31 +0100 Subject: [PATCH 4/4] patch --- data/default_config/{render.json => renderer.json} | 0 src/compas_viewer/actions/action.py | 4 ++-- src/compas_viewer/scene/sceneobject.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename data/default_config/{render.json => renderer.json} (100%) diff --git a/data/default_config/render.json b/data/default_config/renderer.json similarity index 100% rename from data/default_config/render.json rename to data/default_config/renderer.json diff --git a/src/compas_viewer/actions/action.py b/src/compas_viewer/actions/action.py index 8274c6aa35..7c4d6182fd 100644 --- a/src/compas_viewer/actions/action.py +++ b/src/compas_viewer/actions/action.py @@ -65,11 +65,11 @@ def pressed_action(self): """ The behavior of the action when the key is pressed. """ - self.viewer.render.update() + self.viewer.renderer.update() @abstractmethod def released_action(self): """ The behavior of the action when the key is released. """ - self.viewer.render.update() + self.viewer.renderer.update() diff --git a/src/compas_viewer/scene/sceneobject.py b/src/compas_viewer/scene/sceneobject.py index b1557d150a..dfc759db91 100644 --- a/src/compas_viewer/scene/sceneobject.py +++ b/src/compas_viewer/scene/sceneobject.py @@ -450,7 +450,7 @@ def draw_instance(self, shader, wireframe: bool): if self._lines_buffer is not None and (self.show_lines or wireframe): shader.bind_attribute("position", self._lines_buffer["positions"]) shader.draw_lines( - width=self.lineswidth + self.viewer.render.selector.PIXEL_SELECTION_INCREMENTAL, + width=self.lineswidth + self.viewer.renderer.selector.PIXEL_SELECTION_INCREMENTAL, elements=self._lines_buffer["elements"], n=self._lines_buffer["n"], )