From 7702df5d8d10d9913f8ded6fd65a98dc1965ea3e Mon Sep 17 00:00:00 2001 From: Monty Marz Date: Thu, 6 Feb 2020 17:34:32 +0000 Subject: [PATCH] Hack to allow minimap rotation. Currently it just always rotates towards the camera, but it wouldn't be hard to create a config option that swaps out the rotation of the indicator and the map. --- CHANGELOG.md | 3 + .../buttons/button_mmap_closed_hover.vox | Bin 45263 -> 56639 bytes .../buttons/button_mmap_closed_press.vox | Bin 45263 -> 56639 bytes .../element/buttons/button_mmap_open.vox | Bin 45263 -> 56639 bytes .../buttons/button_mmap_open_hover.vox | Bin 45263 -> 56639 bytes .../buttons/button_mmap_open_press.vox | Bin 45263 -> 56639 bytes ...indicator.vox => indicator_mmap_small.vox} | Bin 56760 -> 60583 bytes .../buttons/min_plus/mmap_button-min.vox | Bin 1640 -> 58044 bytes .../min_plus/mmap_button-min_hover.vox | Bin 1640 -> 58044 bytes .../min_plus/mmap_button-min_press.vox | Bin 1624 -> 3560 bytes .../buttons/min_plus/mmap_button-plus.vox | Bin 1656 -> 58092 bytes .../min_plus/mmap_button-plus_hover.vox | Bin 1656 -> 58092 bytes .../min_plus/mmap_button-plus_press.vox | Bin 1608 -> 58092 bytes assets/voxygen/element/frames/mmap.vox | Bin 176060 -> 176344 bytes assets/voxygen/shaders/ui-frag.glsl | 3 +- assets/voxygen/shaders/ui-vert.glsl | 19 +- voxygen/src/hud/img_ids.rs | 10 +- voxygen/src/hud/map.rs | 59 +++-- voxygen/src/hud/minimap.rs | 186 +++++++++------ voxygen/src/hud/mod.rs | 21 +- voxygen/src/render/pipelines/ui.rs | 23 ++ voxygen/src/scene/camera.rs | 2 +- voxygen/src/ui/graphic/mod.rs | 215 ++++++++++-------- voxygen/src/ui/img_ids.rs | 2 + voxygen/src/ui/mod.rs | 118 +++++++--- world/src/sim/map.rs | 24 +- world/src/sim/mod.rs | 10 +- 27 files changed, 438 insertions(+), 257 deletions(-) rename assets/voxygen/element/buttons/{map_indicator.vox => indicator_mmap_small.vox} (88%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bc81b6ee7..e17f69506e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added music system +- Added zoomable and rotatable minimap +- Added rotating orientation marker to main-map ### Changed +- Brighter / higher contrast main-map ### Removed diff --git a/assets/voxygen/element/buttons/button_mmap_closed_hover.vox b/assets/voxygen/element/buttons/button_mmap_closed_hover.vox index e61ef968e12b180b1d5a8d1a9a8d12ccafdc5ea7..eeb88952224857408727e6d064280d843125b91d 100644 GIT binary patch literal 56639 zcmeI5cX%8}8OEnzIxrFKv3Kl?gT!F3Ge_3wN4?VmVFD!7I;WTFLSqe9zg!9W)BARn>7DJ*;& z79M162v4}6A%%K~_7L|73e3=g4|$M<45T3ig;0cXhD-nn`~mU@ zg|Pwh2gn~FuMdw8j}MOzj}MOzkB|BK@c2a}xvdAE2cHL@2cHL@2cHL@2cL&r79IojA!Ao@ECXuJO&;EkAcU4*}!AqG4N=3G&~v}4Ufi}X?Qd|8XjFlYA9FA z&qH?)^1$80+;{gV_i!IF9@fD^2GWpPz;5IUWrdhRn}SDStrXTwVeJ&w&^IRY&>lcO zygqyuWe;V~*erByItwI@d_Hm*#4Oq^Vj3|Iu?Vpcu@EtXSRgT_a*en_+#nw4D7VJL zc-Sw*BE)>H^AO$uF(32Nh-<_>ZE}OSMchN&*I^!^9-M z9-=)!yKkaQqi#^Q;s~oi74|`4 z9sC8WJ+#~0$6Nz&Sd@p*Hl#EZK?VvTi3gAe`N-vAKQ&|^3wh}4=St&jLlLAj&bP+- z*1|4zoO6vm)!19thJ8f4=h}S4u!bmGXb2vqamHL5&V|OFxH8TM;tF{*WFQN9kPih= z2t^{R4uwzv`H%-$$UquWB7-tyAPaer4+T&NMGzhfIUWnSfh>eaMV{}O+;JQC#8`R< zk2>7Hq%2pyb#m7Y$|9y*UUEk+B{@#*$D}S7^1B>T7T*zXQefv)T!|~SeD}G#ZX)ft z#4gv7)KcEQdEex%q|m>lO*$ueeJ+(sEOT7$lHeLwb+t>TxW+ZI+9fku;~HJFkpsy?BQI;9(cFTH=9W}6@*NhQXWFf)XyhAnJbQB-70qp_Xl_SEQ=y_c zo{HuKDw+*cG`FXsxdRo=9jRzeq@p>Aisoc0np3D~T{G{aOhcc!9= zsc5QHG$T|rqf|6wR5Udzn$xIg#;IsFQPG@EMRNuf&0VNy?n*^-CKb)ysA%p^MRN}- zn$1)+Tc~L6NkwxO70uaHH0My!Y^9<(mx^YBisn2jnr&1x+o@>Ir=r`TisoHZH1DROc@GuMd#PyN zM@92~Dw+>a(R`4K=4vXM4^h#4n2P2jR5Tx@qWKsV&Bv)|K0!tENh+F8QPF&wismy^ zG@qrS`5YC^=c#DEKt=OKDw;1*(R`VT<||Y*U!|h?8Wqjgsc61IMe|K6nr~6je4C2q z8Y-IaP|~A(fpK(=4VtiKc}Mk1r^ONsc3#h zMe}Pan%_{-{FaL5cT_aLr=s}-70n;1X#PY+^JglWzfjTqm5SzXR5X95qWK3E%|EGV z{zXOeZz`JqP|+NwqEY&2|9xxSomUWHAUpaQYm~%MY`eM>3 zp~nV+1INHWR;yIwF=2P{xh!32l)$f9^ z=PEr1bCroFGwo(_WUb0P>u!$=HV5qMZnjI@O7os8bh_<}oZl_nO#7gu7^@A*p!H7L zE#|xKG{wUsH8+!~R=trXx$Cnm&>alA16}2k^aBW2n8{jmu8=Nt+Tt&F>tI&S*frIs z)85j2n)Nx^n33TTIRkr9luL}xEJxk#%v7u0o^u3q*+RLM<(BoP>#g$ehv<~ld!2N; zJR7pVNio|^d$aA9ThgkGaVElYtvIT#Z?oH;&l_&I>2|B#75GhY#r<(Z&$hee&@R!5 zF3qafrL-qg&7~xQ5m)dgW1rFQvSMrpnl_pxs2h3E$>lkeHHz7CV7E#a_Opn~b(U3f zg=RNfHvd5uw~M__eLBnCMpT#53Kw3|BhG@Cbf;Bc9BlL@{eh%$Fi@E+Eea%Cwrp;< m2a|9qTus21YE#W*dPS}7YHmJmC#6rdf;ZQBI&HPYQ2j6eHA!^< literal 45263 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 diff --git a/assets/voxygen/element/buttons/button_mmap_closed_press.vox b/assets/voxygen/element/buttons/button_mmap_closed_press.vox index 23cf970bfc7ba205b86c46e594cc7a8c042dfcd6..773b63e831dfbcd7773b68d059c0ba28dc4184ea 100644 GIT binary patch literal 56639 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 literal 45263 zcmd6vdz_S29mdalpOrL}n}EW|MOd(PW-lx#>LMT)LF6LBs*J<#?C!X`GuzBC%;Kuy zdP74A5w%oABQg__R?@7H49zk#G_#D%%Q_nhB(&hLEB zIq#fVhRf0g%fg$LQuC+Hxd1oy)J~-q gH5naJ`4CHp-mo2ZIGhSD4l~|A+DkvwE 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 W%zVsF>OPSWK1}Djcq*j@k$(Yr41>S` literal 45263 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 diff --git a/assets/voxygen/element/buttons/button_mmap_open_hover.vox b/assets/voxygen/element/buttons/button_mmap_open_hover.vox index 88cb9c2c6dcb407c0c48e215554b094468622d02..471bd8c49e6ef7bf563edf70fce4895701c491e1 100644 GIT binary patch literal 56639 zcmeI5ca$4f6~^D2u7r{hN+Q(las$Vd?#;xciy}2yZ61{yQA46AA9e_zVhY9 zm>rw8?!?8Mag{Ng@_N~3*ZYJ4_Y5JbD*~{7j-nq?Lm)v z!56_7!WSYwfX~OiEc_OJ2Yv^B7k&@^2;&Ij(D9KwfHs8AWEMULJ{LX@z6kmd{Q!L* zd=_H|V;5r&_3$R9rIq`>x6JH3uT;a3+L}1{FD%Ye`?x>gFJaFm6T)275cy1m zzJ&!a4`y-)d$%xG8A`dQ*C_YJk9{~W7v{lySO5!Q5e$z3#2dsK#2LgGoQ1);V2rcK z_e}1*g+4JBKOx2(88qoj%ePGKI@Rdu ze62J|Bb%O{>!tEINe-u3bEYr4iadmpZhNjdBM-oMq@q#1PFgRniHvLZc0TX@38PZ({4^hBX7*{)aE2A znp;xQ+=_~(Oht2RDw>n2Xx35D+=hzgwp28?qoO&5isn=*n$xIgPN$-gzh=kt6T$7N zXx3BFj8M_sfr=)kqNz~Pj8f5TprRS0qN!5RoJmD9PDQhkisp_~G-pxK+=+_j&QvsK zQ_7V7Al(asc5!R(Of`9vyF;oI~C0i zDw>^CH1cn=@VxK2i;CtRR5X)RG`p#2_E6E>lZs|970tb(q@sBc70rXG zXdXgE^H3_9hf&cyoQmdRDw;=7(L9oh<`OEJM^Vu{nu_KzR5XvJqInz@&81W{mr>C? zo{HuPR5VYdqInV(&6BBUoaOrJ{Kq70v6ZXx>0Y^F}I~H&M~NnTqBuR5Wj;qInw?&D*JH-a$q4PAZyrQPI4c zisn63H1DONc^?(c`>AL?Kt=OGDw->)Xg)+m^I~B(fpi> z<`+~nzoer16&1~|sc3#fMe|!Kn%_~;{GN*D4^%XNq@wu~70sWiX#PS)^H(aGzfsZr zor>lkR5bsjqWKpU&A+K={zFA`go?)4|M&lUwL7u-f_12gGzaFxlKw&`^`w*Lhtx6K zZlpjpvB)!Yqy@0$@+_a097*Qlb38JxgM-InFj}pa2PR=jEpN6`39iQFYOGmm-Lxi) z#v}2#IvQE;;Be7#%t({W%NL!?v#VcJ_Pt&ctd%00Y85GDxr&l^+x_9%R}2CpT$it1 z>(44qx3-Wp3h1$+2@9#LYy&l|j`;ep< ztCnQZS|{!H=el|~#UrCt-N{s|)<~0FW0p9&!$o%@RGOq8LTG0?Yt3pWo$s_oUsUT* zR_s`(YW1|YxSwWiRthsZGAj4LK6IstP{neqYh|Wd?e?q^%x3dNDT|Wz>a|vJ^M?pZ zYQ0WcFYXPgZ_=OXroEYVOOLc7Yn%dM0)&2uXbK$(*y3oanben!YC6*WXeA}4QpSe{*V9%@1eN~+|A|Ip literal 45263 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 diff --git a/assets/voxygen/element/buttons/button_mmap_open_press.vox b/assets/voxygen/element/buttons/button_mmap_open_press.vox index 59510d8f44aaa71a394b9a2ee7c9909ee4ede88e..c20e0a9d138b8956ce51f6d5a510dcd5fba180bc 100644 GIT binary patch literal 56639 zcmeI5cXV7w6~<@g)wO{TLJ1|X#6TJrZ)I&{0s(9i9LJ7rWD{&dc&xNftBqH0m)(^u z(Fwix&>{5Rdxy|_?}Xla?_j=r-+EQg;T-fRr%DA^$wDrkH(uPgkb^wPhXN>6MJPvz zMQDrQiQtX;28z%g;T}VwE6oRx4|$M-EM%YviZM>fMNkL@^RXAAZ-_BMWv79I<|7uvAE6wg9DvWF?ojto z_fd~si18w{OIwIBBD6_7LO+Q`@XH-B8>Er-)6jaUMcJY3p&VG3`YI3YW% zwg54#A<7<9ve1 zjXBFb#{A_Tfko~ixa1z>vEF@@J;*^861EU)6kz>AtY3ij^V59a#I76Z8)NY&tb;i^ zxTGvszHMU9HH#var?}*fbu*IVj6qE5a$!w1hm^&4%$xSH>Lw{CJc3fhY z>sV?j@7!`=;s#O}T+$|;)4VpDNhOgvE_F$8m8-JSB~x7G8eQp<8Le_{TIrIv?JC#U zN|(%fm8-hag(JDzb>>PJ4)1E$xVR>^ZQY`u3*gwXW5>~}bmgzXi6Y(^5&6WF6z6pztG9>Inbo_=JfPj zFO%0vdL(N$X8Pi*$V({gw&xl%@&ZgoD%z{p$)<{WRXa#M?F=IF4osWvZc*K&)mmTE zB@#;;iNrQ0Bh{i>DV&>&+L59*t^-ZC=H_J{+9Pe%yINUFBX4gW8e!+5k!|Lokpsy? zBM&wYjl6|;Xyk>=LxV3_h-l;+EIfO&o{C2Hg=cTBPDOJKDw^Y{Xyh9?JkQPXR5aJ3 zqB((zM!s9g^W0pAisrghG}oh|IgyIy`cyRXJ1ji!v>Q^<$ZyQ??9EA3G&iQAxd|0b znTqD7R5T}3(QKfixfvDB&8cW^K}B;470szsG^bI~oK8g}f6R{OD}q~6(QKrm8KI)N z6%|cFMN^@o8Kt7xL`5@3MN_4sIg^TJoQh^M70s=wXwIUdxeXP~ZK-I^rlPqW70vCb zXzoBovxSOgD;3Qhsc6ojqB)m}=1x>J+o)*HqoUbPMRPtC%?>J>om4azP|@t7qS;MF zvxkc2&QvrLR5W|3X!cRj+=YtfLMocOQqkB;(L9`r<`GmhkEEh`6cx>*sc0TUMe|rHn#WPmJf4c? z2~;#sq@sBe70r{WXr4kv^HeIDOQ~p{Mn&^3Z^G+(7cTv&2n~LT= zR5b6UqIn+`&HJfnE~ldT02R##sc1e#Me|`QnvYP?e3XjjV^lOBr=s};70oB9Xg)qf@ zprZK}70tJ)Xud;5^Ia;M?@`fwpNi%OR5U-NqWKXO&5x;QenLg_Q!1LDQPKRIislzo zG{2;x`4tt-uc>H$Lq+pjDw^L>(fpo@<_}aff25-M6BW&$sc8N}Me|oGn!i!e{GE#C zA5=8|q@wv370pp98e{+8|L@iA?ycuyR*L3it4JZkRg}Ej?hnVlY|t^refik6{;cA3YYS<; zfF2tL4y}WKtXi%lW5TZS*=DxfD1kLsNE#Z&dTg%hsO?Q@UFUSHru`~Ov9gtlZq7M_ zxk}IBTxH_vbi0urTdN|^n%kqn#*lr@&DO-NEbnQd(`{d@eqFff_F+jeRxQb(wNBRU z&vo@QB_pF%oylaYR?pI0`z#4`hlB1ySGgqp5JC&n&DN|IviVM1{Kak^ZWc4vrrK22 zTbxg$HY*!5Ix;F}U_Xj-iBZjR)OBYjTkZC&63jN|i>)lStT$C_6^B1Ur?l4VWK+f2 zko`^jGu^B=({AaKR%DE`5teJ&QPsYUZhJ1T>u^);R=X?ko0GEs(4lAA-C}4>bc&`~ z@mxxKI@wrEA{a>-A2Rk?gD%U)R?w{8C_r`OVJFRVq*?FJ6a(ujT{OrdF6}Iqb--(+U?J=~1=dk?yo=3&V}RWH6944hJfdW&J*qEm=0*?cpRe ih1LXYu{POArdGQ293w07n%7 literal 45263 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 v1nZYJJt=HG4+XF&`tE>rp_^S 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 O5bO delta 2032 zcmbuAU2GIp6vywKnVp$C)BSEs3$ZL8g%+f2DWwz;0uiJjVAI$D0)+?(l?R$if}(K) zC7vRhdvlcF)>+r@a_1U)$rh})Bg6{^FRN4 z=I-9PnajV}Uw&nm`nPQ_ysMPjvbJX{L0$S)slJ|_>uchKD~=Y_!S)?HdoDQ)xLUMQ zj&ddv$|<|xF}77=!cmEG0$lLGM^oCVXt1<1WrG6=aJ5sK@)-DFAixxY(g`LcrYx|* zfdshVfe!`(2=NBmBlplf>K;CCO6i(Pg6Mz^7HFNLug5%>x?eH6CO<$AUD z*(RUu^4T_@?elpae4Y!Rt@e3NeD>dG8x6ja!DuiVj0U5@XfPU#2BX0kU<~jD_yT+Z zz5ribLVO{<5MPKd#24ZV@rC$8d^PxL@YPH?B|bdx!9W07Cov>3B+--T zN%SOo3Oz;R6pd5pDfAS28a<7kMo*)s(bMP|^bCD6^vR%S&@<>+^elRIs^swDfe!`( zuyl@Mj&G5pX^y5jJUKi$JaH{gEl({^El({^E!J!_8_ht*T5?`P6jLY?Rl*o5V zCMPFl{B)0ukL;82(IM#?KP*8@a_r~2hjeM-oO)TcWTtFh(;^4@yX4R&B`0?)xo||u z^*59(Ynm=S3+BqMWo}Z4*|Mx{o~&5X8a+F0mfg2uMl?FD zHM&v1^nb6XqoYIK>bf9{+b_z>(Fn3_#^mW49 zM^@{hYTPn^uo@TXm6CmOxH@hge7zd`=bfv@ZtKNrjOWEy9J`-BUX2f*D@#7zC>?rG z&YnFRt!b=_h8mr*HygWd>A~oSJF`6-f3dAA`s2==`p#mZvzR~_*f)G&U;HX8wiUag z=DVFU|Fy;M%7H_M&-Tvl!m@V$hqtZUv?!XKsvSFXx6jfm8MZe0IF@%6s{e7HfrE#K zd8Mji?4BPjy4ReF?^7)B7fUPR2GP-b`I!%7H=cHMaQ~5m|J-{??Ask(xi{ZD@I=4e M8_~t+x!)K64U;Kd>i_@% diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-min.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-min.vox index 322487d85b2066ce42f7821562376a0e5fbc6b78..433c06b901768b4a0d18eb2768cdb0264887aef3 100644 GIT binary patch literal 58044 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 delta 684 zcmXZYziL!L6oB!W^KZ_&i6F7Cv`8C*Wx&D|32b3vP$VuEA&@2(HX9ZM*}^7$Af$+W z`n60W!57d+u*qAD-wiJO?%cieo!RBy{?hxE#ryrk=a;3F*V~glmhvu2c{`cztPEfH zJc9mT4?j#N>oPno5Bi`F`k)UQr*WEv6FHF+Igt}NkrNq_5gCoq z7>&^wjnNp5(kPA6D2>u6jnXKM(g=;v2#wGPjnK%fF1QpVZ=oUJFen5S1<6}#2sjK1 zK}8wXTF+{gd94bABhZj%QtMn{a2y4fhGZ}qOa_y|WH1>_2J>Ms8B7L~!JG#glvZiu zfwAxGJFBtUe0ejzsu!;wKi%AU`J(UdZuRM#?f&U#uYdVG?dM-l`t10i|GxX)e_Vg; aKW|R^cs%aU)}CB^TiwvVf68*XTIC-ESZ^Ev diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-min_hover.vox index 1b27aa486472182916e893830ee29db2df0c5342..5dfa14ec30092ffdf39ef953e1159fa4db4cb796 100644 GIT binary patch literal 58044 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 Xa=n^vzkZz7S0AQ7zrH`*yja*HKs;uk diff --git a/assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox b/assets/voxygen/element/buttons/min_plus/mmap_button-min_press.vox index 6e4c11db7d58b827aba558b5b543e4dc8035b3bb..950abaa9b729821fdbc23b278af1771d2f9216ea 100644 GIT binary patch literal 3560 zcmb8xZETiT8Nl&#&i(#=-{+LFmI)n$LFpVXWkBV{GU&E4aWY)pDiU8H;~81jG-i25 zaE8?^W0Q!8Fp^E|lrXal$5zOUACM2YELj$U#F!YeG{*SV561ZI^54hBX#Aiy`RDXJ z^tpb|MQCou9)7Ivlu~Nv*3r*%sGEgSyGO@I^0^CNUF3aoKKA(d=ueZmSCu+oI!9Y8 z)#lqaKhyRpppYVpi63vLlo2!AjBl4zQB4h5a-_6sYck}KPXUD#QA`P?lu=Fvl~hqp z4OwzzjN0dsPXUD#QA`P?lu=Fvl~hqp4Ow!elx9!Oo|-*1dusO7?5WvPv!`ZH&7PV) zHG69I)akLg$Kg(v92w)|_&7d}kK^O`I6jV#bz6XV1< zF;0vVC&S5bGMo%2!^vZgPKi_ElsF|$iBsZ~I3-SrQ{q%O6;6dy;czEQj*O{rDx3GH zschWQQi8|F96ZJR!e42D0%R;YjS7T-{db{U2^s6PMQ09 zYxI&_`Joc|wUXJ{S-Es{R4$$Pnp`?PA?q(aEzL-`^nA5X`kot*{Q&H1a z)U|G@cPg3xl#<(zE4lk^CGkNe#gr1qz57iiYjSQVEoh~`LtdaAp=E=>?3q*F@At#lR%k*3NBb{t3x$pxeSI;Z?;3D^7CDS8H-g`vJ zttXU>b8n9+IlhnApHZ@{U&-DLN}k!SZ++9>2)%}ZQ-92~7XV&z~@$cL&7k<20e)qu&x%JV2yoxz zP_DhTP5%7*-7@)dEysS=B^R&v$Sqm)Z~I$o|L6U$zW62i)4A6Fwg2Syq5s%_aBxt* zzy7SOTsq>5ZS;?ErmrH+tzuap#%jX_^N7U3InKwC4E}vHN(vXtp zdil4raG`vA=}B3&azggK{DR!JcfNe|^QH3cSdX0G@9JOw{^$HH8&7m*J-+)xnLHr! z?CJ9|^^+MnGJR3b{OX3>J8@LDJbzXm`q35H{q_wR9v+riemzu7@>lV0DEaso|M+|# z^Y81w{W-sdGSGXU%$-~GMCaVOtkpR`tv5>Z=w#>nrLFIF&au1Bbj~4jxO2|EZ|-aE q9QwwQ&UyEl>*A^&8PqL#_w@sEary~)?~Q|U`RJ4X{Mk?5qy7%H-a7aI delta 635 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 delta 715 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 delta 628 zcmW;IJ!%|55QgEZuBz@@>nBn!T|uD4;6NM5uz~&%h}A~Mph$ro%&;IZ>(IHtIB}#S z=mj3+KUSk! x|Ma@`M<2fL?(Ls^IvmbFe;ig9^WpBx*>L}DHT?Q*0j>^kwE1Xhf&VQ&F5{$9WJkNSyc&kdLUXc)%k>9w;6eRbZ{mU6T0Be#E3(|VjJ*tv20vRpLLD&Np!eluCJctIh!$<&7M`evr9CTQ&Txa@{zo zQ5m5}#2+P3X*XGi4cL^!=}R^7vb?CUXfVN$%S2fr%Kohi<0?o!pVms*Of96)HnNBs zB!+HKXN#H#WbBi%&nbdLkx@+V`Shhv@8mBwgx~k*PLIyh@~NQ-0oMFGEIPnvI<&=c zv8;=*avy2jM;gmpQtjI^xI&?pIP~7s)Iq+}6mKn7aI8WNED-Enlk41|pT96Ct~3-A z8cZe{E%E1-3WElobr_M$h+INmO2~_d%538-|EeWcY#)n<#lw>CZi_Eel_0aWcs{BT z!~((PNKjzNMe^O91_agRyhZEP$+fsZk2LY2j6(0CRD-lZ8S4a)UBOysbixvgysP7|7)s0j(03^SdN7An-kO$I4cfaYehia>NyHR7MRm zvv5+&sYV*=zEmM4G-#7L1o%zVIFtHFI^kNzT%cQC^5Im=&7p^GB7I~98R&8Txg(xe zBR!s;n-^&Uxh-)a1_wxf=D?Lju>lsmc8SAeIS0h>@zW;W5;SW9n-ZHj1%>E8q>W$p}ZcBUk*f| zT$IP|5wGrv2_LiSL0K6Z)Jy1vbj(=l#Wc#rg7}#T^Gge2@#KidzFrgtxqyZ)TiiWm#@Z2PW5B1%*~W? zr@vkl*MuDtW=y>%cuxC!L|Yx#IG9j@Dva4Bh6q9!K>!WTQ7x zm&8F8qs*4X(P~tdI?5l~Cw|KHMbqp1#P7{&z_ib3?+?WXX4PZlGWyRE@$TzaJ9I-E zS}+Gqu)(2IY;fp%hphW*oH%Unu)V|i9Xh}+Z9YB`IyO4Z28V98q0g1{pbH&vcoQ}_ zd=hMMq<0C$%euveIQ04F=s_1c(1sSwK@)mKg0%J=w4ezDm|0m82b81Y>F0kD3^8ui(;hvsLOjxElvJ+XiG=IH*} s>Zzl%b7xM>-1Dbr4?l2t_N$+}vlp*CH+%E7-^~{0yVGC%O{{(Pf7#0|wEzGB delta 1986 zcmXYyTZmOv7{~Xw*4pQO=Gp@OJ|2|FwR+G4E%20wL6d(^d7=S4guRm>K^{0$of6|!x zq|x;(@eHIP1xZLi9Ac`Q=-C)Xbr(z5cWaGKqe^v`&RxI%fGHb)e(CHVu9#9}{r>0Q zVv3Qqa_gvV3RsIfZoi(ebfahKW^d_}+o#lsXdjPbXpW;fmUem-mWpXC?!U7ku1sTI zo5qrJXHs?<981pz$~+m^*kUFF%Nz<~*n{SHFl6dM)zpGGegcxPxbn{~lZlM{-IaV6 zG}Ix#`72j$mn`dM6>#MVCm_ggk6RTom{?e8=W`)(%1jK zZFJ7~eMiYLyHqhv8Y%~6RGA9@(+sc1Won^Fpa6Nu!2o0-18GP>5)xpkt%0a*fztbG zqW4mKPoUKHTAW;LEx(2QR$|*~1B}TgWixG8@~%2jF)fbJnlFK+ z#@S_pT{hQ>_ytgAFvzcIHpro3GEAsNr>r+==9~;N*l9>X5)u%H7}yY=PfM$8urwHT zxNd`rGWWv}UT*4& z>4d9!IUPQ-Eae$XjnLrwAW5@1(_w8g5R+mq9m;k11v|`Ukk}A+vKplEQ;>uN#32SY zgx?k9X4PP6FePW*`kINJ0XX*}+rc(2YYk(Z<^Yqh{+S@=+b-P(^_o6*;ZNIQ=7o zG9`?}4c{A*+3@VLRHv1Gkc+vQ-)MrOE@N;h=u*(7pi4oQf-cRu6g|kJ=~C=*uFnD3 zz+>xj_&Ex@;dE7A8P^25+(%ze20nK(MzX691s-?v878Ax_*+%lbmWFltdkEmSemz> z_IkTjtZp$JF~ba~+f!yF(4h>=3u3|-hh=2HO>{as89IZ;(OEQs&Y?;42%18VqG|LP zn$g|x@~~WZI7?sva*&4t6hWECf)XlbKc{*$C}UT2xBuFRT#$?ykG3QH`F?qWt^Fa z@|7Lecn0sU9dhN;LYuBT;D8Gr_|RawO=v+II^ci{9{AAZmD^>eU1sX@I`%kB1Deo+ zHgv!N7kt|D*6`WiV}Eaf0v-iC3V0OoC=lUe`^0>5K5KjyNB`u{`+P~de6qR}Z1YKL zK?mA=+S+{PnrpERakuBJt$_2tIu`7 + + // Minimap + indicator_mmap_small: "voxygen.element.buttons.indicator_mmap_small", } } @@ -131,7 +138,6 @@ image_ids! { skull_2: "voxygen.element.icons.skull_2", // Map - map_indicator: "voxygen.element.buttons.map_indicator", indicator_mmap: "voxygen.element.buttons.indicator_mmap", indicator_mmap_2: "voxygen.element.buttons.indicator_mmap_2", indicator_mmap_3: "voxygen.element.buttons.indicator_mmap_3", @@ -169,7 +175,7 @@ image_ids! { mmap_open_press: "voxygen.element.buttons.button_mmap_open_press", mmap_plus: "voxygen.element.buttons.min_plus.mmap_button-plus", mmap_plus_hover: "voxygen.element.buttons.min_plus.mmap_button-plus_hover", - mmap_plus_press: "voxygen.element.buttons.min_plus.mmap_button-plus_hover", + mmap_plus_press: "voxygen.element.buttons.min_plus.mmap_button-plus_press", mmap_minus: "voxygen.element.buttons.min_plus.mmap_button-min", mmap_minus_hover: "voxygen.element.buttons.min_plus.mmap_button-min_hover", mmap_minus_press: "voxygen.element.buttons.min_plus.mmap_button-min_press", diff --git a/voxygen/src/hud/map.rs b/voxygen/src/hud/map.rs index 662d004ccc..0ce7691198 100644 --- a/voxygen/src/hud/map.rs +++ b/voxygen/src/hud/map.rs @@ -1,9 +1,12 @@ -use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR}; +use super::{ + img_ids::{Imgs, ImgsRot}, + Fonts, Show, TEXT_COLOR, +}; +use crate::ui::img_ids; use client::{self, Client}; use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize}; use conrod_core::{ color, - image::Id, widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; @@ -30,12 +33,13 @@ widget_ids! { pub struct Map<'a> { _show: &'a Show, client: &'a Client, - world_map: (Id, Vec2), + world_map: &'a (img_ids::Rotations, Vec2), imgs: &'a Imgs, + rot_imgs: &'a ImgsRot, fonts: &'a Fonts, #[conrod(common_builder)] common: widget::CommonBuilder, - pulse: f32, + _pulse: f32, velocity: f32, } impl<'a> Map<'a> { @@ -43,7 +47,8 @@ impl<'a> Map<'a> { show: &'a Show, client: &'a Client, imgs: &'a Imgs, - world_map: (Id, Vec2), + rot_imgs: &'a ImgsRot, + world_map: &'a (img_ids::Rotations, Vec2), fonts: &'a Fonts, pulse: f32, velocity: f32, @@ -51,11 +56,12 @@ impl<'a> Map<'a> { Self { _show: show, imgs, + rot_imgs, world_map, client, fonts, common: widget::CommonBuilder::default(), - pulse, + _pulse: pulse, velocity, } } @@ -160,9 +166,9 @@ impl<'a> Widget for Map<'a> { let (world_map, worldsize) = self.world_map; let worldsize = worldsize.map2(TerrainChunkSize::RECT_SIZE, |e, f| e as f64 * f as f64); - Image::new(world_map) + Image::new(world_map.none) .middle_of(state.ids.map_bg) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade - 0.1))) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade + 0.5))) .w_h(700.0, 700.0) .parent(state.ids.map_bg) .set(state.ids.grid, ui); @@ -177,31 +183,18 @@ impl<'a> Widget for Map<'a> { let x = player_pos.x as f64 / worldsize.x * 700.0; let y = player_pos.y as f64 / worldsize.y * 700.0; - let indic_ani = (self.pulse * 6.0/*animation speed*/).cos()/*starts at 1.0*/ * 0.5 + 0.50; // changes the animation frame - let indic_scale = 1.2; - // Indicator - Image::new(if indic_ani <= 0.3 { - self.imgs.indicator_mmap - } else if indic_ani <= 0.6 { - self.imgs.indicator_mmap_2 - } else { - self.imgs.indicator_mmap_3 - }) - .bottom_left_with_margins_on(state.ids.grid, y, x - (20.0 * 1.2) / 2.0) - .w_h( - 22.0 * 1.2, - if indic_ani <= 0.3 { - 16.0 * indic_scale - } else if indic_ani <= 0.6 { - 23.0 * indic_scale - } else { - 34.0 * indic_scale - }, - ) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade + 0.2))) - .floating(true) - .parent(ui.window) - .set(state.ids.indicator, ui); + let indic_scale = 0.6; + Image::new(self.rot_imgs.indicator_mmap_small.target_north) + .bottom_left_with_margins_on( + state.ids.grid, + y - 37.0 * indic_scale / 2.0, + x - 32.0 * indic_scale / 2.0, + ) + .w_h(32.0 * indic_scale, 37.0 * indic_scale) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) + .floating(true) + .parent(ui.window) + .set(state.ids.indicator, ui); None } diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index fc196c6e5b..259325f178 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -1,9 +1,12 @@ -use super::{img_ids::Imgs, Fonts, Show, HP_COLOR, TEXT_COLOR}; +use super::{ + img_ids::{Imgs, ImgsRot}, + Fonts, Show, HP_COLOR, TEXT_COLOR, +}; +use crate::ui::img_ids; use client::{self, Client}; use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize}; use conrod_core::{ - color, - image::Id, + color, position, widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon, }; @@ -33,12 +36,11 @@ pub struct MiniMap<'a> { client: &'a Client, imgs: &'a Imgs, - world_map: (Id, Vec2), + rot_imgs: &'a ImgsRot, + world_map: &'a (img_ids::Rotations, Vec2), fonts: &'a Fonts, #[conrod(common_builder)] common: widget::CommonBuilder, - pulse: f32, - zoom: f32, } impl<'a> MiniMap<'a> { @@ -46,20 +48,18 @@ impl<'a> MiniMap<'a> { show: &'a Show, client: &'a Client, imgs: &'a Imgs, - world_map: (Id, Vec2), + rot_imgs: &'a ImgsRot, + world_map: &'a (img_ids::Rotations, Vec2), fonts: &'a Fonts, - pulse: f32, - zoom: f32, ) -> Self { Self { show, client, imgs, + rot_imgs, world_map, fonts, common: widget::CommonBuilder::default(), - pulse, - zoom, } } } @@ -69,6 +69,7 @@ pub struct State { last_region_name: Option, last_update: Instant, + zoom: f64, } pub enum Event { @@ -86,6 +87,14 @@ impl<'a> Widget for MiniMap<'a> { last_region_name: None, last_update: Instant::now(), + zoom: { + let min_world_dim = self.world_map.1.reduce_partial_min() as f64; + min_world_dim.min( + min_world_dim + * (TerrainChunkSize::RECT_SIZE.reduce_partial_max() as f64 / 32.0) + * (16.0 / 1024.0), + ) + }, } } @@ -93,53 +102,74 @@ impl<'a> Widget for MiniMap<'a> { fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { state, ui, .. } = args; - let zoom = self.zoom as f64; + let zoom = state.zoom; if self.show.mini_map { Image::new(self.imgs.mmap_frame) - .w_h(100.0 * 4.0 * zoom, 100.0 * 4.0 * zoom) + .w_h(100.0 * 3.0, 100.0 * 3.0) .top_right_with_margins_on(ui.window, 5.0, 5.0) .set(state.ids.mmap_frame, ui); - Rectangle::fill_with([92.0 * 4.0, 82.0 * 4.0], color::TRANSPARENT) - .mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 4.0 + 4.0 * zoom) + Rectangle::fill_with([92.0 * 3.0, 82.0 * 3.0], color::TRANSPARENT) + .mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 3.0 + 3.0) .set(state.ids.mmap_frame_bg, ui); - // Zoom Buttons - // TODO: Add zoomable minimap - /*if Button::image(self.imgs.mmap_plus) - .w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom) - .hover_image(self.imgs.mmap_plus_hover) - .press_image(self.imgs.mmap_plus_press) - .top_left_with_margins_on(state.ids.mmap_frame, 0.0, 0.0) - .set(state.ids.mmap_plus, ui) - .was_clicked() - { - if zoom > 0.0 { - zoom = zoom + 1.0 - } else if zoom == 5.0 { - } - } - if Button::image(self.imgs.mmap_minus) - .w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom) - .hover_image(self.imgs.mmap_minus_hover) - .press_image(self.imgs.mmap_minus_press) - .down_from(state.ids.mmap_plus, 0.0) - .set(state.ids.mmap_minus, ui) - .was_clicked() - { - if zoom < 6.0 { - zoom = zoom - 1.0 - } else if zoom == 0.0 { - } - }*/ - // Map Image + // Map size let (world_map, worldsize) = self.world_map; let worldsize = worldsize.map2(TerrainChunkSize::RECT_SIZE, |e, f| e as f64 * f as f64); - Image::new(world_map) - .middle_of(state.ids.mmap_frame_bg) - .w_h(92.0 * 4.0 * zoom, 82.0 * 4.0 * zoom) - .parent(state.ids.mmap_frame_bg) - .set(state.ids.grid, ui); + + // Zoom Buttons + + // Pressing + multiplies, and - divides, zoom by ZOOM_FACTOR. + const ZOOM_FACTOR: f64 = 2.0; + + // TODO: Either prevent zooming all the way in, *or* see if we can interpolate + // somehow if you zoom in too far. Or both. + let min_zoom = 1.0; + let max_zoom = (worldsize / TerrainChunkSize::RECT_SIZE.map(|e| e as f64)) + .reduce_partial_min()/*.min(f64::MAX)*/; + + // NOTE: Not sure if a button can be clicked while disabled, but we still double + // check for both kinds of zoom to make sure that not only was the + // button clicked, it is also okay to perform the zoom action. + // Note that since `Button::image` has side effects, we must perform + // the `can_zoom_in` and `can_zoom_out` checks after the `&&` to avoid + // undesired early termination. + let can_zoom_in = zoom < max_zoom; + let can_zoom_out = zoom > min_zoom; + + if Button::image(self.imgs.mmap_minus) + .w_h(100.0 * 0.30, 100.0 * 0.30) + .hover_image(self.imgs.mmap_minus_hover) + .press_image(self.imgs.mmap_minus_press) + .top_left_with_margins_on(state.ids.mmap_frame, 0.0, 0.0) + .enabled(can_zoom_out) + .set(state.ids.mmap_minus, ui) + .was_clicked() + && can_zoom_out + { + // Set the image dimensions here, rather than recomputing each time. + let zoom = min_zoom.max(zoom / ZOOM_FACTOR); + state.update(|s| s.zoom = zoom); + // set_image_dims(zoom); + } + if Button::image(self.imgs.mmap_plus) + .w_h(100.0 * 0.30, 100.0 * 0.30) + .hover_image(self.imgs.mmap_plus_hover) + .press_image(self.imgs.mmap_plus_press) + .right_from(state.ids.mmap_minus, 6.0) + .enabled(can_zoom_in) + .set(state.ids.mmap_plus, ui) + .was_clicked() + && can_zoom_in + { + let zoom = max_zoom.min(zoom * ZOOM_FACTOR); + state.update(|s| s.zoom = zoom); + // set_image_dims(zoom); + } + + // Reload zoom in case it changed. + let zoom = state.zoom; + // Coordinates let player_pos = self .client @@ -149,30 +179,36 @@ impl<'a> Widget for MiniMap<'a> { .get(self.client.entity()) .map_or(Vec3::zero(), |pos| pos.0); - let x = player_pos.x as f64 / worldsize.x * 92.0 * 4.0; - let y = player_pos.y as f64 / worldsize.y * 82.0 * 4.0; - let indic_ani = (self.pulse * 6.0).cos() * 0.5 + 0.5; //Animation timer - let indic_scale = 0.8; + // Get map image source rectangle dimensons. + let w_src = worldsize.x / TerrainChunkSize::RECT_SIZE.x as f64 / zoom; + let h_src = worldsize.y / TerrainChunkSize::RECT_SIZE.y as f64 / zoom; + + // Set map image to be centered around player coordinates. + let rect_src = position::Rect::from_xy_dim( + [ + player_pos.x as f64 / TerrainChunkSize::RECT_SIZE.x as f64, + (worldsize.y - player_pos.y as f64) / TerrainChunkSize::RECT_SIZE.y as f64, + ], + [w_src, h_src], + ); + + // Map Image + Image::new(world_map.source_north) + .middle_of(state.ids.mmap_frame_bg) + .w_h(92.0 * 3.0, 82.0 * 3.0) + .parent(state.ids.mmap_frame_bg) + .source_rectangle(rect_src) + .set(state.ids.grid, ui); + // Indicator - Image::new(if indic_ani <= 0.5 { - self.imgs.indicator_mmap - } else { - self.imgs.indicator_mmap_2 - }) - .bottom_left_with_margins_on(state.ids.grid, y, x - 5.0) - .w_h( - // Animation frames depening on timer value from 0.0 to 1.0 - 22.0 * 0.8, - if indic_ani <= 0.5 { - 18.0 * indic_scale - } else { - 23.0 * indic_scale - }, - ) - .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) - .floating(true) - .parent(ui.window) - .set(state.ids.indicator, ui); + let ind_scale = 0.4; + Image::new(self.rot_imgs.indicator_mmap_small.none) + .middle_of(state.ids.grid) + .w_h(32.0 * ind_scale, 37.0 * ind_scale) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) + .floating(true) + .parent(ui.window) + .set(state.ids.indicator, ui); } else { Image::new(self.imgs.mmap_frame_closed) .w_h(100.0 * 2.0, 11.0 * 2.0) @@ -186,9 +222,9 @@ impl<'a> Widget for MiniMap<'a> { self.imgs.mmap_closed }) .wh(if self.show.mini_map { - [100.0 * 0.4; 2] + [100.0 * 0.3; 2] } else { - [100.0 * 0.2 * zoom; 2] + [100.0 * 0.2; 2] }) .hover_image(if self.show.mini_map { self.imgs.mmap_open_hover @@ -267,7 +303,7 @@ impl<'a> Widget for MiniMap<'a> { state.ids.mmap_frame, if self.show.mini_map { 6.0 } else { 0.0 }, ) - .font_size(if self.show.mini_map { 30 } else { 18 }) + .font_size(if self.show.mini_map { 20 } else { 18 }) .font_id(self.fonts.cyri) .color(TEXT_COLOR) .set(state.ids.mmap_location, ui), diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 1a16e2c2d8..2c9f442e1d 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -13,7 +13,7 @@ mod skillbar; mod social; mod spell; -use crate::{ecs::comp::HpFloaterList, hud::img_ids::ImgsRot}; +use crate::{ecs::comp::HpFloaterList, hud::img_ids::ImgsRot, ui::img_ids::Rotations}; pub use settings_window::ScaleChange; use std::time::Duration; @@ -46,7 +46,6 @@ use crate::{ use client::{Client, Event as ClientEvent}; use common::{assets::load_expect, comp, terrain::TerrainChunk, vol::RectRasterableVol}; use conrod_core::{ - image::Id, text::cursor::Index, widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, @@ -307,7 +306,7 @@ impl Show { fn map(&mut self, open: bool) { self.map = open; self.bag = false; - self.want_grab = !open; + self.want_grab = true; } fn character_window(&mut self, open: bool) { @@ -431,7 +430,7 @@ impl Show { pub struct Hud { ui: Ui, ids: Ids, - world_map: (Id, Vec2), + world_map: (/* Id */ Rotations, Vec2), imgs: Imgs, item_imgs: ItemImgs, fonts: Fonts, @@ -446,7 +445,6 @@ pub struct Hud { force_chat_input: Option, force_chat_cursor: Option, pulse: f32, - zoom: f32, velocity: f32, } @@ -461,7 +459,7 @@ impl Hud { let ids = Ids::new(ui.id_generator()); // Load world map let world_map = ( - ui.add_graphic(Graphic::Image(client.world_map.0.clone())), + ui.add_graphic_with_rotations(Graphic::Image(client.world_map.0.clone())), client.world_map.1, ); // Load images. @@ -497,7 +495,7 @@ impl Hud { quest: false, spell: false, character_window: false, - mini_map: false, + mini_map: true, settings_tab: SettingsTab::Interface, social_tab: SocialTab::Online, want_grab: true, @@ -509,7 +507,6 @@ impl Hud { force_chat_input: None, force_chat_cursor: None, pulse: 0.0, - zoom: 1.0, velocity: 0.0, } } @@ -1590,10 +1587,9 @@ impl Hud { &self.show, client, &self.imgs, - self.world_map, + &self.rot_imgs, + &self.world_map, &self.fonts, - self.pulse, - self.zoom, ) .set(self.ids.minimap, ui_widgets) { @@ -1864,7 +1860,8 @@ impl Hud { &self.show, client, &self.imgs, - self.world_map, + &self.rot_imgs, + &self.world_map, &self.fonts, self.pulse, self.velocity, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 6f3ab102ea..35ba91bb86 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -10,6 +10,7 @@ gfx_defines! { pos: [f32; 2] = "v_pos", uv: [f32; 2] = "v_uv", color: [f32; 4] = "v_color", + center: [f32; 2] = "v_center", mode: u32 = "v_mode", } @@ -55,11 +56,23 @@ pub const MODE_TEXT: u32 = 0; pub const MODE_IMAGE: u32 = 1; /// Ignore `tex` and draw simple, colored 2D geometry. pub const MODE_GEOMETRY: u32 = 2; +/// Draw an image from the texture at `tex` in the fragment shader, with the +/// source rectangle rotated to face north. +/// +/// FIXME: Make more principled. +pub const MODE_IMAGE_SOURCE_NORTH: u32 = 3; +/// Draw an image from the texture at `tex` in the fragment shader, with the +/// target rectangle rotated to face north. +/// +/// FIXME: Make more principled. +pub const MODE_IMAGE_TARGET_NORTH: u32 = 5; pub enum Mode { Text, Image, Geometry, + ImageSourceNorth, + ImageTargetNorth, } impl Mode { @@ -68,6 +81,8 @@ impl Mode { Mode::Text => MODE_TEXT, Mode::Image => MODE_IMAGE, Mode::Geometry => MODE_GEOMETRY, + Mode::ImageSourceNorth => MODE_IMAGE_SOURCE_NORTH, + Mode::ImageTargetNorth => MODE_IMAGE_TARGET_NORTH, } } } @@ -78,10 +93,16 @@ pub fn create_quad( color: Rgba, mode: Mode, ) -> Quad { + let center = if let Mode::ImageSourceNorth = mode { + uv_rect.center().into_array() + } else { + rect.center().into_array() + }; let mode_val = mode.value(); let v = |pos, uv| Vertex { pos, uv, + center, color: color.into_array(), mode: mode_val, }; @@ -118,10 +139,12 @@ pub fn create_tri( color: Rgba, mode: Mode, ) -> Tri { + let center = [0.0, 0.0]; let mode_val = mode.value(); let v = |pos, uv| Vertex { pos, uv, + center, color: color.into_array(), mode: mode_val, }; diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index d35a4c240b..a0d0d59e54 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -190,7 +190,7 @@ impl Camera { } /// Get the focus position of the camera. - pub fn get_focus_pos(&self) -> Vec3 { self.tgt_focus } + pub fn get_focus_pos(&self) -> Vec3 { self.focus } /// Set the focus position of the camera. pub fn set_focus_pos(&mut self, focus: Vec3) { self.tgt_focus = focus; } diff --git a/voxygen/src/ui/graphic/mod.rs b/voxygen/src/ui/graphic/mod.rs index 3fc704b30a..f1431aff08 100644 --- a/voxygen/src/ui/graphic/mod.rs +++ b/voxygen/src/ui/graphic/mod.rs @@ -6,7 +6,7 @@ pub use renderer::{SampleStrat, Transform}; use crate::render::{Renderer, Texture}; use dot_vox::DotVoxData; use guillotiere::{size2, SimpleAtlasAllocator}; -use hashbrown::HashMap; +use hashbrown::{hash_map::Entry, HashMap}; use image::{DynamicImage, RgbaImage}; use log::warn; use pixel_art::resize_pixel_art; @@ -26,6 +26,14 @@ pub enum Rotation { Cw90, Cw180, Cw270, + /// Orientation of source rectangle that always faces true north. + /// Simple hack to get around Conrod not having space for proper + /// rotation data (though it should be possible to add in other ways). + SourceNorth, + /// Orientation of target rectangle that always faces true north. + /// Simple hack to get around Conrod not having space for proper + /// rotation data (though it should be possible to add in other ways). + TargetNorth, } /// Images larger than this are stored in individual textures @@ -41,7 +49,7 @@ pub struct Id(u32); #[derive(PartialEq, Eq, Hash, Copy, Clone)] pub struct TexId(usize); -type Parameters = (Id, Vec2, Aabr); +type Parameters = (Id, Vec2); type GraphicMap = HashMap; enum CacheLoc { @@ -130,6 +138,8 @@ impl GraphicCache { self.textures = vec![texture]; } + /// Source rectangle should be from 0 to 1, and represents a bounding box + /// for the source image of the graphic. pub fn cache_res( &mut self, renderer: &mut Renderer, @@ -137,15 +147,18 @@ impl GraphicCache { dims: Vec2, source: Aabr, rotation: Rotation, - ) -> Option<(Aabr, TexId)> { + ) -> Option<(Aabr, TexId)> { let dims = match rotation { Rotation::Cw90 | Rotation::Cw270 => Vec2::new(dims.y, dims.x), Rotation::None | Rotation::Cw180 => dims, + Rotation::SourceNorth => dims, + Rotation::TargetNorth => dims, }; - let key = (graphic_id, dims, source.map(|e| e.to_bits())); // TODO: Replace this with rounded representation of source + let key = (graphic_id, dims); + // Rotate aabr according to requested rotation. let rotated_aabr = |Aabr { min, max }| match rotation { - Rotation::None => Aabr { min, max }, + Rotation::None | Rotation::SourceNorth | Rotation::TargetNorth => Aabr { min, max }, Rotation::Cw90 => Aabr { min: Vec2::new(min.x, max.y), max: Vec2::new(max.x, min.y), @@ -156,101 +169,115 @@ impl GraphicCache { max: Vec2::new(min.x, max.y), }, }; + // Scale aabr according to provided source rectangle. + let scaled_aabr = |aabr: Aabr<_>| { + let size: Vec2<_> = aabr.size().into(); + Aabr { + min: size.mul_add(source.min, aabr.min), + max: size.mul_add(source.max, aabr.min), + } + }; + // Apply all transformations. + // TODO: Verify rotation is being applied correctly. + let transformed_aabr = |aabr| rotated_aabr(scaled_aabr(aabr)); - if let Some(details) = self.cache_map.get(&key) { - let (idx, aabr) = match details.location { - CacheLoc::Atlas { - atlas_idx, aabr, .. - } => (self.atlases[atlas_idx].1, aabr), - CacheLoc::Texture { index } => { - (index, Aabr { - min: Vec2::new(0, 0), - // Note texture should always match the cached dimensions - max: dims, - }) - }, - }; + let details = match self.cache_map.entry(key) { + Entry::Occupied(details) => { + let details = details.get(); + let (idx, aabr) = match details.location { + CacheLoc::Atlas { + atlas_idx, aabr, .. + } => (self.atlases[atlas_idx].1, aabr), + CacheLoc::Texture { index } => { + (index, Aabr { + min: Vec2::new(0, 0), + // Note texture should always match the cached dimensions + max: dims, + }) + }, + }; - // Check if the cached version has been invalidated by replacing the underlying - // graphic - if !details.valid { - // Create image - let image = draw_graphic(&self.graphic_map, graphic_id, dims)?; - // Transfer to the gpu - upload_image(renderer, aabr, &self.textures[idx], &image); + // Check if the cached version has been invalidated by replacing the underlying + // graphic + if !details.valid { + // Create image + let image = draw_graphic(&self.graphic_map, graphic_id, dims)?; + // Transfer to the gpu + upload_image(renderer, aabr, &self.textures[idx], &image); + } + + return Some((transformed_aabr(aabr.map(|e| e as f64)), TexId(idx))); + }, + Entry::Vacant(details) => details, + }; + + // Create image + let image = draw_graphic(&self.graphic_map, graphic_id, dims)?; + + // Allocate space on the gpu + // Check size of graphic + // Graphics over a particular size are sent to their own textures + let location = if Vec2::::from(self.atlases[0].0.size().to_tuple()) + .map(|e| e as u16) + .map2(dims, |a, d| a as f32 * ATLAS_CUTTOFF_FRAC >= d as f32) + .reduce_and() + { + // Fit into an atlas + let mut loc = None; + for (atlas_idx, (ref mut atlas, _)) in self.atlases.iter_mut().enumerate() { + if let Some(rectangle) = atlas.allocate(size2(i32::from(dims.x), i32::from(dims.y))) + { + let aabr = aabr_from_alloc_rect(rectangle); + loc = Some(CacheLoc::Atlas { atlas_idx, aabr }); + break; + } } - Some((rotated_aabr(aabr), TexId(idx))) - } else { - // Create image - let image = draw_graphic(&self.graphic_map, graphic_id, dims)?; - - // Allocate space on the gpu - // Check size of graphic - // Graphics over a particular size are sent to their own textures - let location = if Vec2::::from(self.atlases[0].0.size().to_tuple()) - .map(|e| e as u16) - .map2(dims, |a, d| a as f32 * ATLAS_CUTTOFF_FRAC >= d as f32) - .reduce_and() - { - // Fit into an atlas - let mut loc = None; - for (atlas_idx, (ref mut atlas, _)) in self.atlases.iter_mut().enumerate() { - if let Some(rectangle) = - atlas.allocate(size2(i32::from(dims.x), i32::from(dims.y))) - { - let aabr = aabr_from_alloc_rect(rectangle); - loc = Some(CacheLoc::Atlas { atlas_idx, aabr }); - break; - } - } - - match loc { - Some(loc) => loc, - // Create a new atlas - None => { - let (mut atlas, texture) = create_atlas_texture(renderer); - let aabr = atlas - .allocate(size2(i32::from(dims.x), i32::from(dims.y))) - .map(aabr_from_alloc_rect) - .unwrap(); - let tex_idx = self.textures.len(); - let atlas_idx = self.atlases.len(); - self.textures.push(texture); - self.atlases.push((atlas, tex_idx)); - CacheLoc::Atlas { atlas_idx, aabr } - }, - } - } else { - // Create a texture just for this - let texture = renderer.create_dynamic_texture(dims).unwrap(); - let index = self.textures.len(); - self.textures.push(texture); - CacheLoc::Texture { index } - }; - - let (idx, aabr) = match location { - CacheLoc::Atlas { - atlas_idx, aabr, .. - } => (self.atlases[atlas_idx].1, aabr), - CacheLoc::Texture { index } => { - (index, Aabr { - min: Vec2::new(0, 0), - // Note texture should always match the cached dimensions - max: dims, - }) + match loc { + Some(loc) => loc, + // Create a new atlas + None => { + let (mut atlas, texture) = create_atlas_texture(renderer); + let aabr = atlas + .allocate(size2(i32::from(dims.x), i32::from(dims.y))) + .map(aabr_from_alloc_rect) + .unwrap(); + let tex_idx = self.textures.len(); + let atlas_idx = self.atlases.len(); + self.textures.push(texture); + self.atlases.push((atlas, tex_idx)); + CacheLoc::Atlas { atlas_idx, aabr } }, - }; - // Upload - upload_image(renderer, aabr, &self.textures[idx], &image); - // Insert into cached map - self.cache_map.insert(key, CachedDetails { - location, - valid: true, - }); + } + } else { + // Create a texture just for this + let texture = renderer.create_dynamic_texture(dims).unwrap(); + let index = self.textures.len(); + self.textures.push(texture); + CacheLoc::Texture { index } + }; - Some((rotated_aabr(aabr), TexId(idx))) - } + let (idx, aabr) = match location { + CacheLoc::Atlas { + atlas_idx, aabr, .. + } => (self.atlases[atlas_idx].1, aabr), + CacheLoc::Texture { index } => { + (index, Aabr { + min: Vec2::new(0, 0), + // Note texture should always match the cached dimensions + max: dims, + }) + }, + }; + // Upload + upload_image(renderer, aabr, &self.textures[idx], &image); + // Insert into cached map + details.insert(CachedDetails { + location, + valid: true, + }); + + Some((transformed_aabr(aabr.map(|e| e as f64)), TexId(idx))) } } diff --git a/voxygen/src/ui/img_ids.rs b/voxygen/src/ui/img_ids.rs index bf18a99ed8..f3cfc0f65f 100644 --- a/voxygen/src/ui/img_ids.rs +++ b/voxygen/src/ui/img_ids.rs @@ -106,6 +106,8 @@ pub struct Rotations { pub cw90: conrod_core::image::Id, pub cw180: conrod_core::image::Id, pub cw270: conrod_core::image::Id, + pub source_north: conrod_core::image::Id, + pub target_north: conrod_core::image::Id, } /// This macro will automatically load all specified assets, get the diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 598040080d..a384c77078 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -28,6 +28,7 @@ use crate::{ window::Window, Error, }; +use ::image::GenericImageView; use cache::Cache; use common::{assets, util::srgba_to_linear}; use conrod_core::{ @@ -43,6 +44,7 @@ use conrod_core::{ use graphic::{Rotation, TexId}; use log::{error, warn}; use std::{ + f32, f64, fs::File, io::{BufReader, Read}, ops::Range, @@ -172,6 +174,16 @@ impl Ui { cw90: self.image_map.insert((graphic_id, Rotation::Cw90)), cw180: self.image_map.insert((graphic_id, Rotation::Cw180)), cw270: self.image_map.insert((graphic_id, Rotation::Cw270)), + // Hacky way to make sure a source rectangle always faces north regardless of player + // orientation. + // This is an easy way to get around Conrod's lack of rotation data for images (for this + // specific use case). + source_north: self.image_map.insert((graphic_id, Rotation::SourceNorth)), + // Hacky way to make sure a target rectangle always faces north regardless of player + // orientation. + // This is an easy way to get around Conrod's lack of rotation data for images (for this + // specific use case). + target_north: self.image_map.insert((graphic_id, Rotation::TargetNorth)), } } @@ -420,46 +432,88 @@ impl Ui { PrimitiveKind::Image { image_id, color, - source_rect: _, // TODO: <-- use this + source_rect, } => { let (graphic_id, rotation) = self .image_map .get(&image_id) .expect("Image does not exist in image map"); let graphic_cache = self.cache.graphic_cache_mut(); - - match graphic_cache.get_graphic(*graphic_id) { - Some(Graphic::Blank) | None => continue, - _ => {}, - } + let gl_aabr = gl_aabr(rect); + let (source_aabr, gl_size) = { + // Transform the source rectangle into uv coordinate. + // TODO: Make sure this is right. Especially the conversions. + let ((uv_l, uv_r, uv_b, uv_t), gl_size) = + match graphic_cache.get_graphic(*graphic_id) { + Some(Graphic::Blank) | None => continue, + Some(Graphic::Image(image)) => { + source_rect.and_then(|src_rect| { + let (image_w, image_h) = image.dimensions(); + let (source_w, source_h) = src_rect.w_h(); + let gl_size = gl_aabr.size(); + if image_w == 0 + || image_h == 0 + || source_w < 1.0 + || source_h < 1.0 + || gl_size.reduce_partial_max() < f32::EPSILON + { + None + } else { + // Multiply drawn image size by ratio of original image + // size to + // source rectangle size (since as the proportion of the + // image gets + // smaller, the drawn size should get bigger), up to the + // actual + // size of the original image. + let ratio_x = (image_w as f64 / source_w).min( + (image_w as f64 / (gl_size.w * half_res.x) as f64) + .max(1.0), + ); + let ratio_y = (image_h as f64 / source_h).min( + (image_h as f64 / (gl_size.h * half_res.y) as f64) + .max(1.0), + ); + let (l, r, b, t) = src_rect.l_r_b_t(); + Some(( + ( + l / image_w as f64, /* * ratio_x*/ + r / image_w as f64, /* * ratio_x*/ + b / image_h as f64, /* * ratio_y*/ + t / image_h as f64, /* * ratio_y*/ + ), + Extent2::new( + (gl_size.w as f64 * ratio_x) as f32, + (gl_size.h as f64 * ratio_y) as f32, + ), + )) + /* ((l / image_w as f64), + (r / image_w as f64), + (b / image_h as f64), + (t / image_h as f64)) */ + } + }) + }, + // No easy way to interpret source_rect for voxels... + Some(Graphic::Voxel(..)) => None, + } + .unwrap_or_else(|| ((0.0, 1.0, 0.0, 1.0), gl_aabr.size())); + ( + Aabr { + min: Vec2::new(uv_l, uv_b), + max: Vec2::new(uv_r, uv_t), + }, + gl_size, + ) + }; let color = srgba_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into()); - let gl_aabr = gl_aabr(rect); let resolution = Vec2::new( - (gl_aabr.size().w * half_res.x).round() as u16, - (gl_aabr.size().h * half_res.y).round() as u16, + (gl_size.w * half_res.x).round() as u16, + (gl_size.h * half_res.y).round() as u16, ); - // Transform the source rectangle into uv coordinate. - // TODO: Make sure this is right. - let source_aabr = { - let (uv_l, uv_r, uv_b, uv_t) = (0.0, 1.0, 0.0, 1.0); - /*match source_rect { - Some(src_rect) => { - let (l, r, b, t) = src_rect.l_r_b_t(); - ((l / image_w) as f32, - (r / image_w) as f32, - (b / image_h) as f32, - (t / image_h) as f32) - } - None => (0.0, 1.0, 0.0, 1.0), - };*/ - Aabr { - min: Vec2::new(uv_l, uv_b), - max: Vec2::new(uv_r, uv_t), - } - }; // Cache graphic at particular resolution. let (uv_aabr, tex_id) = match graphic_cache.cache_res( @@ -500,7 +554,13 @@ impl Ui { State::Image(_) => {}, } - mesh.push_quad(create_ui_quad(gl_aabr, uv_aabr, color, UiMode::Image)); + mesh.push_quad(create_ui_quad(gl_aabr, uv_aabr, color, match *rotation { + Rotation::None | Rotation::Cw90 | Rotation::Cw180 | Rotation::Cw270 => { + UiMode::Image + }, + Rotation::SourceNorth => UiMode::ImageSourceNorth, + Rotation::TargetNorth => UiMode::ImageTargetNorth, + })); }, PrimitiveKind::Text { color, diff --git a/world/src/sim/map.rs b/world/src/sim/map.rs index 5737c8370c..0707abd0d6 100644 --- a/world/src/sim/map.rs +++ b/world/src/sim/map.rs @@ -239,6 +239,9 @@ impl MapConfig { } } + let water_color_factor = 2.0; + let g_water = 32.0 * water_color_factor; + let b_water = 64.0 * water_color_factor; let rgba = match (river_kind, (is_water, true_alt >= true_sea_level)) { (_, (false, _)) | (None, (_, true)) => { let (r, g, b) = ( @@ -251,7 +254,7 @@ impl MapConfig { 0.0 }) .sqrt(), - if is_shaded { 0.2 + (alt * 0.8) } else { alt }, + if is_shaded { 0.4 + (alt * 0.6) } else { alt }, (if is_shaded { alt } else { alt } * if is_humidity { humidity as f64 @@ -272,17 +275,22 @@ impl MapConfig { }, (Some(RiverKind::Ocean), _) => ( 0, - ((32.0 - water_depth * 32.0) * 1.0) as u8, - ((64.0 - water_depth * 64.0) * 1.0) as u8, + ((g_water - water_depth * g_water) * 1.0) as u8, + ((b_water - water_depth * b_water) * 1.0) as u8, + 255, + ), + (Some(RiverKind::River { .. }), _) => ( + 0, + g_water as u8 + (alt * (127.0 - g_water)) as u8, + b_water as u8 + (alt * (255.0 - b_water)) as u8, 255, ), - (Some(RiverKind::River { .. }), _) => { - (0, 32 + (alt * 95.0) as u8, 64 + (alt * 191.0) as u8, 255) - }, (None, _) | (Some(RiverKind::Lake { .. }), _) => ( 0, - (((32.0 + water_alt * 95.0) + (-water_depth * 32.0)) * 1.0) as u8, - (((64.0 + water_alt * 191.0) + (-water_depth * 64.0)) * 1.0) as u8, + (((g_water + water_alt * (127.0 - 32.0)) + (-water_depth * g_water)) * 1.0) + as u8, + (((b_water + water_alt * (255.0 - b_water)) + (-water_depth * b_water)) + * 1.0) as u8, 255, ), }; diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 594e158696..ea945ae27a 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -292,6 +292,9 @@ impl WorldFile { pub struct WorldSim { pub seed: u32, + /// Maximum height above sea level of any chunk in the map (not including + /// post-erosion warping, cliffs, and other things like that). + pub max_height: f32, pub(crate) chunks: Vec, pub(crate) locations: Vec, @@ -1288,6 +1291,7 @@ impl WorldSim { let mut this = Self { seed, + max_height: maxh as f32, chunks, locations: Vec::new(), gen_ctx, @@ -1306,7 +1310,11 @@ impl WorldSim { pub fn get_map(&self) -> Vec { let mut v = vec![0u32; WORLD_SIZE.x * WORLD_SIZE.y]; // TODO: Parallelize again. - MapConfig::default().generate(&self, |pos, (r, g, b, a)| { + MapConfig { + gain: self.max_height, + ..MapConfig::default() + } + .generate(&self, |pos, (r, g, b, a)| { v[pos.y * WORLD_SIZE.x + pos.x] = u32::from_le_bytes([r, g, b, a]); }); v