From 54a5b4572313802d8b0c0ea8ef5bc34ad409aad0 Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Wed, 26 Jul 2023 13:05:52 +0800 Subject: [PATCH 01/23] Fix dimensions for legacy lifts (#126) Signed-off-by: Luca Della Vedova Signed-off-by: Michael X. Grey Co-authored-by: Michael X. Grey --- rmf_site_format/src/legacy/lift.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/rmf_site_format/src/legacy/lift.rs b/rmf_site_format/src/legacy/lift.rs index d5d16b11..5022bd83 100644 --- a/rmf_site_format/src/legacy/lift.rs +++ b/rmf_site_format/src/legacy/lift.rs @@ -45,8 +45,14 @@ impl Lift { // TODO(MXG): Rewrite this with glam now that we've accepted it as a dependency let x = self.x as f32; let y = self.y as f32; - let d = self.depth as f32 / 2.0; - let w = self.width as f32 / 2.0; + // NOTE: Coordinate axes changed between the legacy format and the + // new format. Width used to be along the local x axis, and depth + // used to be along the local y axis, but now that is flipped to + // better align with the robotics convention of the local x axis + // being forward/backward while the local y axis is the lateral + // direction (side-to-side). + let d = self.width as f32 / 2.0; + let w = self.depth as f32 / 2.0; let theta = self.yaw as f32; let rotate = |x, y| { ( @@ -95,8 +101,14 @@ impl Lift { let dx = door.x as f32; let dy = door.y as f32; - let half_width = self.width as f32 / 2.0; - let half_depth = self.depth as f32 / 2.0; + // NOTE: Coordinate axes changed between the legacy format and the + // new format. Width used to be along the local x axis, and depth + // used to be along the local y axis, but now that is flipped to + // better align with the robotics convention of the local x axis + // being forward/backward while the local y axis is the lateral + // direction (side-to-side). + let half_width = self.depth as f32 / 2.0; + let half_depth = self.width as f32 / 2.0; let cabin_face = if dx.abs() < 1e-3 { // Very small x value means the door must be on the left or right face @@ -208,8 +220,14 @@ impl Lift { } } - let width = self.width as f32; - let depth = self.depth as f32; + // NOTE: Coordinate axes changed between the legacy format and the + // new format. Width used to be along the local x axis, and depth + // used to be along the local y axis, but now that is flipped to + // better align with the robotics convention of the local x axis + // being forward/backward while the local y axis is the lateral + // direction (side-to-side). + let width = self.depth as f32; + let depth = self.width as f32; let cabin = RectangularLiftCabin { width, depth, From d2fb61f8785e66021b56286fb64b6fda454f9ffe Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Wed, 26 Jul 2023 13:45:55 +0800 Subject: [PATCH 02/23] Hotfix for outline issue in wasm (#127) Signed-off-by: Luca Della Vedova --- rmf_site_editor/src/interaction/outline.rs | 23 ++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/rmf_site_editor/src/interaction/outline.rs b/rmf_site_editor/src/interaction/outline.rs index 1d1a699e..ce81ef70 100644 --- a/rmf_site_editor/src/interaction/outline.rs +++ b/rmf_site_editor/src/interaction/outline.rs @@ -81,17 +81,20 @@ impl OutlineVisualization { } } - // A strange issue is causing outlines to diverge at certain camera angles - // for objects that use the Flat depth. The issue doesn't seem to happen - // for objects with Real depth, so we are switching most objects to use the - // Real outline setting. However, I don't think this looks good for certain - // types of objects so we will keep the Flat setting for them and accept - // that certain camera angles can make their outline look strange. - // - // The relevant upstream issue is being tracked here: https://github.com/komadori/bevy_mod_outline/issues/14 + // Flat outlines look better but are subject to glitches in wasm, use a feature flag to use + // Real outline depth in wasm and flat in other platforms. + // Tracking issue here https://github.com/komadori/bevy_mod_outline/issues/19 + // TODO(luca) revisit once issue is solved pub fn depth(&self) -> SetOutlineDepth { - SetOutlineDepth::Flat { - model_origin: Vec3::ZERO, + #[cfg(target_arch = "wasm32")] + { + SetOutlineDepth::Real + } + #[cfg(not(target_arch = "wasm32"))] + { + SetOutlineDepth::Flat { + model_origin: Vec3::ZERO, + } } } From e45f497c4a4df3da64ea075a86fb8aefd848310f Mon Sep 17 00:00:00 2001 From: Luca Della Vedova Date: Mon, 14 Aug 2023 17:36:30 +0800 Subject: [PATCH 03/23] Drawing editor mode (#132) Signed-off-by: Luca Della Vedova Signed-off-by: Michael X. Grey Co-authored-by: Grey --- assets/textures/add.png | Bin 0 -> 1180 bytes assets/textures/alignment.png | Bin 0 -> 34039 bytes assets/textures/alignment.svg | 173 ++++++ assets/textures/attribution.md | 9 +- assets/textures/confirm.png | Bin 0 -> 1218 bytes assets/textures/empty.png | Bin 0 -> 2187 bytes assets/textures/exit.png | Bin 0 -> 6952 bytes assets/textures/reject.png | Bin 0 -> 1686 bytes assets/textures/search.png | Bin 0 -> 2876 bytes assets/textures/selected.png | Bin 0 -> 20954 bytes assets/textures/selected.svg | 91 +++ rmf_site_editor/Cargo.toml | 4 +- rmf_site_editor/src/interaction/anchor.rs | 1 - .../src/interaction/camera_controls.rs | 41 ++ .../src/interaction/category_visibility.rs | 85 +++ rmf_site_editor/src/interaction/highlight.rs | 86 +++ rmf_site_editor/src/interaction/lane.rs | 8 +- rmf_site_editor/src/interaction/mod.rs | 34 +- rmf_site_editor/src/interaction/outline.rs | 35 +- rmf_site_editor/src/interaction/popup.rs | 57 ++ .../src/interaction/select_anchor.rs | 106 +++- rmf_site_editor/src/keyboard.rs | 32 +- rmf_site_editor/src/lib.rs | 3 + rmf_site_editor/src/occupancy.rs | 12 +- rmf_site_editor/src/save.rs | 2 +- rmf_site_editor/src/site/anchor.rs | 7 +- rmf_site_editor/src/site/assets.rs | 19 +- rmf_site_editor/src/site/constraint.rs | 216 +++++++ rmf_site_editor/src/site/deletion.rs | 12 +- rmf_site_editor/src/site/drawing.rs | 356 +++++++++--- .../src/site/drawing_editor/alignment.rs | 128 ++++ .../src/site/drawing_editor/mod.rs | 265 +++++++++ rmf_site_editor/src/site/fiducial.rs | 273 +++++++++ rmf_site_editor/src/site/floor.rs | 193 +++--- rmf_site_editor/src/site/lane.rs | 10 +- rmf_site_editor/src/site/level.rs | 6 +- rmf_site_editor/src/site/lift.rs | 13 +- rmf_site_editor/src/site/light.rs | 10 +- rmf_site_editor/src/site/load.rs | 85 ++- rmf_site_editor/src/site/location.rs | 17 +- rmf_site_editor/src/site/measurement.rs | 78 ++- rmf_site_editor/src/site/mod.rs | 44 +- rmf_site_editor/src/site/model.rs | 8 +- rmf_site_editor/src/site/nav_graph.rs | 9 + rmf_site_editor/src/site/save.rs | 320 +++++++--- rmf_site_editor/src/site/site.rs | 12 +- .../src/site/site_visualizer/mod.rs | 104 ++++ rmf_site_editor/src/site/util.rs | 2 +- rmf_site_editor/src/site_asset_io.rs | 33 +- rmf_site_editor/src/widgets/create.rs | 200 ++++--- rmf_site_editor/src/widgets/icons.rs | 34 +- .../widgets/inspector/inspect_asset_source.rs | 59 +- .../src/widgets/inspector/inspect_fiducial.rs | 267 +++++++++ .../src/widgets/inspector/inspect_layer.rs | 168 +++--- .../src/widgets/inspector/inspect_lift.rs | 8 +- .../src/widgets/inspector/inspect_location.rs | 60 +- rmf_site_editor/src/widgets/inspector/mod.rs | 171 +++++- .../src/widgets/inspector/selection_widget.rs | 19 +- rmf_site_editor/src/widgets/menu_bar.rs | 150 +++++ rmf_site_editor/src/widgets/mod.rs | 381 ++++++++---- rmf_site_editor/src/widgets/move_layer.rs | 48 +- rmf_site_editor/src/widgets/view_layers.rs | 200 ++++++- rmf_site_editor/src/widgets/view_levels.rs | 49 +- .../src/widgets/view_nav_graphs.rs | 52 +- rmf_site_editor/src/workcell/load.rs | 17 +- rmf_site_editor/src/workspace.rs | 14 +- rmf_site_format/Cargo.toml | 4 - rmf_site_format/src/alignment.rs | 550 ++++++++++++++++++ rmf_site_format/src/category.rs | 6 + rmf_site_format/src/constraint.rs | 56 ++ rmf_site_format/src/drawing.rs | 38 +- rmf_site_format/src/fiducial.rs | 46 +- rmf_site_format/src/floor.rs | 8 + rmf_site_format/src/layer.rs | 268 +++++++++ rmf_site_format/src/legacy/building_map.rs | 346 +++++++++-- rmf_site_format/src/legacy/floor.rs | 6 +- rmf_site_format/src/legacy/level.rs | 57 +- rmf_site_format/src/legacy/mod.rs | 1 - rmf_site_format/src/legacy/nav_graph.rs | 7 +- rmf_site_format/src/legacy/optimization.rs | 415 ------------- rmf_site_format/src/level.rs | 30 +- rmf_site_format/src/lib.rs | 8 + rmf_site_format/src/misc.rs | 55 +- rmf_site_format/src/site.rs | 23 +- 84 files changed, 5408 insertions(+), 1412 deletions(-) create mode 100644 assets/textures/add.png create mode 100644 assets/textures/alignment.png create mode 100644 assets/textures/alignment.svg create mode 100644 assets/textures/confirm.png create mode 100644 assets/textures/empty.png create mode 100644 assets/textures/exit.png create mode 100644 assets/textures/reject.png create mode 100644 assets/textures/search.png create mode 100644 assets/textures/selected.png create mode 100644 assets/textures/selected.svg create mode 100644 rmf_site_editor/src/interaction/category_visibility.rs create mode 100644 rmf_site_editor/src/interaction/highlight.rs create mode 100644 rmf_site_editor/src/interaction/popup.rs create mode 100644 rmf_site_editor/src/site/constraint.rs create mode 100644 rmf_site_editor/src/site/drawing_editor/alignment.rs create mode 100644 rmf_site_editor/src/site/drawing_editor/mod.rs create mode 100644 rmf_site_editor/src/site/fiducial.rs create mode 100644 rmf_site_editor/src/site/site_visualizer/mod.rs create mode 100644 rmf_site_editor/src/widgets/inspector/inspect_fiducial.rs create mode 100644 rmf_site_editor/src/widgets/menu_bar.rs create mode 100644 rmf_site_format/src/alignment.rs create mode 100644 rmf_site_format/src/constraint.rs create mode 100644 rmf_site_format/src/layer.rs delete mode 100644 rmf_site_format/src/legacy/optimization.rs diff --git a/assets/textures/add.png b/assets/textures/add.png new file mode 100644 index 0000000000000000000000000000000000000000..0a586af5f98e9bbb4e798a007f5c1a1c8fcc67cf GIT binary patch literal 1180 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1SEZ8zRdwrY)RhkE)4%caKYZ?lNlIT0zF+E zLn`LHy?ZeKa+=JskJtNR)fF?7W^iy_WfLwDKecqK8Kd|S&cfHMeRroG{@3JtdD&mq z$=kGL9&Wg|OW9dE!#T@xLlJ|?jS15=KZF%Zzt^VZxURpmjIqd#g`QHim@6`PEIem{mGLg+qv+P)I@8PNcwp!og_nh_T zz5ML9p9`zMIXw^Bd+A2=)~6v&432MVe?M8BzWCm{byhD*^yUAS+$!RZnmR@3PRst+ zu{YnYUO%PE?3M2Kbz&Q25_hq8Tz>KI+1;G$>+;vRo%Fu>wd1m_gFvOH)w#0VNotO7 zPOo#H^Nz9T{(_SIhhNGiJThdEU~V9Z5Z!8S;V+h6ymvTbh5(hG%r z^`HKUZ#`vqaOR=!4Ztw)to=GQ=-3TKA^QN0?eZ zCQRW0@^hx}9JZJ+OHIt-|J)xsc4v$pkJ z>F4&F%wuqShVYzaYi}O&JeWC&QS4T_&tfH@+m{8-%%49^M#CceR*`+tc`m*y7c{@m zdGq}dhduv}3p=kA@|`|+<+x({vzq6N-uV1TB7_6tB4C9<`%zYw$gdbyF;I& zhw*>}14)F>cZQw*wJ+*&T)s10-Zr~(|H{mesBQ0-ilR6O-|JzspH~sxFzi+c=xjmgy{jTPD z(%PW=pv2tAaJ%Wo{@3^G1n&J#etog~I$vw}*;^BTeY|<>3;I*Xj-yM^~?0!>H!QnRjS%FUh_F2f-Wp`c*P^&w_480gD?3Pgg&ebxsLQ E0QTPd#Mu~ZU@qB5sJG8IB4A(RXm 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 v+TM0h(i_$M+RqhSCqDDZXh_ z>WGFyjA?u%pGqhpTOk;Gh@4!8N8x5!y_zzmjxMcX#dc;Q{~(&~VJVbrg_V@JKvgd` zzajY-fkN>vReTFc1H@O(XQy$W_e7D{CnPP+Y>~;1-yjx+)2E37A|owL zv7MQCS^Qu6Es_J8slceg$Df#kFliNonua2RQo= zQM~+#lbO33jyL>-yHSv`|3rj>9 zY&NCGo^&DOgXd8O{VyxKCRx0`PIQso0%2|%zXChBe3>NLLva7-+6hY-5fOpqhhTzl z-Foy$rswM7(l-CcJ+A3h2f_U!=Z69e#<6wX_iV`%ncvbf_S#jIt>b zFP0V?+%o&*nu)bsTo+MNC1OcQb#%1ltxkasz8eg=ug%btqjkyHe1PaEwVsMtoNoMR z5EK9DqL-SjI$S3DJ9l0Ly$)h=K$q_uKpshKp>gNHo1#YC+ID6W(!eev&S`O(D1#&= zoM(1+LA2b%d^|fGW;{yn!5$*1|HYcdtykCu-X7B7i4%cf>s(zIRXK8*^&2)YoSPWZ zg8Zl$kwPh}aP!6u*Mu>op*MOC4!xkLakGSP14V_;gmc8iYd~jug4T|(osS>;^`4zx z|DopYff(@V5TaF!j_+I4ke2Ke>M!)1MR(I7acxg;tdCaeNrh&hDkv(te2JkV%o1TT zbRX^Aw{KZQchrp=!7Ate93;H{-Sr5-)J1ch#rxC$~tw6hbrtSt|I6*9IUESRy^}D3b{x*r3=VWSF_6#L#j5TqM3{5piEJ==bmKF;!A z1Rz)V5&@`r30{%UE%|Q3XuS~d4fm60E{BJ2XVtn3UOuHRfAAV!KR=WSXegy)g_Z3w zVVc>~A*3-e>7!Vveud zP51HR#}A%@BZ_cdOi{rF7go^)QvdDvkcp8IC5UaJHx2&b=HknE@ZiFpw6SViZI`H| zq)4QuW>3L3Yth7D7Bs2a{nVSX%w?321_SfT znDF=S_b7uZ@ci*0jhTms@!sAL=<5OqHZXSRIO|@*9TeH=f&W`!Pj-w7? zo@`hiOY~0CU=W-v}SjSp&dB&>*APBP4Ar~8ZMs~cOdv?~a-3!>=;<%RziUSk{(+snhN-WVAz=`3L z-IbAL_IY)e*rK=K)kw3luyjdiKq=n5IT}i%KgbxAD7;KKM1Wz4*^XG(tkdB10?YzT z!?s>BWhiW1LO*zcL>R8F#u85Y!F2e_PUdC5`>R8_2m9;q!3of{8TXV;*bYK?F1c*) zKYU090Wu_HJ7`=WOmm$=N7UqKVI4zj>pfz}u5h!kv2B4Hv%T;vxr7@o5!qZ3&~dHAt4M z^fV-8B`AGMz1y(M;(FGD2b7g=Hx^}*^0Flx^%Bq#78geq(@^Ha#oUl-Zr2@+T14F= zpB<8{nt$>CyULz8k&t?KDE8X5<^T8-BF*#cb0ai4Q9aWa4Ga%>)|})ek3`r8@OA~o z4-EA6TR&EE^YVHWnVW#AKptMd^UXE5<|+C}x!T_!F)9C`_qvO-_U`XCo0xZ-#dlUIUmEfaZ-&P4~?7-deQbmV$^N9V@hN{GEFc@&y3H zB7qU2e+Obpv!^XV+j%6XmWvT=xJ6l+F}*Pq)(Au&$OO@?cNNkhoS<9Hp4lpFzzX&O zvLD*t;N)PaP%xwJrd#wikWvL-!=j28Fv$vZvJvhscqw|%E?EvJT#L+OmkRXPMVCjL z9DwYD2c-0AojfT6{Hz4U8UAKoSR585Mc8Nol2T1vT%=GF5CEQum1yE&vD*8$P%n|H z#QzS;^ydGAr5N4v-~2;rSd=3H(P3c1Ko~+yUNqhoh+>n%{G-iQv~HpquEetMHSuo4 zU$-}Bs&#E8tyQLcZJcZn!paV9N!(t*GGH{YH~s>2*5}sUd-jY2jRFFM__2MagfjWMx4CehqXY7@CZ{a5{m`4Sl)YPMAh_q%}Necl7Br=b|7Mc>y}?ua{uDmA`+! z7azNX(eVbH+6vgfr~;A7{};iqFtoxpfHX+;$4;4=vV%QAGd`f(aLCS%`rMzN7vN*q zlXm#epBCe=@bHSEwik6xP0La6czE6^#ni?uSAF~Tt&e@-hy5k(APfqIdr?7IOMyGi5Xk zJv}#(XI=sXuUl8~d$&~<{2So^2(gd^D;!ASCEx{D$~8&zS4uJa>6g&^(W9jO!@j6d zs=o@p?TWQCOuDxW&hs*#C2e*cAMhPK=I$!5;vX zY`5=l2I&8FK78CmfKAY5Qc0jVoSu1VC%oST3rWPH z9Yv632%mk7=?mT(5_aMUaR0=NgIBff~ENyxFQ;8Cg-k6-5 zyBa1*c#`q!0a(_8*9;rk!)jY)u39@+EmA!S?#B97RtdE}xHKSjJ{TS}Zt9ERr*n2{ z3}1Xg+*~Q4i*By|)Tx;nLXu*gmEPV0LpVP$sTv_S+ZO-Rp_y28~QUl~3ieu$GGiTy;^C*`}?vk-k;lz?r*$kGw zB^#IG#-z&qC98so8R9VUPyAzsfO#HWPFljhtt4=4W(eJ7t0!{a;3(IIp_gGt^J+$kEbhD6*3=7}_V(UMWxy>#(4!p+22`vYwT~lQrHIFy2@98#l_Imi{E29nwo(1OF+f5mF)rd zx}sKrqTKJh7~U<8i>z9)VnuVI?(QmuJ5)X2?#|306aQxf0r=jHLv+#YlP$RD^mx_j zsy`#E@NaHre9|E%E7sV%XZYlfbLUGW|ZV2RcB(|o9mnA@ppgZsE?A-S!*F4(V8RJO5uV%@gV@PY*3hOAeIbt0Jqx%*X z1(N(t?;2muND?0lxD!^#TGM0hx`9ABclw0oJpju!v^y%lD~fC zi4MNPZA^XKba|1KT_lWXzb@?j0i5amA}B59H1$o0lI|?-}9NsY!Ai;a*sD}TIBPDw?PY<>^JZY4dU~va-5+vUTUPs3esYu~kZUoMA3;d0Xac-o?oGN|eU23zQ1l}48rZW__1 z>2*hB%NDjswRy#%;u+^8Ps2n@waEE>Nw6<;s7$o3*>7k#oQaNa^0noL`9D9t?~*FQ z+>Gn|>{%$7I$$Sz&jMC7idlz?wjT%VC;Dct_teSh^Iz?krh<@$KwN|SP+J-I=CX~c z>9r7#U@7`ltNxTM%+Kt@JRiKYW5Q;=aS{MdQia1*)@Q%5Sx6rtHX&k;nJd>(j&aw@ z$LP#ry;FR&X6@P#T0Tz-Tz9d93$jduXfCzj(wt>Qo83F%`EkdGJcrsuIH4NQShfu+ zB@CUmS+ACq=qq?vEMy(t+P@30$!e=#i5cv^oQzQ~x1Jk`s3 z((!OIy5~G*I&9&`N?-94P1b>3J9qLGcSme1<^WUoMyA&IKZ8^%t$o_q4xe*umytOa zW?x@lr_YaQ01we-$(8rpLsWrki19L|gjF>)H4qHezrITW&(Hg*8kh59MMdW(xZuxo z-(_eR)vOkxv^0JNUh_?tvAqE}EO~kP>5rQj1?z2d!A!dIvhQkjSR76`^zBV7aXX?s zz)l;Q|AgYmks~!TaYp3Se^4=ikzM;RCUnZ8@IZ2K8eoh?oN$-reZ@ zZSw?t0+}BH@rWTX$hV}N!T+>>Bo~(CMH_uU{%-iZk$5092Uvwx{--SKRsz%29a2OJ?7el)HR>bYu=x*L8z$mG=E$l04yQLRDL2 zfT8SzV}LP8Iy`pu=oUx}BR~!8p#9&kJ`6Jy<_ZpD)`pIr9zH2kXFJ-XZ|I{Qw|Ij- zX~RV9b2|yuRI$GP{+Do^T;{O$q+G;ZI;WALh@A?&fnc*O99hJ4GYpodL2r~1BJx#b&XQeIAD%3@P~T;w-B$m4*^1lTUlmpKjTV%nf zhFE(B+zY<=+?!phNd%2v6fm4}lg0Q5GzN>zYj2nY6$IfugO3<+7|Kz5jC)>ju_`1~ z2&sUGN?qk;mJ=PD;6`NHBq>?g*y+kSf2L5{N$KMAcsM{46IU6ry8ZrPf+Am5TU)zD zP#{x&jYjGoSnLV)&CN}ipoz7MJ z(|=~R{sdZujcqJ4HHem6qNZ#;NsV;-`09{7oOD@6T5uqMK!JvJyu-{7tY7auJZe+z z@h-*dGv&|Cr40TxxDvm=p&>IU?7Rp%TS%`=h*0P|{Ta#=YnP1cP>C^0*jWbZBj#SV zqsOWM+$Es^fF|oZ z2X7Sm)CH_H_b-O)JESZ<3{yP*@dD)gB`wVM5^(eK;O%DhHm4=tApj--NLJ12D@Lf6 zJfWali6;~pgluzvTBZW)shmXnk7uc;QJv6q{gOu;M_1ndcB zT4G8y@oD%Wat>ZF&@Vn44iaN_pk#gny8B`Lm@RRQiX?R|z)$yG^1#z~>5=u$PELTy zaPL>5glb}T?|W}=5Lqo^F&`=%!|Z}cIV}uX-63L$>X^fGelaMI8ruv1GVy_6KOGk7Eb)LSM+~@9iEH5V)K=KkQQLXBXB0Ef0@5V06fP;yeu*y%x6jwAEzHg%It81yI~zk&BCio# zAatPushU!#6!K1=D2l8N(s4T5^FVON#_!p7IuD+=uI7^YEqLqyGev9{svD%8 zZJu{2Yc~J$<+ZZIW&HEZ@RNALaT}eKREyvnru9R07#=r(N3Y}epFfHAynXiQs(}iI zN`X*wTsl;}Vd*8}CkFPd(s++UPuq4H6DF|Xp-of=Cwyat0^O_K1-d ztlfKTx1F6GVC^YOg;nSR-nYSRRdNmn(T)=DsnK=U?xenf*@-yS3Q{ZjPu`i)4Vulg zctZc5CQ>NC(jR74FnvPkEs=QsN5q8p=RjZY-PmglP)|@4H5lmx*E#Fr1PJdx&9xS@rZkj*#H-J z269-JF1dxy%7W23Il!^d2}t!?ZGN(QpG)zS{kL~{B`GgUY5n`Gp5ErIyqka2!R667vp}C%)?N#fBftYsq*+zx}37z0`a3^+yIj(3s z(-Drvs&#*TmCT})ImzRkj>Fxr!`)AJ?Y=omB?2}8I_KbLg?7)BA9&&fc=k?x2loGU z>55k{_~2HrflSZgm$bws3Tde{jDxc9Jq9L5=4XE46p(i}HZQ~6G#wq?LEbRtq^5=j z|K22DKH_jD?o-R+pN&!!=Mpe1LadLU@*J3&G7so5 z0-uaadm&BxysH~(8wLUV3HV0G3;pKqm7caf%m#bHr9A>aArSy!23(YO%>pK`LO!}t zV~=s&tFf`Rc6P)yRQ>K0iuluR=Bx9Iw z2Uh5&@P448D<5jgywfY!B)-SOXpKYrEjg{ptL}*>V>rFL+_g)bgq(k#y;2|+bxU+i z)Q#mWVL%qBrJGFMK6bp)r&}PSto)PPL@vJO z=!uophX;bGc5YDRkzy=FrpEgrlOE2`xQ{nyvGIneUh2rM@HlgZ33z0n4SJO#PBa)+ zyK}z$l0D4E1k$hKS7l78t1_yf;DYVs;X|CpKr+*@W5+aggyYcR{x1Rdm1WB;HQJamHmbR>m_w7n<`O?ADDY?1PDWR09OXDgE z4|VT4pf_-RZV9CCUw2gV#EDEi3JWYu=GW@l+E(HqlE&}MV;@{DsAPP3=F%}!cE4)` zmCag~lTi=d2g8(61>)TMyKK@+WT>;iJ+~h`2$}e_Oqbil{Y4uol<+NjnnbuChAWJ? zbVpFc!4MHoNwRSNP8iOty+^cWk0n4g?rg0C^N!bE(6kRC>UrC=gY2K@-D<;NB;%(FA7V`~l+D|Mchx!+F4} zQ(3~LfYw3RZO*SPnXHf^uAcWE)X}#$sdJq$9^ojN)M|qbxHb*_UPM?}7?a(lYAAJK z#LkR%q6|rb93!&oGR+4xCc{8}FTb4>TtY-VoGCeO{q^h6yUa2qo*UXa+w42XL3?1C zq_8k1s8(*e&OmTg$usIZQR3=1XF?7AOstNdfXSam^6vT{tH0Jd}XNMpLJrm;iQjniRTrUhLD=WcmsI6_!nST`whz z7vAJK*b?uK1WxEonIoZnx^gQnCQ~@Jqv2t&nS903-hz>zk|t>1ZJ2xMX}*V$Azo1^ z6_J(x7;~tLcK?RuHDsj$dwBo;{nF2QOus2Fh~GvV4)0Dbyk!v_^u*)|L1pGO!_*-y zPlkt7cQJKYVrp$&ynxx3d#8_# z_xRbfun5hblyDAqHa7TZT3?(oa2IIiJltnA}o@3=?(K?P<)lBat?5Qh55D3hqbGi?1NYbuk`>6be?=Z$+LW_0!R*4 zTw>bRV?htAg(Zhl379uNF_D56^HlGp*%tb#6%2;Vu#&>VH*vxb=CI(1yBov|5(7l^ zpjBTe>-_qMUL^*d@9jsASm0ocIk3OP9uC6+)x4BH+A1GUshm7x_QL4mcr|1cB{ z0wjLE{oDCNXvC>;g4D}HxwkQF4|#3-v11RB&ywfVk*_e4(!(S-ZHRMN5TnCv-;r5D zaQ`r5kcl`@pewFamp9r^Yf7pMVjO2Vx>VBcJbY;O$SwqzISD3b#X$Y9l7-?vT~=!H z1-OR5*ocR|I*>}43Li>ica&p zsglA-J%^(I-5f2IMChw!l*=-3*3Bcy8Ev*~o03iVH2MlSpKv}8CGxw1b1PYw$15l^ zCovlp9HFW7it6q@IIJ-5KkQXxXu|gV`Exw+8PSGGr4bu&>tMrjKtaZ`4L1upLn?QL%wT5&z?5S+_{Nz1?HsFZWGKxw}j6mJ$ zMtw>a4t#>5NLWp@>4qk;wRSXynwr#*aN(=&;+E>Mqzx&j(xjMoF&-%oSwlbuj$xC+ zz!7|ackEO9GPRr+*owGN!HetvQt>3JeJmPb8pv4mm%*_Ut(!-qs@Qv1;atCk}e zF)LDIq(zBN3bh8sm(0tswIJz+baM$OzIa^z$-Y%oks#DtKlq87{uWyEJ)BaosNO;O z;}4?=<}(A^`SbJ(7pt2GcrTbhR>aR?7!GB9gtA=?3}H1a#y8=c>DNlCkAHw;KrCa|smv`oDBQ@LsJ56baP581TNfRG@-2go*eAW_e{!H$ zhWx1`i5e>zm{lGvrM`~)U10i1v?eAdu1E>>T04S)`Xp)V$(OYJB)#I4BZLs~NSjG2 zJ49))4%OFv{@IY5C(F9XzAQNO~k;G^z{H86Hio`telV4B1Wj;&3@76nZMLnc>}F83qC~2n4a&e|_Q1yA z+`ir1Qp%`*ch9Tb#HiDWSDv;S8U*^i%AqhaBo_9@V_LqxYOGo>3(t;`;KSwwvVw{W zoBE{B;a((P)Jw*h%;bY0M*{)6iLDRGald6qDV64SQBcsZN`h+y>cf;_0JaD@6u{PM z+HL=}b6#Ge8S(>1GL_6EZHjpwK1@b`f^zEpJ)%!lQl0fGCV^LkRZw9!0eQv8Zy*r| z-y$Lo!w{3x%_R{i_{txDWv8c?0f$8=B&^gjazAGsC*BgEj`B7&!Oasu zALJGx&%cuLoqFr1W|`@*G)P7in@WZdK8oz1y}BQ?*`O|w(Kz_7Fkh_WF4=~GfQm0J zCE?(#4!E;U3!`hFj4zqu#wB454T;#nD&t8LtnvQRN^VzplseK|c}zr9fLAVw=)s3o z2~=%%KA4Y%fjLm}gq6j)*!bG5QGA$z)VOwpI7Ry1g|=-&aZ8Ru-WJSW8kR#M0IEXk zwFW0={lcIXG084LKFFt`5t^*^W`5#0`pvG?`B@5J(6%!}<>)eiLA{(HgCk+Yx)i#; zzeVzBAPu_!{k9gS%TNk{_2x@&M_q-bNz2GP@H{4}$S2tFi32#z2yPo3B;%hfZU$l& zk(6{F_k$M;u@+JB%soVO1)igboYo`Bj>yNs8LDzSx9f3B;rx~!PeCJ!9Exb?qbZ>+ z$IDQH(FN0SD>#>9Gozy4@(`eBWEZF>v+sYKWn`(PX4zeI$!~$t{z{x*NK~1yh#ro` z+`+6Ojc;WJ2h+i+`4xM(*hnk6`ffN!qLK$a+HIVrkSsi<1!Efgh0$RFU zq;E|w#p=!lZMK1dfvpd9&nukzt`Fz}$e@_82M$*=caaiuT-ax)KfGS&=B7Q!z#haL z^i6no9K6we!ni=21BRv{bK#iOiz0eAlwvEt)ujN4Pq6U=gKLGchu~I8YZYHZj{ZR| zLklG~JAn=gNu3xiH*SP4KlAooP5yA2;JzIQ95l!OP7p?PdVBUH=Cmk-YOaf(O)e-P zhezNfDge`@$#=Clu@V`Vm=tj^BMZjKnGE+P8@#5{9N!EhCYV41x&b?)q6Cy!Xg2%5 z1a9z#17djM2#(&w=PMzK_+K}cES6fsw>h+UR=zX;Ch zg>Y0Y?i@}Flp|ZW3Rh^HNL?sW7`=qAYUFLwfqz%ix#~gLWOWn>FFNo?_zs!yNEWvp z)2CIr33P}sftvt)Q(%ScVH6fn5oS@8kZr$a7B z4b2oT&I{!`F3;TD8{6*?;t%`ZjTXx-L-7+^x>MDTSzb>?IIYX zmYl3is*~#OA`}Y;V7=uApf!Yb6YC?M!zGSs1v_jDOoevRAuGKnP1fms z#F$qRIvDjmdsZQVV?Iq&XW9^kIAmgQeh4*KgqV3lUNJH-*NFhv15WF(?a&21VrQ<6 zgYj!+9O;(0SmsS6H*L}eWfj4vB7r7BkzF8} zLeIbeyau96N{NLM#~CI_TPxyJ7JRu2=lFcevGxBI{={`H9}ho&5PE+c_2Dy6-#JYF_r9F zvSh@hjfhDpCfg9nG7VFCYD`Iz$vT!IOfhYivb6}6>V7}J`zAckdmQh7uYcw^My~Gr zT7JLp_dGw}^BVg~Gl0d(bwlYyf<}@Com)|2!_llqXT70E;a7H3E?rrirFhcw zJblV}F&4>F1NyuT<3dXXN2JNSx0K|EvdC)^z2Y_GeW$-t)>L3E*7Y@WuyhStH2nY@pnSH# z#5pR}09exw2$v~x2Mde##*@h#!nE#ifniX59%#$TT9hlQ4o_0ZHNb=a zPrWYwvL>IM&Y$_N+j)6Ph@WJ0uxLiHSVt{Ho)8=4>?BRT9j{ z-1mJ|sZcbyHJD50D!P=^ZJjDpda55asA+$x=UBVvg;>*yu$3{`m`vX>z&-s&*XRMC zSO6!KgWL$c+6sbUa4iSLV!tu{ZPw|4)O z6nS-3|J&JPNT$8l9n)<}Y~Aa? zEZ6Axps}-i%G`mAPp!RkQw(OXym$9?d0#slpgkdB4w#zAR@mCv2+2x?x>dJ=XGkb5 z>~5$ZzJYNysGF_}-e$~DyPn>2M63c* z{w0iC4mXv?BQWml*}}C|r6@rcOE;|v6yKAUA+xC)XwjLd3vAM?8U%DugriTgI2?`q zok`A-2W|#=J~|>@Lm^HReBsPD+8sOhDB%nHqvMS#DbArz4vUc7$MPG0@+b4~K{_)*!hyJmYVwT;dr z14_?I4>{U7>eL-_d{wETzN~{zn~h%CQ6?FxU0e~x9zOhzYDTu-+Rj$YOC{!uf!3=d z%)4~7OtF(K$Iaogx`uFzrrVy!o5m&(!gqCE=^GrzKK!H|>5 zB)Yt9akDXgMLSHbLdigu2uuGOX~p07 zs;}}ZafHimHNU)-{rtHDF>&vf+_i(A2$-#oX<)rC-IN(20nyxd*P(NX9(nu62J}jlK~HCid?nO}Poqy`kWs7G z;^~~RF|@?Cj*d~@ny2gXsV@!Aco)vBB1x&a9+ois>7-zGBtZt&)(_G zcu&(l#Mdo{V)DxIY|8iaCW3Rp&*fv9^GMSGdHpGNee2xjWa^2q2pik?1nFK}nt1Ng zuO%T8ZEYg;n)+G1PrDU*V_(yQ2M^B0#Kg=Hwy}Et-Min_CwX>uQeMPpQ!cV(X*wP6 zDtA%>!#R2lu}-CDi<$-nkp8tTB5pL-O@?`I_wjEfgn+V6xtE0|%M@+1$VmLbOo{tY zB;3`(l0+g>=dNtzbrj1oIDa`MD>7!exU7BEEFH8+^)?Q1PM>JQ4gJ7;XJYn=ye>gC z3EIg%Qb&suM_nMIRWfSxCc0+$C6|x1t?k6US0!=?VU&0UN=Es}bdiAN|D?aC7$F-> z#vZ>?NRe|ZGe5j8@$oO~Assem%$PQm%(*#fcQmnkP`w5TR16)S2b!=}G$4-lf+d1!Fa}=79OE z9;kgiX4*gRyLIiFr5;e#N{q}2Gak@J2;HN(gNKt4S9F*%nYv!mYfD(;vTM6c1fcBU zSE5WEjrj4cs9SV&#*;GT5!kc_8%2j&J?G`$htE3f+_7Wu4}zhwQDb1PAzz4zi{mnz z%S5({>@Hp%`=RH<!pc`0^3Be z0o=B;&pk&8yfwngR`K4wdwtDAUiaaRH~a>_SE=`HYQ~jg`}njwryRpq&IBP>a`cos zPTo6IS-6=T1{r@FS{9avweJA;=PzH{;LycZ`y9NEs zZG;^DPu6jZx4-Pz@cMLSW^?@Q{#GLQ%p9vb-EM(jPa$xgJ^x`e6mr>l>4)>eOQd10 znCRJ{X~7T1rKURjO7!;`@;NUG!W!tLYJO)$Hizc7o>DDdo+Bzj+9o^u_4D}UX>VD~ z&KadBAYfa^JdyHv*7S)QrQ?Ee#pjq>LTK_x0=1eO5~b$LZaTNq0-e$(rpysL0C@(D z)iz)i@CAiC%1f)F=67e-1xNE|!&dyw#+y>V59qIoNp;KYbi5=Jj}vg(@;9 zO76rq57##c_2^%{ADz;@UNFl~nH5>vu5EOmMK^f7V+8#*l|azHv<~EWVycTwBC*GZ zhllZC^`Ch%i#)>lW2B95yxv6aG5$FY_xz7S$$`>c95C7ww3Bs98s^9}_ZB(W~= za;M*SoZmfJ(vh?!aUu{favgn*&~|T)dDEUjB&J18%p-~(rmtCgB0as~&tDTW*VjV4 z>DJ$Ny{&!d1GC@9EI3y^(5_b5F09@S4B7bMymYke!ESnA)P*$>trE1kE|TtfS;u+< zRV}WhNbsya<+DMJ5j3vq6c|{6>G;D1*-x4BpwTsl4ed86fcWSIX9{1uKA->A(FXp7 zOZfX^kjV%7=36Yq`$mWdH+{Cp%~3N zGezF^)oAIVcQ8DPmt@0BKfY2*g&zdeMU6&HzHmQVPGFo4EcuS zOP6p>X42Vtc<4ZeIL?~YA6Mo|n%w-1LgsXf5u+Qz$mQJu$aKtL&;0e9c$fV~ov9NG z8OdQqh7>}km3cbR%LSWXRxQ$!{0OiWsHvzHYlR3xo(Br{{u`GJ`YWA;Z}{XuD9aoX zlM~4bp(5uR@1&F(ONanYPP>F7gjFe0g9Mt4T5xN-W}Ic|+w~kTSO#!}e1t*pBsN_x zvj&Br`95<~r<2;WwgRgB0-s^ij`Fpm0|d|FahB6Z`iF^FWjjV^QnPdPo8l6*IOiFw z7cUqo>9$KznQ0KH5z2dx)|xwCy)Wt&Z4wos!G@V$XAOezGN4f!89y z_y0+b5wxF92R;ryR7i_`$HORC9m?t}r`r=agT3%3th4G5fW?0b`P4h^HK?FbRD&6UBz5HK?u;aWTb6m+?Fr)1d&24((;0S-Jk73e`2ojWzl(EVUeN7 ztR(kOTueD2!_9{MAuD(syf!KuhcA*&Lu{8z$oj(8OIxK(c?#!%WL>ObB*|k9D_)hB zH1DdWkRXM^9N(YZvK{mPet+S6S>qYni@s1of(}|IusOz=WaL-+_RE(N9Gu_|Wx&%y5_--HVQCmz}bo*E@wIl>p+BAq<+^jrP=q*MA6hOTZXXART(1Qi$S>t zZZ&CfS*Rc;5)%IS;XR~TIxZ*iZ(&4LtjZW1mZYGe(3>295ecrJgvR*(Vw5CvgD6PI z1z7Rnowqp7qMR*dp}}346C^(8qqhMFhaa#3YgUZLrrF1G$A)r2eN(DuFLJyhOVF*$zKT|NL=Dr1eEa^DH6q(#1S>XAUn)_ zmazKV+}z-+SdN7b0;DP&c#@sY6pFC$+^BLzM8a0N7SU8_Nu z5expk*Rr^6mQ;HlyI}t-GWELR8df{pbSORSr$yCpeOrN%h_VwANM;bX|C!6htt5XL zMveBCDef5Kc<|!wPXn%J*ma+c$-~DM#T0LEqp{O7*Bq;)-FyAKf^=WJaTu{G`ij7u%|JsuweZa*AemXscgYy2c;T5ck;i zC#ARDyMnL-6g{1GtoLW9H{+46hilN4N;x?L9f7~?{*|ojsG{e9lXUaPQb&_urcv8* zkAf6YsJE5%xDLZ7aGT{Zt$$%jD&36wwz#VN+X^o#DuM@GXC_o&eqOt+my>NE%uN=- zQ69!YW*!gFzF7Tukg>FOhAW5lb;l8F0cB;5Sl&-0p%E%75{EeD#2)Sg8PoMnUB`P1 zGT+1*uMptECr@EiLxKS?1Fzy6g756?oa|dMU96y(BPa}@isO*?{~_9*|LKi9icdN* zW^l6v;h&AEZTh>=Qzh@e9LW&}0UB@LZRMFni~qt2C^t0$lu z`JzX)3y30>ibb!*9d_uX-CJ|~tlbtsE|t#9Rez3((%@cV#`qA67jL%^l-QSe=3bX# zrN2m|aFhrWV@WD6x3PvA*0 z)8+vM3~M>EH5 z(r8{hxJ$?k`5O4oQ)5kSvEPdD%5n-WNWgz z)vK6+7H@MsJwT2cR{U$plINSMvoRRC)LxsE!?M4iT>Lwj368It7D@6EahNi$3N%0h7#yYP?U;oCSn3tx_%SI%F0ar8a$@|R?r>7T;@VHW#FL4-P6+c?e+-Ql-qs6eM6jY8j)MEy$ zYr+s1bRzlz;ad9R2isCS+uj^EinsX zD53t6+E|@iGU&_PoX=4H{n=4&*4fDlQLjIm((pi-(sF-l6z|o{Y{*ZXBgT)Z__#lx z-?t3JLSPiEFH;*;#FfXCg(_-);iHcF_FvY34(009M6?g0xZx7>R9}Ol6MbD#dM$T_ z?u%PktDCPs$^PtlHJF%;4f|Xj&{U84eRD`hAO+p6;o;(yoj{ZuWTbS54%U#;^XGdp z(*iK!f1)T5W!W<-+OXnqpyk+u^6sPsO}~i=Up{WKR<9sqS34$9NSP-2QSj1er1cLS z6lk{u;aW$Eez>Ldjpb!ABZXbsn=3#Fcc$kEBIJ=vhMSp{(#Ln8Awirl7@TH7m39Qw zR}6vBPuN}76Lh$(x|N(><&}K50-IN7j*|4I(X8WwL>5V#-*;|)gV^?vE!22zXl*=g zisy%d`$8R@bl{q*Q&0%-6XRW+#>!7dpRv9pisq%AL^X^25Y)}8&STuLFWyq6o48t+S^MOCk0$!Zu2 zZY>#Oq3Jkn4o92*6)?9x_dL)=5A95vh3SM{9j%% zu|H|hjXRkecgmSy&uYE6tK8i2tAXxtkV9dz?N_`{o3n`^XJ@aU*Fn3tey^?n zOG9h&-;JtmI$&G;xB~TJo_TqFgaEB3Z$e$Hx(xi5nUkpHoP`S4mKl!XYCn;TmK&8l z{YxNsom#YUTh2(7k9+#DV=&YXk+)_Kp48QJl7j;fR#-Erd{|%h*B8&9Pn$XO()}b| zYorpcA2kitr%Wf-)M(P+^EdFigHI1X{rZ+Voh%9{dTGv(fQ&RYoD2z3!apmXx2~On zLTjf9w$@IZcB`2A9yjVbfmnQO3H9|<6}hQvtwb3h+rnC5o{?CwHNw#8<4}Ok*lX1` zahXQ4@+J5e;2b}A#q_HtO;)Mbx_*VYlK;ySZ5tpyb->Z> z{m{ls8O$V9n}S+>KEalJ0UNY11VsQ=8aj>1v_|^-hBJe0vt~`IkGuIEdo4!3u#eeE z#ft`T#>V*?>hBW^`|t`l8eRm7740;7lx&dVBYMBb%$r`oR-(X9Nd|v4dVmqLX+CQO z$jB%Uhxl>gCsv3Y)52GoYbvb%SuUb<#XA&wn6`gfxXO0;I=-yK9`qKxOi_0)__r4V z44{z+K^)#44edw5B}*!f#~$33IL`Jk8*bR9kFpQnO=4GF*#8+|xhWid{e(}Xy;JwX{MjB|0wcvcH5@6HPwB)HYYyi## zE2iJ)Lwf~|QPCJ{E`ID=1TrQCM5POlN4suOd%us7(NtIOgCl%Af_7>;o&d&-J9J#m z?2kxjD+J$`MVh#;5b-m6`k5P}rD21}F6d)n64EublVWh$*P-A#(bGtxlpRi3|y zh>VPkg%J5myu)boyLa!d2REd1A(6V4k9k?S6%YFKWE*Y$IF+G+&5eu6Kz2=CS$3&Z zyin?DgE_*m0b_E@>cwk(9`n{u7o!(1Iyo+aXNx;TRJ2w#KCs9a+O>P<&Yj(Kbz`gk z2z-iVae$$agBTsD=Xs~nD`DAH+t1Wj-5_qUUCi4o@CKUnTCiY24MQZF3vcYx(&a83 z?Ol*kL7RUExmH1eYJM%{xV;Z)HNMCcJ&;f`?>&07;g`dQOBxAFF-0`=`L0ST(O0#R a>b@w^?BX@6@&^U}Ot70`` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/textures/attribution.md b/assets/textures/attribution.md index 11eef4fd..3a6d66e2 100644 --- a/assets/textures/attribution.md +++ b/assets/textures/attribution.md @@ -1,4 +1,11 @@ * [`select.png`](https://thenounproject.com/icon/select-3324735/) * [`edit.png`](https://thenounproject.com/icon/edit-2162449/) +* [`exit.png`](https://thenounproject.com/icon/exit-1826632/) +* [`confirm.png`](https://thenounproject.com/icon/confirm-2261637/) +* [`reject.png`](https://thenounproject.com/icon/x-2289933/) +* [`empty.png`](https://thenounproject.com/icon/empty-194055/) +* [`add.png`](https://thenounproject.com/icon/plus-1809810/) +* [`search.png`](https://thenounproject.com/icon/search-3743008/) * `trash.png`: @mxgrey - +* `selected.png`: @mxgrey +* `alignment.png`: @mxgrey diff --git a/assets/textures/confirm.png b/assets/textures/confirm.png new file mode 100644 index 0000000000000000000000000000000000000000..5e7ae0e7aeff4385ecd7b2825f45fed4fa37f62c GIT binary patch literal 1218 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1SEZ8zRdwrY)RhkE)4%caKYZ?lNlIT$~|2i zLn`LHo#USo<0^A}|L1EGt2#uMW@@1D6LW4n)Re>_W2+!^9>(A{j+rI4m z+B+fV6N4U3o_|+*^WM+i3>)%STW;H3di-o+f5sQlrLX6_yb-={+c!4(@AuQ}?%uv- zB=uoIRMWrIt+fo?;&=bey!SqwSuUKh!S0*4lX*bH);H5xaxZ*gczsKs^ZJ5|jAj}8 zRRWryv02=eJ5YD>kn8s&H}5UYw)0=SkkN1Z+wA*1Y5P;&>6gE-e*MvBmPA6vZ`JvK zpM9Pj{FrIZ%aBd{53Wtyzd19iLGjw(t2R6DR#?d{2xQb+XQSHRH(R{?$CPVR7_NrP zF$gC=J2Efq^mFb7l8kIs`|tO68Wz8rcx^>~;!pODn|7P{1$NdxkyWVseZu0vmj3cN z3*RbVXSkgEdsY8;8zB2M1LsZmI>t+z`m2^HP1D`?-Qx%m!cG&1vx=--uoa&l>g{KDfwb*~Ynw2Ix{_E$)s zH)wmm0Ekn+Z2Pvqle&0~Ht@e^G|Stc@`A1MM*Dq+`k13no-^Ojx7?L+U%KF2!m0MZ zCku^_ZsXt2$an5$ydMAO1InM7O+3E*t+TJ0cj#vE;pm$Q&1c>m&TlxYJXNkPrEc!) zgIoB20|TqVZ*u&+Ve4Ik?cS|(DFTW<->bmB z$1>ahU%*%4YnRJK-@nt!lRx-W&Th_jdHt{{^4E9OEB`ZpTw|IcnRB}(etp8uPxD;2 zd=tztzrvVbo84dkzW8`K8 zZ;pAZd@lZ6=>d1{Z_SmvQvxOSY*<{8o<4DD?GecZPYxN0{VyxOpY)FB=jnqbk9aQ# m7}X{&Z>DNS1?BU9j89KET}=pDZVfDy7(8A5T-G@yGywnrSupkh literal 0 HcmV?d00001 diff --git a/assets/textures/empty.png b/assets/textures/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..5c20903e1c2d3e57fb937c7ac2d4e45ae390e671 GIT binary patch literal 2187 zcmbVOc{tST7yr)O?BfLyWP^ zSW+Zgvi(Hnj=c~=4a227{r&szKIb{-JkNRF=e(bD&U?;zlWncdgasu90RRv-zieX9 z)p5U=AIz1OF6<(%;`O{@W&-^DMWyu0YyjXlHaEF&HL_^ExZmdZ4T;X_0JZVb2lg2M zi;cl6XsZR07ijY{kMdKp)E}#e!&Uj2WaDmy+g|tZj|0yLn?FE66Z|b!h_VRYMdnBU z8!rkTuFUXgyPQ4uhu@GvJ9FqG_fOEh2+_~i(+69X#hqT-uZ_U=J?e;(;zJ);|6IW-UNp4@kdoh zswv0GII(vE{QYfd@@o$x^YiohdE;AL(jD8Inkpi1D#uy1uSr1?ujHwpb|cI!k7XrN zm#2DfQPkDd5v~e?yBU3beKAv1jH;KH*R885;6onxK1A?;d|H*Oe4rd@w?&sn2< z^h--i%i`ih?Wrgqa79EvOA<|q!+}s#FJ&B>-%;*vp>$b3SWgtky zmFADdRw%ztI*~#IKQLAmn-{K4T07TzVsr1uYHO?BD_U4UP>>4-qa*F6H05_!SvJSw zUU<0Z&#&7T?5;*cL}(TIe195yDFi&n+HDD2erk2#fj}U>F*?Wut{YJ#3gumoF{$|I zeRe8Hi;Fx|Ctb!!ogsXg4LjhMkd{VC;$Q0`R8&@1RwQ6B+&(*4Jx`w&tyOr_**R)= zlS#TkwXm>Aw_wAHe;tQfXEHX9CUv*9wRsXpPzSp#FVxC5I5~VsKMl*?#`vh7`651HM39M;eLgV?C3sD(*WNPZlLgPW~X zYx{h7co5BD@$~3iw}qa_=v|z=%$pC8C;JEA)_e6fe!*dO5AJhvo`4i&8S<5fhxa*M z31*THyJR;AzP`Q-*Q|iFxTPgutROcDKC|0M`5v7Avn9GV7ouZ%fIa9~U3>e`^!{P$)Bl&@aGquxx2XMdI{s zsE(>q#hAzvlj-p-H&4SYHw@zKuf{FnZ9lR8_wP;8w>QzqcAL@0L0_+6OS`e14TcXY z{RoLC4UfM)IyN$LK{_)s{5hRo+}6La0B2=omi_qjVR6w1>*3&V{5ncEP*PG#swF{4 zNXXj^oi+h>a&l@;aCCG$Qs!N&%;Ln%ytW}2ibyA`q73Jojl#40-aNZ068{hGGl``3 zt^FF=Rq>XXuCvgK+FD=A6qb5Lm^kLFh0Uz4MpW@B94EDv25I#pba7kd<@_W5-%bHryxV(K^Faa?N^EKNANU+ASDKT+3yF8hOVfj zPk^n9bh;3ny&pC2Vsi%DyWIbFxn>#~$io!atY+@d6QdsIzT z2Iv)AHwfAk>nWao9MdS)sn5sZZ2K|kW0-DQYwO`~E%~uMe}e zw?~hnBD{V$jeJ{M3l;xRFt}uSO5v~DZ~$VqJ;a-lmR6_ba8G!9Wkp&0<>YG4@oWeH zij9r^Gl=#{o0Uj?rn}`4XV|6&YvZA6n>vYQAjS4s{QQ!!82HN}?`>bMo z=x~@|gd;bqsi~!)tPn`BXT3y7N_l25}Rb;1z|0A><2*iElG@EyGQ=dPtudfeI zPM&~5;i3Z1KcRWcfir>mH`TAfMdebBG&S$B=HA9+;V;c+E7?2^76G|~;UrlyiS)e+D&)5k8<={&b-=2<54^{uU~O-)S{N=~1*-X<3vur60x&nVHmOCsKl~R6*B8_P literal 0 HcmV?d00001 diff --git a/assets/textures/exit.png b/assets/textures/exit.png new file mode 100644 index 0000000000000000000000000000000000000000..bc6c6be1df3b32441fc3561ddc2bb0412277ecee GIT binary patch literal 6952 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 lAY^U?5 + + + + + + + + + + + + + + + + diff --git a/rmf_site_editor/Cargo.toml b/rmf_site_editor/Cargo.toml index cc7f4ce2..f1f2221b 100644 --- a/rmf_site_editor/Cargo.toml +++ b/rmf_site_editor/Cargo.toml @@ -43,8 +43,8 @@ tracing = "0.1.37" tracing-subscriber = "0.3.1" rfd = "0.11" urdf-rs = "0.7" -# sdformat_rs = { path = "../../sdf_rust_experimental/sdformat_rs"} -sdformat_rs = { git = "https://github.com/open-rmf/sdf_rust_experimental", rev = "f86344f"} +sdformat_rs = { git = "https://github.com/open-rmf/sdf_rust_experimental", rev = "a5daef0"} +pathdiff = "*" # only enable the 'dynamic' feature if we're not building for web or windows [target.'cfg(all(not(target_arch = "wasm32"), not(target_os = "windows")))'.dependencies] diff --git a/rmf_site_editor/src/interaction/anchor.rs b/rmf_site_editor/src/interaction/anchor.rs index 5c8d9a9c..90160806 100644 --- a/rmf_site_editor/src/interaction/anchor.rs +++ b/rmf_site_editor/src/interaction/anchor.rs @@ -38,7 +38,6 @@ pub fn add_anchor_visual_cues( >, categories: Query<&Category>, site_assets: Res, - interaction_assets: Res, ) { for (e, parent, subordinate, anchor) in &new_anchors { let body_mesh = match categories.get(parent.get()).unwrap() { diff --git a/rmf_site_editor/src/interaction/camera_controls.rs b/rmf_site_editor/src/interaction/camera_controls.rs index 0350c610..bf13cfc8 100644 --- a/rmf_site_editor/src/interaction/camera_controls.rs +++ b/rmf_site_editor/src/interaction/camera_controls.rs @@ -78,6 +78,18 @@ impl ProjectionMode { } } +pub struct ChangeProjectionMode(pub ProjectionMode); + +impl ChangeProjectionMode { + pub fn to_perspective() -> ChangeProjectionMode { + ChangeProjectionMode(ProjectionMode::Perspective) + } + + pub fn to_orthographic() -> ChangeProjectionMode { + ChangeProjectionMode(ProjectionMode::Orthographic) + } +} + #[derive(Debug, Clone, Reflect, Resource)] pub struct CameraControls { mode: ProjectionMode, @@ -152,6 +164,23 @@ impl CameraControls { self.use_perspective(!choice, cameras, visibilities, headlights_on); } + pub fn use_mode( + &mut self, + mode: ProjectionMode, + cameras: &mut Query<&mut Camera>, + visibilities: &mut Query<&mut Visibility>, + headlights_on: bool, + ) { + match mode { + ProjectionMode::Perspective => { + self.use_perspective(true, cameras, visibilities, headlights_on); + } + ProjectionMode::Orthographic => { + self.use_orthographic(true, cameras, visibilities, headlights_on); + } + } + } + pub fn mode(&self) -> ProjectionMode { self.mode } @@ -329,10 +358,21 @@ fn camera_controls( mut previous_mouse_location: ResMut, mut controls: ResMut, mut cameras: Query<(&mut Projection, &mut Transform)>, + mut bevy_cameras: Query<&mut Camera>, mut visibility: Query<&mut Visibility>, headlight_toggle: Res, picking_blockers: Res, + mut change_mode: EventReader, ) { + if let Some(mode) = change_mode.iter().last() { + controls.use_mode( + mode.0, + &mut bevy_cameras, + &mut visibility, + headlight_toggle.0, + ); + } + if headlight_toggle.is_changed() { controls.toggle_lights(headlight_toggle.0, &mut visibility); } @@ -488,6 +528,7 @@ impl Plugin for CameraControlsPlugin { app.insert_resource(MouseLocation::default()) .init_resource::() .init_resource::() + .add_event::() .add_system(camera_controls); } } diff --git a/rmf_site_editor/src/interaction/category_visibility.rs b/rmf_site_editor/src/interaction/category_visibility.rs new file mode 100644 index 00000000..7f7a7496 --- /dev/null +++ b/rmf_site_editor/src/interaction/category_visibility.rs @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +use bevy::prelude::*; + +use crate::site::SiteState; +use std::fmt::Debug; + +#[derive(Resource, Clone, Debug)] +pub struct CategoryVisibility(pub bool, std::marker::PhantomData); + +// Initialized to true (visible) by default +impl Default for CategoryVisibility { + fn default() -> Self { + Self(true, Default::default()) + } +} + +pub struct SetCategoryVisibility( + pub bool, + std::marker::PhantomData, +); + +impl From for SetCategoryVisibility { + fn from(val: bool) -> Self { + Self(val, Default::default()) + } +} + +#[derive(Default)] +pub struct CategoryVisibilityPlugin { + _ignore: std::marker::PhantomData, +} + +impl Plugin for CategoryVisibilityPlugin { + fn build(&self, app: &mut App) { + app.add_event::>() + .init_resource::>() + // TODO(luca) Check that this is at the right stage + .add_system_set_to_stage( + CoreStage::PreUpdate, + SystemSet::on_update(SiteState::Display) + .with_system(set_category_visibility::) + .with_system(set_category_visibility_for_new_entity::), + ); + } +} + +fn set_category_visibility( + mut events: EventReader>, + mut category_visibility: ResMut>, + mut visibilities: Query<&mut Visibility, With>, +) { + if let Some(visibility_event) = events.iter().last() { + if visibility_event.0 != category_visibility.0 { + for mut vis in &mut visibilities { + vis.is_visible = visibility_event.0; + } + category_visibility.0 = visibility_event.0; + } + } +} + +fn set_category_visibility_for_new_entity( + category_visibility: Res>, + mut visibilities: Query<&mut Visibility, Added>, +) { + for mut vis in &mut visibilities { + vis.is_visible = category_visibility.0; + } +} diff --git a/rmf_site_editor/src/interaction/highlight.rs b/rmf_site_editor/src/interaction/highlight.rs new file mode 100644 index 00000000..e9c66596 --- /dev/null +++ b/rmf_site_editor/src/interaction/highlight.rs @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2023 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * +*/ + +use crate::{interaction::*, site::DrawingMarker}; +use bevy::prelude::*; + +#[derive(Component)] +pub struct Highlight { + pub select: Color, + pub hover: Color, + pub hover_select: Color, +} + +#[derive(Component)] +pub struct SuppressHighlight; + +impl Highlight { + pub fn for_drawing() -> Self { + Self { + select: Color::rgb(1., 0.7, 1.), + hover: Color::rgb(0.7, 1., 1.), + hover_select: Color::rgb(1.0, 0.5, 0.7), + } + } +} + +pub fn add_highlight_visualization( + mut commands: Commands, + new_drawings: Query>, +) { + for e in &new_drawings { + commands.entity(e).insert(Highlight::for_drawing()); + } +} + +pub fn update_highlight_visualization( + highlightable: Query< + ( + &Hovered, + &Selected, + &Handle, + &Highlight, + Option<&SuppressHighlight>, + ), + Or<( + Changed, + Changed, + Changed, + Changed>, + )>, + >, + mut materials: ResMut>, +) { + for (hovered, selected, m, highlight, suppress) in &highlightable { + if let Some(material) = materials.get_mut(m) { + let mut color = if suppress.is_some() { + Color::WHITE + } else if hovered.cue() && selected.cue() { + highlight.hover_select + } else if hovered.cue() { + highlight.hover + } else if selected.cue() { + highlight.select + } else { + Color::WHITE + }; + color.set_a(material.base_color.a()); + + material.base_color = color; + } + } +} diff --git a/rmf_site_editor/src/interaction/lane.rs b/rmf_site_editor/src/interaction/lane.rs index 6f9e3816..4d9a7f0c 100644 --- a/rmf_site_editor/src/interaction/lane.rs +++ b/rmf_site_editor/src/interaction/lane.rs @@ -43,18 +43,18 @@ pub fn update_lane_visual_cues( site_assets: Res, cursor: Res, ) { - for (hovering, selected, pieces, mut tf) in &mut lanes { - if hovering.is_hovered { + for (hovered, selected, pieces, mut tf) in &mut lanes { + if hovered.is_hovered { set_visibility(cursor.frame, &mut visibility, false); } - let (m, h, v) = if hovering.cue() && selected.cue() { + let (m, h, v) = if hovered.cue() && selected.cue() { ( &site_assets.hover_select_material, HOVERED_LANE_OFFSET, true, ) - } else if hovering.cue() { + } else if hovered.cue() { (&site_assets.hover_material, HOVERED_LANE_OFFSET, true) } else if selected.cue() { (&site_assets.select_material, SELECTED_LANE_OFFSET, true) diff --git a/rmf_site_editor/src/interaction/mod.rs b/rmf_site_editor/src/interaction/mod.rs index ff1484dd..5b064534 100644 --- a/rmf_site_editor/src/interaction/mod.rs +++ b/rmf_site_editor/src/interaction/mod.rs @@ -15,7 +15,11 @@ * */ -use crate::site::{update_anchor_transforms, SiteUpdateStage}; +use crate::site::{ + update_anchor_transforms, ConstraintMarker, DoorMarker, FiducialMarker, FloorMarker, + LaneMarker, LiftCabin, LiftCabinDoorMarker, LocationTags, MeasurementMarker, ModelMarker, + SiteUpdateStage, WallMarker, +}; pub mod anchor; pub use anchor::*; @@ -26,6 +30,9 @@ pub use assets::*; pub mod camera_controls; pub use camera_controls::*; +pub mod category_visibility; +pub use category_visibility::*; + pub mod cursor; pub use cursor::*; @@ -35,6 +42,9 @@ pub use edge::*; pub mod gizmo; pub use gizmo::*; +pub mod highlight; +pub use highlight::*; + pub mod lane; pub use lane::*; @@ -59,6 +69,9 @@ pub use picking::*; pub mod point; pub use point::*; +pub mod popup; +pub use popup::*; + pub mod preview; pub use preview::*; @@ -127,6 +140,7 @@ impl Plugin for InteractionPlugin { .init_resource::() .init_resource::() .init_resource::() + .init_resource::() .add_event::() .add_event::