From 7e8781024bf7985c1d284c12c879820efc9d080d Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 2 Mar 2019 17:41:34 -0500 Subject: [PATCH 01/72] quadruped testing Former-commit-id: 50340b74d803ec84b6af43ae6d787d72bf2c2d57 --- voxygen/src/anim/character/mod.rs | 18 ++++++------ voxygen/src/anim/character/run.rs | 36 +++++++++++++----------- voxygen/src/scene/mod.rs | 46 ++++++++----------------------- 3 files changed, 40 insertions(+), 60 deletions(-) diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 367cdf32ed..06850b38dc 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -15,10 +15,10 @@ use super::{ pub struct CharacterSkeleton { head: Bone, chest: Bone, - belt: Bone, - shorts: Bone, - l_hand: Bone, + bl_foot: Bone, + br_foot: Bone, r_hand: Bone, + l_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -29,10 +29,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - belt: Bone::default(), - shorts: Bone::default(), - l_hand: Bone::default(), + br_foot: Bone::default(), + bl_foot: Bone::default(), r_hand: Bone::default(), + l_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -47,10 +47,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.belt.compute_base_matrix()), - FigureBoneData::new(self.shorts.compute_base_matrix()), - FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.bl_foot.compute_base_matrix()), + FigureBoneData::new(self.br_foot.compute_base_matrix()), FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.l_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 015feb8d89..3ad70cb68b 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -21,30 +21,34 @@ impl Animation for RunAnimation { time: f64, ) { let wave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 12.0).cos(); let wave_slow = (time as f32 * 6.0 + PI).sin(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); - skeleton.head.offset = Vec3::unit_z() * 13.0; - skeleton.head.ori = Quaternion::rotation_z(wave * 0.3); + skeleton.head.offset = Vec3::new(0.0, 0.0, 0.0); + skeleton.head.ori = Quaternion::rotation_x(0.0); - skeleton.chest.offset = Vec3::unit_z() * 9.0; - skeleton.chest.ori = Quaternion::rotation_z(wave * 0.3); + skeleton.chest.offset = Vec3::new(0.0, 0.0, 0.0); + skeleton.chest.ori = Quaternion::rotation_x(0.0); - skeleton.belt.offset = Vec3::unit_z() * 7.0; - skeleton.belt.ori = Quaternion::rotation_z(wave * 0.2); + //skeleton.br_foot.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0); + //skeleton.br_foot.ori = Quaternion::rotation_x(0.0 + wave_slow * 10.1); - skeleton.shorts.offset = Vec3::unit_z() * 4.0; - skeleton.shorts.ori = Quaternion::rotation_z(wave * 0.1); + skeleton.bl_foot.offset = Vec3::new(0.0, 0.0, 80.0); + skeleton.bl_foot.ori = Quaternion::rotation_x(wave_slow * 2.0); + //skeleton.bl_foot.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0); + //skeleton.bl_foot.ori = Quaternion::rotation_x(0.5 + wave_slow * 0.1); - skeleton.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0); - skeleton.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0); + //skeleton.r_hand.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0); + //skeleton.r_hand.ori = Quaternion::rotation_x(0.5 + wave_slow * 0.1); + + skeleton.l_hand.offset = Vec3::new(0.0, 0.0, 0.0); + skeleton.l_hand.ori = Quaternion::rotation_x(wave_slow * 2.0); + + //skeleton.l_hand.offset = Vec3::new(0.0, wavecos_slow * 1.0, wave_slow * 2.0 + wave_dip * 1.0); + //skeleton.l_hand.ori = Quaternion::rotation_x(0.5 + wave_slow * 0.1); - skeleton.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0); - skeleton.l_foot.ori = Quaternion::rotation_x(-wave + 1.0); - skeleton.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0); - skeleton.r_foot.ori = Quaternion::rotation_x(wave + 1.0); - skeleton.back.offset = Vec3::new(-9.0, 5.0, 18.0); - skeleton.back.ori = Quaternion::rotation_y(2.5); } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index f62fc2b8c8..5792d30ac7 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -7,8 +7,8 @@ use vek::*; use dot_vox; // Project +use common::figure::Segment; use client::Client; -use common::{comp::phys::Pos as PosComp, figure::Segment}; // Crate use crate::{ @@ -82,15 +82,12 @@ impl Scene { test_figure: Figure::new( renderer, [ - Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -5.5, -1.0))), - Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))), - Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))), + Some(load_segment("dragonhead.vox").generate_mesh(Vec3::new(2.0, -12.0, 2.0))), + Some(load_segment("dragon_body.vox").generate_mesh(Vec3::new(0.0, 0.0, 0.0))), + Some(load_segment("dragon_lfoot.vox").generate_mesh(Vec3::new(10.0, 10.0, -80.0))), + Some(load_segment("dragon_rfoot.vox").generate_mesh(Vec3::new(0.0, 10.0, -4.0))), + Some(load_segment("dragon_rfoot.vox").generate_mesh(Vec3::new(0.0, -10.0, -4.0))), + Some(load_segment("dragon_lfoot.vox").generate_mesh(Vec3::new(0.0, 0.0, 0.0))), None, None, None, @@ -98,6 +95,9 @@ impl Scene { None, None, None, + None, + None, + None, ], CharacterSkeleton::new(), ) @@ -138,22 +138,6 @@ impl Scene { /// Maintain data such as GPU constant buffers, models, etc. To be called once per tick. pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) { - // Get player position - let player_pos = match client.player() { - Some(entity) => { - client - .state() - .ecs_world() - .read_storage::() - .get(entity) - .expect("There was no position component on the player entity!") - .0 - } - None => Vec3::default(), - }; - // Alter camera position to match player - self.camera.set_focus_pos(player_pos); - // Compute camera matrices let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents(); @@ -177,15 +161,7 @@ impl Scene { &mut self.test_figure.skeleton, client.state().get_time(), ); - - // Calculate entity model matrix - let model_mat = Mat4::::translation_3d(player_pos); - //* Mat4::rotation_z(PI - entity.look_dir().x) - //* Mat4::rotation_x(entity.look_dir().y); - - self.test_figure - .update_locals(renderer, FigureLocals::new(model_mat)) - .unwrap(); + self.test_figure.update_locals(renderer, FigureLocals::default()).unwrap(); self.test_figure.update_skeleton(renderer).unwrap(); } From 608423f09f1fda3aaaf76c0f75f8ea3edc86ad1a Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 2 Mar 2019 18:05:21 -0500 Subject: [PATCH 02/72] adding test assets Former-commit-id: fc56d4d1bc9f9ea9b40dc42f600e164d11e2eb40 --- voxygen/test_assets/body.vox | Bin 0 -> 6984 bytes voxygen/test_assets/dragon_body.vox | Bin 0 -> 9540 bytes voxygen/test_assets/dragon_lfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_rfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_tail.vox | Bin 0 -> 2080 bytes voxygen/test_assets/dragon_wingL_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingL_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragon_wingR_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingR_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragonhead.vox | Bin 0 -> 3040 bytes voxygen/test_assets/foot_BL.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_BR.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_FL.vox | Bin 0 -> 1192 bytes voxygen/test_assets/foot_FR.vox | Bin 0 -> 1192 bytes voxygen/test_assets/lionhead.vox | Bin 0 -> 5164 bytes voxygen/test_assets/sabremale.vox | Bin 0 -> 7436 bytes 16 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 voxygen/test_assets/body.vox create mode 100644 voxygen/test_assets/dragon_body.vox create mode 100644 voxygen/test_assets/dragon_lfoot.vox create mode 100644 voxygen/test_assets/dragon_rfoot.vox create mode 100644 voxygen/test_assets/dragon_tail.vox create mode 100644 voxygen/test_assets/dragon_wingL_in.vox create mode 100644 voxygen/test_assets/dragon_wingL_out.vox create mode 100644 voxygen/test_assets/dragon_wingR_in.vox create mode 100644 voxygen/test_assets/dragon_wingR_out.vox create mode 100644 voxygen/test_assets/dragonhead.vox create mode 100644 voxygen/test_assets/foot_BL.vox create mode 100644 voxygen/test_assets/foot_BR.vox create mode 100644 voxygen/test_assets/foot_FL.vox create mode 100644 voxygen/test_assets/foot_FR.vox create mode 100644 voxygen/test_assets/lionhead.vox create mode 100644 voxygen/test_assets/sabremale.vox diff --git a/voxygen/test_assets/body.vox b/voxygen/test_assets/body.vox new file mode 100644 index 0000000000000000000000000000000000000000..d6c7aa48dcc2c87e2cddbfa2b1ccb66f309a022f GIT binary patch literal 6984 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 IXVT@r0oGHx%>V!Z literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_lfoot.vox b/voxygen/test_assets/dragon_lfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..80828a713720e4be9d073de8f5282fa58a8c93bb GIT binary patch literal 1408 zcmchWZA@Eb6vxkV@9m4j7Z|0iFrjuZTA1Ud45%n`wkqoPZ3d|&EL&JZyJbt{XyU3((qzSoBqid*I2H`C7mUU^jlF7ABATA#{TlZ$iHs^SC=pfTdPYc0yq8hT zj7f>0smDtktem}y9PjD`fqB)w7NJ{q3`$0o`g+`FfZ z>-E*t)P#6Ejt7&3eOFeo&GH9+vsjSL1|Zipe;VCgH8_5>8S&vRq{sY7Paa2ldJv82 z2y(qv*pAs@f2#_vSr5o(0EIV!<~D;?t;h`!3QrTZP7ronCz!*8ClZ8w_SUO}`aljk zPv;^ynvV<1PopDF=t&Y@T_l`c^j}D(6d4d#eJ4{e-en z?mb0lSs~C%Jb%OtNWdKaIWW@W#MH?;#1A!M>Qp_oJ~gT6{DLiNQM z-&>BcpBgv;f^uFbo# zf8P=)F@l0<0hXs9zC-zrN=i!bc6kyt)q^;3@jSK+6yokz>--aI~3L9^3eOb_HCch)uY69m34AS^}IH!>yDW< SP({jXB)_ literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_rfoot.vox b/voxygen/test_assets/dragon_rfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..1e2bcfe32d72e45c57b712337b993ed77f354f69 GIT binary patch literal 1408 zcmc(eZA?>F7{{M`?(NHDFCeAZ;!0OR+T!G;2y`GTLZ=0bLuRKP65TYj>r6={M4M&{ zb~9s+jj;wKQ4tMci;*d5NtbeNq+f1 z|K~jCIp>~xZ)o2^`y>$s+XFo;^sbJmFA(-Wtr{L|X~W-o@K89=Dydl_wOHtsoX{&d zk|`%K;wd^Mj10#zqo{eoc}8YPVb2IgW)#)y*fX+`i6cvtzU?h$i zK{P~atVlT_OWd1Pkzx|7%qnwEVuXQndR9HFj#bBV>}6JAluikQU==ypAaat5BDfEG z6`hF52JXWMMdq{0IYq~Ly@)A#!79i9dbkD2;cjF{1ISJsMRsZs zP1zUz8Z3=&FD5;l($w%sHcql9NtgktvQ>x712 z0lH2WB0N%zkC&cDXOhsHCcL>oIJ3%Yd#$iV9H>aT(U|d}EN+5h%nJ8hIqL3Ip|qb+ zF~Yqk39ZWndX4u_7(wZ0L5n7gRuy5swgeA$mH}NaAWeiN<_G2%CViT)@C6}1Pq=%F zy^k>KC*<}M*54+C*`E#(#*cA+n9$)O3^WslI|&y!-`ikC#P2|&*NMsF^++CQ!sLk# z8uyWNgD zmjjL4x8kLG7sfx>jD;%>{CL-m_50Ph$a`ky2=~4v{QNy35pm)|%7c{~9r*31KE%%# zV(cpuZmn9dj`IKg`8^&FK5v>qP2DV7M$f{Mvf$2D!h<&m*PTwdTrTX`xD$K#EP_%A zl*CK0H1+r$?o|}nY&N`KnMQ5RAda0shfM>exc_w}mckZH@LfH5|7|T3TCYQW_Ygk; zoSB+O>RJY$F5brUcWc-&IEuEjGw8m&jJ}&|@cDdrL;x8X`~i85@bH_*=X=QC*MH6P zPl#&kE~wfj4Qd*!ifH$Ij`kOV literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_tail.vox b/voxygen/test_assets/dragon_tail.vox new file mode 100644 index 0000000000000000000000000000000000000000..050f21c65a3468e0a49993190171cc26cc9904a9 GIT binary patch literal 2080 zcmc(eYiO2r7{>qaY3}eIpVQp5x#npHQ|EMtrZx{tr%h9H=~B^Bat(2e5FNwNm9)$< z8&g4B7P3M#l}+C0gAEZ8L}W<>B_a`h?L$c4u71xW^}#QF?178>zW?`i-S_qU-{);x zyQy^07}L6>Wevf^bB)>1(%u~R3!Wkn136&R=Ju9fA|yPIL18$OEewZ2C|elvK_22P zLLMQHkcXo5K?H;hIfwuQ$G|agqU2HXXe2u^9LqZN9e56WkC+bfC@~B|*$j1tJsI|8 z*qdQ~hFuwUX4vha_s}~2IUY0UGUzNkSkxA^MQyXsVwTNr8xJ;KY&_X`vzcN0y})yf zI!X$2O$pUXav z+zVnjn+rD|B+(_&B$=5{KNm#c$A~!~N}dBR0xuTu`8~+fXwuXUz8(BKyoVQn9n=;a z3$GR&%fEB@mVXXE8q8uI-lHG_a_|+wcND||u!orDJ<|SN`oAOhV{tzg=N5Nl(X)7W zi@wDS%l~%hd;a~w^*HnB=fKPL!H#?%tIQJ9xeSQfO1?QtXJsEAYWt0sI2A1@QAZ z%L@?7=21uK<-y4#=5jv42lWK%3G^qR%i$~rlH|!CMzRU=1bG5p0xt=;3A`lmlE6!X z840{3@DhWwe#O!yCK~+BO?`d6dV72I=!DVAvo|%>`AdH~j>g7XI0FRHX;2R58>b(;SoO%$GT5$=vjmZZ#_0V>J1= z(X7ixxt&IdJ|mmjyI?fGwLq)(q}6`N)(6*~(ehrSbpuAPUotvy5AC{Qm2{M8T5qLl zN18OL+fmuEVpX1>qUu{SRk+1y+975S8ZEqTWL{x^Pp-^BQs%0o{+SsK&vkWw(Ijcr zvl=i)*T9e9H!!f@=+dV~W5Y(buTVD`oohDAt~Yw{rcpcf{x+lIJ2~HHw5-BtTfNb~ zhzxYierr zN!^g!Oii!#?uomg1l~-l@dgOMyx_0u(Z+NhnZ>OY0 z?@S-i+&Nv^dGv@TZY$K?Z>H;7dy!6XS5M#n;>Huftj!zlsC&0`;N-CSz8uj)LR6Tun_)dSoP%3-nl#aifRdKJoXE@9V$%{0mi8yi|T%9O?>U z>&%WIJ{M|KW@C4dPw)6Jh;1`Y2eBdC8$@5{KYna@<4_Q1oxUeKRiv6w$G^RQI8R0M EH>B;$0{{R3 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_in.vox b/voxygen/test_assets/dragon_wingL_in.vox new file mode 100644 index 0000000000000000000000000000000000000000..aa0a7eedb2afbf963d7ede5a3235f2f9b7bdf915 GIT binary patch literal 2884 zcmc)LTZ~m#9mnziz|5S>zMs9%KDW6s+-9JbYqw3=qN1qrvV`jUzj_)CCrDwKpd}4?1F8GY1i7q_x7SF)M<=D9PKCZY3H^0q`s_sX+X?Br z6VQLhXAF+VIGi$LaY~HGDKaLfz_^@V#^&@eKBt>8I`bK)Gmo(%?zVQ^!(2PP)($Z* zw{}-#{3MCJ=8BCQ|7*c3<;`;k+UulStCQTP6njU z`#u@C`6OE?qYoAC^^++%!1EsKF-Z1OH{|MB;|ek)s3Jzrx<{xXM8Nw2S#fJcHsPTK zpYz(sI|12GhU5VC1q>o(?^KW>K@}c*At!w@r0tMBR(0P&X4Ls)6CPS9^K2hV=tmI) zNE6ydh6Gi2%{=5}NJg$r+N-$lL4!T)bFT>xEtIM2BTHmIStL{Tc?B5~R1qU}ZMvkb zgmRs7L^jAWbxqPk%Uz=nB@~fzW-7=yHwjrKV=_mC8bZ_&pn;hAZjupgx5zR|D58Lr z^H)K}8B9<`j2sba2vJ9X27EN(p^OrW$T+_#s;D4G!nv-IF z-C*A}*dGnbb=I>^xlUb;^{w&yRpUA*D?FdDM-sQ5u1uRT<(Rf&>SLad9QI($J0a^B zavhL9^Y6i@98g!L{St~UIa@^(9L{ww9((wqt=4_-zi`8b4Vs>w)@P?okGyqD3$uUe zA6cfGH+Rc@-Wk8DJ-b%wnWr{s`p7O_JwC3hr=HQ(vu&-v`l8~oT#cuPH1x`Hjh^2q z+tDLCRF+++$Zq9|cbjT2nEFnd?t9l%JY))HOexp-+orX3Fs!d#nI4{Fz!M)chN^*XfEH1m|{{9)6LADh+sh%bp z8XD57(P6E-e~G@hdQ>OB*Qd)rAJ(5fT&BApFV~xV=j=t(N53=u-nl<{#`tw?`>Vh^Me^rf{hCcX(>634m-X0mz z=;){(s642zJaR=gb5zx-s;-^Aw}!7Y**gOR`tIV>TDhXFXJ3C!^@BBi{F}wPHqp>2 z=IZnFzh%>@xwf9%_mQTamtH=5Ni)BkRp-k4I`{iKdZ2w=TV6e{T|c{_eed4U*w~mp zGs%k3KQ;f3>C@ld>))sBum5$QQ>f+5hvafgS9>mZFP)srFLZ5E^7zzTdGX|r=5qg% nb91?I-t=6$_uR+j#%~>)%lppVRvI<5rfc%Q_x|(D=hFTSe|IGn literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_out.vox b/voxygen/test_assets/dragon_wingL_out.vox new file mode 100644 index 0000000000000000000000000000000000000000..879372f6d8d7af3fb5897159e1512c98499fe431 GIT binary patch literal 3544 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 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragonhead.vox b/voxygen/test_assets/dragonhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..0de9789f15d4495178dca869b50b40272cc46005 GIT binary patch literal 3040 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 S)HH5pGxbliZ6tnry!;FE;3mre literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_BR.vox b/voxygen/test_assets/foot_BR.vox new file mode 100644 index 0000000000000000000000000000000000000000..073a55c9e009ef5d5b79538af901e1f6f04bd83f GIT binary patch literal 1236 zcma)*e@L8l9LGP;^V~wR*)7lW$F1`^b-O!b?$q>5TW5N?d;GDSY1?fR7aMtqZ5$!n zaV)kg$%bW@=!BM8h{Tv}qEhsSlOba;#;_4V$QTj*+aD4A_v-t&KZmOiy!kwzpYQMI z^L)QO2M&2AM5Mhj+M$%(u!(d^&CU|Q%`A3D)^Q!lR(6A!Nn~Fb~g^cGQ3l2th?_h3k9`|2y zf%yXCA}lNXtnjk9bLT`j|LbNvgY+iT);5KYEKlX5*BXIBBRXru9`HCwpocFopCnVfsB` zh-NckutuUsYAbXSLH*1ZSupxj`wC!I& z(n<0Xc`Q#p`iJL=)ZKBrdB1F&ef1emTpXsLH=n!Tm9ZQvB;)Zswtp+n>UFs54vBs^ zJ2^-Cn?*iZxXILwbzV9>!oCaBw0^ll*R^%R;V=&cBujz6G1i3#KRi0$19iXtE3Tg4 W<~!R;Tfwbjmj6ky&Bjlzmwy2+<0jnz literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_FL.vox b/voxygen/test_assets/foot_FL.vox new file mode 100644 index 0000000000000000000000000000000000000000..23eab56821aed022d1485f7849650580a8a36cc5 GIT binary patch literal 1192 zcma)*Z%kWd6vofJWeE|7OiH0;mRewIiy12*6v0^pWWD^E48g722s13wG`OWPWNVt4 ztxCiNWwn7VaUvQ*%re|aOEi8!vXEuTvMjh56GN887{B_#7{C2|FZ0{N^d!%H?s?8V z=Y7w)?>lhdkZW2*x?4g$iX@#Q(iaN1KW#e7EdOGg;zNhSp0R-&NkIbG^us5e9O z90iMlZfLrML=!_aQ&+5OhNf8zUF5Q^bj^f_p=(-5Ghybdn5O9=O;^5dvZd=_$Ez)( z_G4Ng5Fn9A@GvFpzp_TT^>6;PT3KD~#%ow=oX4cg`HEv3)h9*sIWaL6e{0#RjBLE!x$|f ze6Em>mY<_7A@rt&w-$vn_f&4L182ldMZ!mYCP-<_ihI(5Z@vuwt=$wK6)MiD+S5Yw ziXd;O_2aonIv-iGGO>FH3ww*W|8gl9&yyBmS>Y#z-xSiPg~d;W)dk`94dn-gxpv{( zgTlt!LZm}DJs?a)Y>W>H(-C1XAdIyMmz3UH=OEJVCf@5|`a}(h{syK;T3P+@O@5z` zP*rZDxu%THS3H~;Xdr3`$z#IoyTZyRLcP;L$XCJ9`aQ(j8X54}h}4xb*-=Smu$uN} zKL=iGB>Z{{(V-sVC&NsA5GAuP&ic(Oq~39pI8sVpULGZdJE$%#!0&Zazh@UO)p(hD zeRwh(|nJO4hP=t(8B1=_7WbfXT0|+_-0FgEGQu z9-I9StGSE`t=_HsAMM)pSpUwFXYjd;@RjA$ z{ic%Tu$`34_1OH)@61|<`|c1Mfip7;B)`h=@zPB$|FF)BrzY5UewNP9SLnOGPB0kc rp@8Hn@E4YK;lX#0_V+-Yum6gxE4X>jwqi55Rm{|%6x%HP(yWrpBd!jLwE zjy9Xj6*rrO*upyJhR7&&tt7Is2PZ{Jp_Jmv7z`<8jJ@t*jJ^GKWA|3f7zz=p~KPQSUkr{1g^}{#$ zeLg}>rJ2^c3c6l#abmEEXh=vN6K3BPRz49L?N)-GDvmbpA=c5%pvO$4!Nyc)HQAwB z0o7nhRttX*s8k6-$UT`)5BwTT<|ENoCg zSj}Uz{}DBpaiQJ4b^l}CyB_P`Uj7UoXDObFVp`nA4EVM);Qjyo*Vor`v1yiC?;I_Y z=dmO$-1<_ue?++Ia^ZHn8Lb?rd;b!Wj8hsbWqIb&KRjzycgJq$z3MdkT2hQ$n4o;9 zjJw}dvmCaNayTBFe|}xQ*5Up;#75!F%mT@;vV6RBlgmG>^Wv#V_MM-l>+==*udn0x t`*|oJg$n+{ur56K?$P-ksQdL_arFc@-`Q3=AKWUI_dhANS@_BM@()`hBKH6Q literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/lionhead.vox b/voxygen/test_assets/lionhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..7d6727d68553a8bfa9c0b56db5003eab21bb2042 GIT binary patch literal 5164 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 E1MV8k_W%F@ literal 0 HcmV?d00001 From 858055b8c46a4ad8b4b033d32b753ded48325a30 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Mon, 15 Apr 2019 22:51:32 +0200 Subject: [PATCH 03/72] Error Window Former-commit-id: e58ba8be94bb6f6b39c713f44dec20089c20b348 --- voxygen/src/menu/main/mod.rs | 15 +++++++++------ voxygen/src/menu/main/ui.rs | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 7f12830ac5..983a2d41b5 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -60,7 +60,7 @@ impl PlayState for MainMenuState { global_state.window.renderer_mut().clear(BG_COLOR); // Poll client creation - match client_init.as_ref().and_then(|init| init.poll()) { + match client_init.as_ref().and_then(|init| init.poll()) { Some(Ok(client)) => { self.main_menu_ui.connected(); return PlayStateResult::Push(Box::new(CharSelectionState::new( @@ -70,11 +70,14 @@ impl PlayState for MainMenuState { } Some(Err(err)) => { client_init = None; - self.main_menu_ui.login_error(match err { - InitError::BadAddress(_) | InitError::NoAddress => "No such host is known", - InitError::ConnectionFailed(_) => "Could not connect to address", - }.to_string()); - }, + self.main_menu_ui.login_error( + match err { + InitError::BadAddress(_) | InitError::NoAddress => "Server not found", + InitError::ConnectionFailed(_) => "Connection failed", + } + .to_string(), + ); + } None => {} } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index c5e7f83504..ae8d053654 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -36,6 +36,8 @@ widget_ids! { servers_button, settings_button, quit_button, + // Error + error_frame, } } @@ -52,6 +54,8 @@ struct Imgs { button: ImgId, button_hover: ImgId, button_press: ImgId, + + error_frame: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { @@ -82,6 +86,9 @@ impl Imgs { button: load("element/buttons/button.png"), button_hover: load("element/buttons/button_hover.png"), button_press: load("element/buttons/button_press.png"), + + //Error + error_frame: load("element/frames/skin_eyes.png"), } } } @@ -203,20 +210,24 @@ impl MainMenuUi { // Login error if let Some(msg) = &self.login_error { let text = Text::new(&msg) - .rgba(0.5, 0.0, 0.0, 1.0) + .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); let x = match text.get_x_dimension(ui_widgets) { Dimension::Absolute(x) => x + 10.0, _ => 0.0, }; - Rectangle::fill([x, 40.0]) - .rgba(0.2, 0.3, 0.3, 0.7) + Rectangle::fill([x, 60.0]) + .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .up_from(self.ids.username_bg, 35.0) + .mid_bottom_with_margin_on(self.ids.username_bg, 0.0) .set(self.ids.login_error_bg, ui_widgets); text.middle_of(self.ids.login_error_bg) .set(self.ids.login_error, ui_widgets); + Image::new(self.imgs.error_frame) + .h(60.0) + .middle_of(self.ids.login_error) + .set(self.ids.error_frame, ui_widgets); } // Server address Image::new(self.imgs.input_bg) From 7ec6e093325a501330049a1f6fc01911acd54978 Mon Sep 17 00:00:00 2001 From: Louis Pearson Date: Wed, 17 Apr 2019 07:41:34 -0600 Subject: [PATCH 04/72] Add basic singleplayer support Former-commit-id: 929b05faca5d2b95a96349dfc17a62b3165289a1 --- Cargo.lock | 1 + voxygen/.gitignore | 1 + voxygen/Cargo.toml | 1 + voxygen/src/menu/main/mod.rs | 7 ++++++ voxygen/src/menu/main/singleplayer.rs | 36 +++++++++++++++++++++++++++ voxygen/src/menu/main/ui.rs | 15 ++++++++++- 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 voxygen/src/menu/main/singleplayer.rs diff --git a/Cargo.lock b/Cargo.lock index 6777d2e7e4..1a1ab9e19a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1960,6 +1960,7 @@ dependencies = [ "vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", "veloren-client 0.2.0", "veloren-common 0.2.0", + "veloren-server 0.2.0", "winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/voxygen/.gitignore b/voxygen/.gitignore index 693699042b..4fb75fb34b 100644 --- a/voxygen/.gitignore +++ b/voxygen/.gitignore @@ -1,3 +1,4 @@ /target **/*.rs.bk Cargo.lock +settings.toml diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 0db23602aa..4b9c11fa2b 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -12,6 +12,7 @@ default = ["gl"] [dependencies] common = { package = "veloren-common", path = "../common" } client = { package = "veloren-client", path = "../client" } +server = { package = "veloren-server", path = "../server" } # Graphics gfx = "0.17" diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 7461b53066..a427890201 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -1,5 +1,6 @@ mod client_init; mod ui; +mod singleplayer; use super::char_selection::CharSelectionState; use crate::{ @@ -9,6 +10,7 @@ use crate::{ use client_init::{ClientInit, Error as InitError}; use common::{clock::Clock, comp}; use std::time::Duration; +use std::thread; use ui::{Event as MainMenuEvent, MainMenuUi}; use vek::*; @@ -100,6 +102,11 @@ impl PlayState for MainMenuState { ), ))); } + MainMenuEvent::StartSingleplayer => { + thread::spawn(move || { + singleplayer::run_server(); + }); + } MainMenuEvent::Quit => return PlayStateResult::Shutdown, } } diff --git a/voxygen/src/menu/main/singleplayer.rs b/voxygen/src/menu/main/singleplayer.rs new file mode 100644 index 0000000000..93f07030ec --- /dev/null +++ b/voxygen/src/menu/main/singleplayer.rs @@ -0,0 +1,36 @@ +use std::time::Duration; +use log::info; +use server::{Input, Event, Server}; +use common::clock::Clock; + +const TPS: u64 = 30; + +pub fn run_server() { + info!("Starting server-cli..."); + + // Set up an fps clock + let mut clock = Clock::new(); + + // Create server + let mut server = Server::new() + .expect("Failed to create server instance"); + + loop { + let events = server.tick(Input::default(), clock.get_last_delta()) + .expect("Failed to tick server"); + + for event in events { + match event { + Event::ClientConnected { entity } => info!("Client connected!"), + Event::ClientDisconnected { entity } => info!("Client disconnected!"), + Event::Chat { entity, msg } => info!("[Client] {}", msg), + } + } + + // Clean up the server after a tick + server.cleanup(); + + // Wait for the next tick + clock.tick(Duration::from_millis(1000 / TPS)); + } +} diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index c5e7f83504..da2551e0c5 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -91,6 +91,7 @@ pub enum Event { username: String, server_address: String, }, + StartSingleplayer, Quit, } @@ -172,6 +173,18 @@ impl MainMenuUi { }); }; } + + macro_rules! singleplayer { + () => { + self.login_error = None; + events.push(Event::StartSingleplayer); + events.push(Event::LoginAttempt { + username: "singleplayer".to_string(), + server_address: "localhost".to_string(), + }); + }; + } + const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); // Username // TODO: get a lower resolution and cleaner input_bg.png @@ -296,7 +309,7 @@ impl MainMenuUi { .set(self.ids.singleplayer_button, ui_widgets) .was_clicked() { - login!(); + singleplayer!(); } // Quit if Button::image(self.imgs.button) From 1ae18fecf87fc141a7942bc4ca8b8743d85d6c35 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 16:46:04 +0200 Subject: [PATCH 05/72] Change timeout to 20s Former-commit-id: dca0d08a06c27259cdaaf0138024f53c6c93d94e --- client/src/lib.rs | 2 +- server/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index bd9a7ae61f..3e0eeaa217 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -26,7 +26,7 @@ use common::{ msg::{ClientMsg, ServerMsg}, }; -const SERVER_TIMEOUT: f64 = 5.0; // Seconds +const SERVER_TIMEOUT: f64 = 20.0; // Seconds pub enum Event { Chat(String), diff --git a/server/src/lib.rs b/server/src/lib.rs index 9b43de8e82..0eb84959b5 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -25,7 +25,7 @@ use threadpool::ThreadPool; use vek::*; use world::World; -const CLIENT_TIMEOUT: f64 = 5.0; // Seconds +const CLIENT_TIMEOUT: f64 = 20.0; // Seconds pub enum Event { ClientConnected { entity: EcsEntity }, From 76adbec3bbce74fbf9e40ffd69fff4250dcf853e Mon Sep 17 00:00:00 2001 From: Louis Pearson Date: Wed, 17 Apr 2019 08:57:23 -0600 Subject: [PATCH 06/72] Add method to drop singleplayer thread Former-commit-id: b62a90728d4e83a005687538e134cee427491052 --- voxygen/src/main.rs | 7 +++- voxygen/src/menu/main/mod.rs | 6 +-- voxygen/src/{menu/main => }/singleplayer.rs | 45 ++++++++++++++++++++- 3 files changed, 52 insertions(+), 6 deletions(-) rename voxygen/src/{menu/main => }/singleplayer.rs (53%) diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index b31bef5e61..ccb2ea0804 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -13,12 +13,14 @@ pub mod session; pub mod ui; pub mod window; pub mod settings; +pub mod singleplayer; // Reexports pub use crate::error::Error; // Standard use std::mem; +use std::thread; // Library use log; @@ -28,13 +30,15 @@ use pretty_env_logger; use crate::{ menu::main::MainMenuState, window::Window, - settings::Settings + settings::Settings, + singleplayer::Singleplayer, }; /// A type used to store state that is shared between all play states pub struct GlobalState { settings: Settings, window: Window, + singleplayer: Option, } impl GlobalState { @@ -88,6 +92,7 @@ fn main() { let mut global_state = GlobalState { settings, window, + singleplayer: None, }; // Set up the initial play state diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index a427890201..05412179d2 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -1,11 +1,11 @@ mod client_init; mod ui; -mod singleplayer; use super::char_selection::CharSelectionState; use crate::{ window::{Event, Window}, GlobalState, PlayState, PlayStateResult, + singleplayer::Singleplayer, }; use client_init::{ClientInit, Error as InitError}; use common::{clock::Clock, comp}; @@ -103,9 +103,7 @@ impl PlayState for MainMenuState { ))); } MainMenuEvent::StartSingleplayer => { - thread::spawn(move || { - singleplayer::run_server(); - }); + global_state.singleplayer = Some(Singleplayer::new()); } MainMenuEvent::Quit => return PlayStateResult::Shutdown, } diff --git a/voxygen/src/menu/main/singleplayer.rs b/voxygen/src/singleplayer.rs similarity index 53% rename from voxygen/src/menu/main/singleplayer.rs rename to voxygen/src/singleplayer.rs index 93f07030ec..11cfa45da2 100644 --- a/voxygen/src/menu/main/singleplayer.rs +++ b/voxygen/src/singleplayer.rs @@ -2,10 +2,45 @@ use std::time::Duration; use log::info; use server::{Input, Event, Server}; use common::clock::Clock; +use std::{ + thread, + thread::JoinHandle +}; +use std::sync::mpsc::{ + channel, Receiver, Sender +}; const TPS: u64 = 30; -pub fn run_server() { +enum Msg { + Stop, +} + +pub struct Singleplayer { + server_thread: JoinHandle<()>, + sender: Sender, +} + +impl Singleplayer { + pub fn new() -> Self { + let (sender, reciever) = channel(); + let thread = thread::spawn(move || { + run_server(reciever); + }); + Singleplayer { + server_thread: thread, + sender, + } + } +} + +impl Drop for Singleplayer { + fn drop(&mut self) { + self.sender.send(Msg::Stop); + } +} + +fn run_server(rec: Receiver) { info!("Starting server-cli..."); // Set up an fps clock @@ -30,6 +65,14 @@ pub fn run_server() { // Clean up the server after a tick server.cleanup(); + match rec.try_recv() { + Ok(msg) => break, + Err(err) => match err { + Empty => (), + Disconnected => break, + }, + } + // Wait for the next tick clock.tick(Duration::from_millis(1000 / TPS)); } From a87cdc1993ff43fc6c0b0d97a6b2e89f824ce286 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 17 Apr 2019 14:23:34 +0100 Subject: [PATCH 07/72] Changed default server address to 'server.veloren.net' Former-commit-id: 660083d3d7ca341428b8c3cd8d54dd3ac1f453ab --- voxygen/src/main.rs | 3 +++ voxygen/src/menu/main/ui.rs | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/voxygen/src/main.rs b/voxygen/src/main.rs index b31bef5e61..ffd3e9c593 100644 --- a/voxygen/src/main.rs +++ b/voxygen/src/main.rs @@ -31,6 +31,9 @@ use crate::{ settings::Settings }; +/// The URL of the default public server that Voxygen will connect to +const DEFAULT_PUBLIC_SERVER: &'static str = "server.veloren.net"; + /// A type used to store state that is shared between all play states pub struct GlobalState { settings: Settings, diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index c5e7f83504..b20266a93c 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -1,4 +1,5 @@ use crate::{ + DEFAULT_PUBLIC_SERVER, render::Renderer, ui::{self, ScaleMode, Ui}, window::Window, @@ -137,7 +138,7 @@ impl MainMenuUi { font_metamorph, font_opensans, username: "Username".to_string(), - server_address: "veloren.mac94.de".to_string(), + server_address: DEFAULT_PUBLIC_SERVER.to_string(), login_error: None, connecting: None, } From a768971c6c92f3b024e9614369e92f04d3eaf807 Mon Sep 17 00:00:00 2001 From: Louis Pearson Date: Wed, 17 Apr 2019 09:22:26 -0600 Subject: [PATCH 08/72] Stop singleplayer thread whenever a session is left Former-commit-id: 16fcf35cbc856bebc12944781c2ac1a4daab5550 --- voxygen/src/menu/char_selection/mod.rs | 10 ++++++++-- voxygen/src/session.rs | 10 ++++++++-- voxygen/src/singleplayer.rs | 8 +++++--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 3ba0130622..04504bb6c6 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -45,7 +45,10 @@ impl PlayState for CharSelectionState { // Handle window events for event in global_state.window.fetch_events() { match event { - Event::Close => return PlayStateResult::Shutdown, + Event::Close => { + global_state.singleplayer = None; + return PlayStateResult::Shutdown; + }, // Pass events to ui Event::Ui(event) => { self.char_selection_ui.handle_event(event); @@ -60,7 +63,10 @@ impl PlayState for CharSelectionState { // Maintain the UI for event in self.char_selection_ui.maintain(global_state.window.renderer_mut()) { match event { - ui::Event::Logout => return PlayStateResult::Pop, + ui::Event::Logout => { + global_state.singleplayer = None; + return PlayStateResult::Pop; + }, ui::Event::Play => return PlayStateResult::Push( Box::new(SessionState::new(&mut global_state.window, self.client.clone())) ), diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index fc9ec54126..46003c7278 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -125,7 +125,10 @@ impl PlayState for SessionState { continue; } let _handled = match event { - Event::Close => return PlayStateResult::Shutdown, + Event::Close => { + global_state.singleplayer = None; + return PlayStateResult::Shutdown; + }, // Toggle cursor grabbing Event::KeyDown(Key::ToggleCursor) => { global_state @@ -166,7 +169,10 @@ impl PlayState for SessionState { self.client.borrow_mut().send_chat(msg); }, HudEvent::Logout => return PlayStateResult::Pop, - HudEvent::Quit => return PlayStateResult::Shutdown, + HudEvent::Quit => { + global_state.singleplayer = None; + return PlayStateResult::Shutdown; + }, } } diff --git a/voxygen/src/singleplayer.rs b/voxygen/src/singleplayer.rs index 11cfa45da2..735834e0ee 100644 --- a/voxygen/src/singleplayer.rs +++ b/voxygen/src/singleplayer.rs @@ -7,7 +7,7 @@ use std::{ thread::JoinHandle }; use std::sync::mpsc::{ - channel, Receiver, Sender + channel, Receiver, Sender, TryRecvError, }; const TPS: u64 = 30; @@ -16,6 +16,8 @@ enum Msg { Stop, } +/// Used to start and stop the background thread running the server +/// when in singleplayer mode. pub struct Singleplayer { server_thread: JoinHandle<()>, sender: Sender, @@ -68,8 +70,8 @@ fn run_server(rec: Receiver) { match rec.try_recv() { Ok(msg) => break, Err(err) => match err { - Empty => (), - Disconnected => break, + TryRecvError::Empty => (), + TryRecvError::Disconnected => break, }, } From b9607ef405b975edb7206ed5039369c43c8133bf Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 19:32:29 +0200 Subject: [PATCH 09/72] Fix #21 by checking animation history Former-commit-id: 5272d1d7aee73fc07edeb31d9f29238d19b7d229 --- client/src/lib.rs | 12 ++++++++---- common/src/comp/character.rs | 8 +++++++- common/src/comp/mod.rs | 1 + common/src/msg/client.rs | 2 +- common/src/msg/server.rs | 2 +- common/src/state.rs | 2 +- common/src/sys/control.rs | 24 ++++++++++++++++-------- server/src/lib.rs | 30 +++++++++++++++++++++++------- voxygen/src/scene/figure.rs | 6 +++--- 9 files changed, 61 insertions(+), 26 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 3e0eeaa217..291ec29fd8 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -168,8 +168,12 @@ impl Client { } // Update the server about the player's currently playing animation - if let Some(animation) = self.state.read_storage().get(self.player).cloned() { - self.postbox.send_message(ClientMsg::PlayerAnimation(animation)); + if let Some(animationHistory) = self.state.read_storage::().get(self.player).cloned() { + if let Some(last) = animationHistory.last { + if animationHistory.current != last { + self.postbox.send_message(ClientMsg::PlayerAnimation(animationHistory)); + } + } } // Request chunks from the server @@ -228,9 +232,9 @@ impl Client { }, None => {}, }, - ServerMsg::EntityAnimation { entity, animation } => match self.state.ecs().entity_from_uid(entity) { + ServerMsg::EntityAnimation { entity, animationHistory } => match self.state.ecs().entity_from_uid(entity) { Some(entity) => { - self.state.write_component(entity, animation); + self.state.write_component(entity, animationHistory); }, None => {}, }, diff --git a/common/src/comp/character.rs b/common/src/comp/character.rs index e34919236e..2ed29831f6 100644 --- a/common/src/comp/character.rs +++ b/common/src/comp/character.rs @@ -19,6 +19,12 @@ pub enum Gender { } #[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct AnimationHistory { + pub last: Option, + pub current: Animation, +} + +#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum Animation { Idle, Run, @@ -55,6 +61,6 @@ impl Component for Character { type Storage = FlaggedStorage>; } -impl Component for Animation { +impl Component for AnimationHistory { type Storage = FlaggedStorage>; } diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index c67f27cee2..d10012c976 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -7,4 +7,5 @@ pub mod phys; pub use agent::{Agent, Control}; pub use character::Character; pub use player::Player; +pub use character::AnimationHistory; pub use character::Animation; diff --git a/common/src/msg/client.rs b/common/src/msg/client.rs index 01c35a7962..95eaadecbf 100644 --- a/common/src/msg/client.rs +++ b/common/src/msg/client.rs @@ -11,7 +11,7 @@ pub enum ClientMsg { Ping, Pong, Chat(String), - PlayerAnimation(comp::character::Animation), + PlayerAnimation(comp::character::AnimationHistory), PlayerPhysics { pos: comp::phys::Pos, vel: comp::phys::Vel, diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 1585c5f32f..4b5a1b5517 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -25,7 +25,7 @@ pub enum ServerMsg { }, EntityAnimation { entity: u64, - animation: comp::Animation, + animationHistory: comp::AnimationHistory, }, TerrainChunkUpdate { key: Vec3, diff --git a/common/src/state.rs b/common/src/state.rs index 84a6736362..6a12cc6d7d 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -100,7 +100,7 @@ impl State { ecs.internal_mut().register::(); ecs.internal_mut().register::(); ecs.internal_mut().register::(); - ecs.internal_mut().register::(); + ecs.internal_mut().register::(); ecs.internal_mut().register::(); ecs.internal_mut().register::(); diff --git a/common/src/sys/control.rs b/common/src/sys/control.rs index a590e13c47..9179ea744a 100644 --- a/common/src/sys/control.rs +++ b/common/src/sys/control.rs @@ -3,7 +3,7 @@ use specs::{Join, Read, ReadStorage, System, WriteStorage, Entities}; use vek::*; // Crate -use crate::comp::{Control, Animation, phys::{Pos, Vel, Dir}}; +use crate::comp::{Control, Animation, AnimationHistory, phys::{Pos, Vel, Dir}}; // Basic ECS AI agent system pub struct Sys; @@ -13,7 +13,7 @@ impl<'a> System<'a> for Sys { Entities<'a>, WriteStorage<'a, Vel>, WriteStorage<'a, Dir>, - WriteStorage<'a, Animation>, + WriteStorage<'a, AnimationHistory>, ReadStorage<'a, Control>, ); @@ -23,12 +23,20 @@ impl<'a> System<'a> for Sys { // Apply physics to the player: acceleration and non-linear decceleration vel.0 += control.move_dir * 2.0 - vel.0.map(|e| e * e.abs() + e) * 0.03; - if control.move_dir.magnitude() > 0.01 { - dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0); - anims.insert(entity, Animation::Run); - } else { - anims.insert(entity, Animation::Idle); - } + let animation = + if control.move_dir.magnitude() > 0.01 { + dir.0 = vel.0.normalized() * Vec3::new(1.0, 1.0, 0.0); + Animation::Run + } else { + Animation::Idle + }; + + let lastAnimation = anims.get_mut(entity).map(|h| h.current); + + anims.insert(entity, AnimationHistory { + last: lastAnimation, + current: animation, + }); } } } diff --git a/server/src/lib.rs b/server/src/lib.rs index 0eb84959b5..ba7dd7ec8e 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -266,7 +266,7 @@ impl Server { ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong), ClientMsg::Pong => {} ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)), - ClientMsg::PlayerAnimation(animation) => state.write_component(entity, animation), + ClientMsg::PlayerAnimation(animationHistory) => state.write_component(entity, animationHistory), ClientMsg::PlayerPhysics { pos, vel, dir } => { state.write_component(entity, pos); state.write_component(entity, vel); @@ -369,15 +369,31 @@ impl Server { } // Sync animation states - for (entity, &uid, &animation) in ( + for (entity, &uid, &animationHistory) in ( &self.state.ecs().internal().entities(), &self.state.ecs().internal().read_storage::(), - &self.state.ecs().internal().read_storage::(), + &self.state.ecs().internal().read_storage::(), ).join() { - self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation { - entity: uid.into(), - animation, - }); + if let Some(last) = animationHistory.last { + if animationHistory.current == last { + continue; + } + + self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation { + entity: uid.into(), + animationHistory, + }); + } + } + + // Update animation last/current state + for (entity, mut animationHistory) in ( + &self.state.ecs().internal().entities(), + &mut self.state.ecs().internal().write_storage::() + ).join() { + animationHistory.last = None; + let mut new = animationHistory.clone(); + new.last = Some(new.current); } // Remove all force flags diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 75b727b07f..02089eb724 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -83,18 +83,18 @@ impl Figures { pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) { let time = client.state().get_time(); let ecs = client.state_mut().ecs_mut().internal_mut(); - for (entity, pos, dir, character, animation) in ( + for (entity, pos, dir, character, animationHistory) in ( &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), + &ecs.read_storage::(), ).join() { let state = self.states .entry(entity) .or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new())); - let target_skeleton = match animation { + let target_skeleton = match animationHistory.current { comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time), comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time), }; From abf32d622955bedf685475a1e8a9ce7fb0896651 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 19:41:20 +0200 Subject: [PATCH 10/72] Add comments Former-commit-id: 950c811256b8c20f58e4bb3c998acc746c4b929d --- client/src/lib.rs | 2 +- server/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 291ec29fd8..b2ad5904d5 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -167,7 +167,7 @@ impl Client { _ => {}, } - // Update the server about the player's currently playing animation + // Update the server about the player's currently playing animation and the previous one if let Some(animationHistory) = self.state.read_storage::().get(self.player).cloned() { if let Some(last) = animationHistory.last { if animationHistory.current != last { diff --git a/server/src/lib.rs b/server/src/lib.rs index ba7dd7ec8e..fd1e8fad5e 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -375,6 +375,7 @@ impl Server { &self.state.ecs().internal().read_storage::(), ).join() { if let Some(last) = animationHistory.last { + // Check if we need to sync if animationHistory.current == last { continue; } From 93fedf3b868ac0a0598dfb273ce92921cc814eaf Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 19:41:22 +0200 Subject: [PATCH 11/72] Rebase and Login Error Former-commit-id: 1865dd58d43ae0a7d78b61ca3a9684ca76fce02d --- voxygen/src/hud/chat.rs | 72 +++++++++++--------------- voxygen/src/hud/mod.rs | 1 - voxygen/src/menu/char_selection/mod.rs | 10 +--- voxygen/src/menu/main/client_init.rs | 4 +- voxygen/src/menu/main/mod.rs | 6 --- voxygen/src/menu/main/ui.rs | 57 ++++++++++---------- 6 files changed, 64 insertions(+), 86 deletions(-) diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index d9f770b4f8..ef6c3bdd83 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -1,11 +1,10 @@ use crate::ui::Ui; use conrod_core::{ - color, input::Key, position::Dimension, text::font::Id as FontId, widget::{Button, Id, List, Rectangle, Text, TextEdit}, - widget_ids, Colorable, Positionable, Sizeable, UiCell, Widget, + widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, }; use std::collections::VecDeque; @@ -85,59 +84,48 @@ impl Chat { // Chat input with rectangle as background let text_edit = TextEdit::new(&self.input) - .w(460.0) - .restrict_to_height(false) - .line_spacing(2.0) - .font_size(15) - .font_id(font); - let y = match text_edit.get_y_dimension(ui_widgets) { - Dimension::Absolute(y) => y + 6.0, - _ => 0.0, - }; - Rectangle::fill([470.0, y]) - .rgba(0.0, 0.0, 0.0, 0.8) - .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) .w(470.0) + .restrict_to_height(false) + .font_size(15) + .font_id(font) + .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0); + let dims = match ( + text_edit.get_x_dimension(ui_widgets), + text_edit.get_y_dimension(ui_widgets), + ) { + (Dimension::Absolute(x), Dimension::Absolute(y)) => [x, y], + _ => [0.0, 0.0], + }; + Rectangle::fill(dims) + .rgba(0.0, 0.0, 0.0, 0.8) + .x_position(text_edit.get_x_position(ui_widgets)) + .y_position(text_edit.get_y_position(ui_widgets)) .set(self.ids.input_bg, ui_widgets); - if let Some(str) = text_edit - .top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0) - .set(self.ids.input, ui_widgets) - { + if let Some(str) = text_edit.set(self.ids.input, ui_widgets) { self.input = str.to_string(); self.input.retain(|c| c != '\n'); } // Message box - Rectangle::fill([470.0, 174.0]) + Rectangle::fill([470.0, 167.0]) .rgba(0.0, 0.0, 0.0, 0.4) - .up_from(self.ids.input_bg, 0.0) + .up_from(self.ids.input, 0.0) .set(self.ids.message_box_bg, ui_widgets); - let (mut items, _) = List::flow_down(self.messages.len() + 1) - .top_left_of(self.ids.message_box_bg) - .w_h(470.0, 174.0) - .scroll_kids_vertically() + let (mut items, scrollbar) = List::flow_down(self.messages.len()) + .top_left_with_margins_on(self.ids.message_box_bg, 0.0, 5.0) + .w_h(460.0, 160.0) + .scrollbar_next_to() + .scrollbar_thickness(18.0) + .scrollbar_color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .set(self.ids.message_box, ui_widgets); while let Some(item) = items.next(ui_widgets) { - // This would be easier if conrod used the v-metrics from rusttype - let widget = if item.i < self.messages.len() { - let text = Text::new(&self.messages[item.i]) + item.set( + Text::new(&self.messages[item.i]) .font_size(15) .font_id(font) - .w(470.0) - .rgba(1.0, 1.0, 1.0, 1.0) - .line_spacing(2.0); - // Add space between messages - let y = match text.get_y_dimension(ui_widgets) { - Dimension::Absolute(y) => y + 2.0, - _ => 0.0, - }; - text.h(y) - } else { - // Spacer at bottom of the last message so that it is not cut off - // Needs to be larger than the space above - Text::new("").font_size(6).font_id(font).w(470.0) - }; - item.set(widget, ui_widgets); + .rgba(1.0, 1.0, 1.0, 1.0), + ui_widgets, + ) } // Chat Arrow diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index ecdf6508c9..2aea2e7c2b 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -515,7 +515,6 @@ impl Hud { Text::new( "Tab = Free Cursor \n\ Esc = Open/Close Menus \n\ - Q = Back to Login \n\ \n\ F1 = Toggle this Window \n\ F2 = Toggle Interface \n\ diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 04504bb6c6..3ba0130622 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -45,10 +45,7 @@ impl PlayState for CharSelectionState { // Handle window events for event in global_state.window.fetch_events() { match event { - Event::Close => { - global_state.singleplayer = None; - return PlayStateResult::Shutdown; - }, + Event::Close => return PlayStateResult::Shutdown, // Pass events to ui Event::Ui(event) => { self.char_selection_ui.handle_event(event); @@ -63,10 +60,7 @@ impl PlayState for CharSelectionState { // Maintain the UI for event in self.char_selection_ui.maintain(global_state.window.renderer_mut()) { match event { - ui::Event::Logout => { - global_state.singleplayer = None; - return PlayStateResult::Pop; - }, + ui::Event::Logout => return PlayStateResult::Pop, ui::Event::Play => return PlayStateResult::Push( Box::new(SessionState::new(&mut global_state.window, self.client.clone())) ), diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index 124939f957..25473bdabb 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -22,10 +22,10 @@ pub struct ClientInit { impl ClientInit { pub fn new( connection_args: (String, u16, bool), - client_args: (comp::Player, Option, Option, u64), + client_args: (comp::Player, Option, u64), ) -> Self { let (server_address, default_port, prefer_ipv6) = connection_args; - let (player, character, animation, view_distance) = client_args; + let (player, character, view_distance) = client_args; let (tx, rx) = channel(); diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 36d8781725..983a2d41b5 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -5,12 +5,10 @@ use super::char_selection::CharSelectionState; use crate::{ window::{Event, Window}, GlobalState, PlayState, PlayStateResult, - singleplayer::Singleplayer, }; use client_init::{ClientInit, Error as InitError}; use common::{clock::Clock, comp}; use std::time::Duration; -use std::thread; use ui::{Event as MainMenuEvent, MainMenuUi}; use vek::*; @@ -100,14 +98,10 @@ impl PlayState for MainMenuState { ( comp::Player::new(username.clone()), Some(comp::Character::test()), - Some(comp::Animation::Idle), 300, ), ))); } - MainMenuEvent::StartSingleplayer => { - global_state.singleplayer = Some(Singleplayer::new()); - } MainMenuEvent::Quit => return PlayStateResult::Shutdown, } } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 2ea5c7d0e9..cd839949e5 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -1,11 +1,12 @@ use crate::{ - DEFAULT_PUBLIC_SERVER, render::Renderer, ui::{self, ScaleMode, Ui}, window::Window, }; use common::assets; use conrod_core::{ + color, + color::BLACK, color::TRANSPARENT, image::Id as ImgId, position::{Dimension, Relative}, @@ -23,8 +24,6 @@ widget_ids! { // Login, Singleplayer login_button, login_text, - login_error, - login_error_bg, address_text, address_bg, address_field, @@ -39,6 +38,9 @@ widget_ids! { quit_button, // Error error_frame, + button_ok, + login_error, + login_error_bg, } } @@ -57,6 +59,9 @@ struct Imgs { button_press: ImgId, error_frame: ImgId, + button_dark: ImgId, + button_dark_hover: ImgId, + button_dark_press: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { @@ -90,6 +95,9 @@ impl Imgs { //Error error_frame: load("element/frames/skin_eyes.png"), + button_dark: load("element/buttons/button_dark.png"), + button_dark_hover: load("element/buttons/button_dark_hover.png"), + button_dark_press: load("element/buttons/button_dark_press.png"), } } } @@ -99,7 +107,6 @@ pub enum Event { username: String, server_address: String, }, - StartSingleplayer, Quit, } @@ -146,7 +153,7 @@ impl MainMenuUi { font_metamorph, font_opensans, username: "Username".to_string(), - server_address: DEFAULT_PUBLIC_SERVER.to_string(), + server_address: "veloren.mac94.de".to_string(), login_error: None, connecting: None, } @@ -181,18 +188,6 @@ impl MainMenuUi { }); }; } - - macro_rules! singleplayer { - () => { - self.login_error = None; - events.push(Event::StartSingleplayer); - events.push(Event::LoginAttempt { - username: "singleplayer".to_string(), - server_address: "localhost".to_string(), - }); - }; - } - const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); // Username // TODO: get a lower resolution and cleaner input_bg.png @@ -227,22 +222,30 @@ impl MainMenuUi { .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); - let x = match text.get_x_dimension(ui_widgets) { - Dimension::Absolute(x) => x + 10.0, - _ => 0.0, - }; - Rectangle::fill([x, 60.0]) + + Rectangle::fill_with([200.0, 100.0], color::BLACK) .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .mid_bottom_with_margin_on(self.ids.username_bg, 0.0) + .up_from(self.ids.username_bg, 35.0) .set(self.ids.login_error_bg, ui_widgets); - text.middle_of(self.ids.login_error_bg) + text.mid_top_with_margin_on(self.ids.login_error_bg, 10.0) .set(self.ids.login_error, ui_widgets); Image::new(self.imgs.error_frame) - .h(60.0) .middle_of(self.ids.login_error) .set(self.ids.error_frame, ui_widgets); - } + if Button::image(self.imgs.button_dark) + .w_h(50.0, 30.0) + .mid_top_with_margin_on(self.ids.login_error_bg, 20.0) + .hover_image(self.imgs.button_dark_hover) + .press_image(self.imgs.button_dark_press) + .label("Ok") + .label_font_size(10) + .label_color(TEXT_COLOR) + .set(self.ids.button_ok, ui_widgets) + .was_clicked() + {} + }; + // Server address Image::new(self.imgs.input_bg) .w_h(337.0, 67.0) @@ -321,7 +324,7 @@ impl MainMenuUi { .set(self.ids.singleplayer_button, ui_widgets) .was_clicked() { - singleplayer!(); + login!(); } // Quit if Button::image(self.imgs.button) From 5044fe8cb59f4d9532ab18ab1aeb807de95e7bb0 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 20:06:06 +0200 Subject: [PATCH 12/72] Simplify code Former-commit-id: c8bdf4199c913ab43ba08fdb19384bf7fcc6653d --- client/src/lib.rs | 6 ++---- server/src/lib.rs | 22 +++++++++------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index b2ad5904d5..53d47a7084 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -169,10 +169,8 @@ impl Client { // Update the server about the player's currently playing animation and the previous one if let Some(animationHistory) = self.state.read_storage::().get(self.player).cloned() { - if let Some(last) = animationHistory.last { - if animationHistory.current != last { - self.postbox.send_message(ClientMsg::PlayerAnimation(animationHistory)); - } + if Some(animationHistory.current) != animationHistory.last { + self.postbox.send_message(ClientMsg::PlayerAnimation(animationHistory)); } } diff --git a/server/src/lib.rs b/server/src/lib.rs index fd1e8fad5e..7f902f24d1 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -374,17 +374,15 @@ impl Server { &self.state.ecs().internal().read_storage::(), &self.state.ecs().internal().read_storage::(), ).join() { - if let Some(last) = animationHistory.last { - // Check if we need to sync - if animationHistory.current == last { - continue; - } - - self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation { - entity: uid.into(), - animationHistory, - }); + // Check if we need to sync + if Some(animationHistory.current) == animationHistory.last { + continue; } + + self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation { + entity: uid.into(), + animationHistory, + }); } // Update animation last/current state @@ -392,9 +390,7 @@ impl Server { &self.state.ecs().internal().entities(), &mut self.state.ecs().internal().write_storage::() ).join() { - animationHistory.last = None; - let mut new = animationHistory.clone(); - new.last = Some(new.current); + animationHistory.last = Some(animationHistory.current); } // Remove all force flags From 7e3f271838cebaf845f6f57bd78585a153f0746a Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 21:22:34 +0200 Subject: [PATCH 13/72] Move code for initializing clients to new function Former-commit-id: 55f8a9b49599b6912489c597c47a13d7657f78f1 --- server/src/lib.rs | 69 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/server/src/lib.rs b/server/src/lib.rs index 7f902f24d1..ebd76783a5 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -15,6 +15,7 @@ use common::{ net::PostOffice, state::{State, Uid}, terrain::TerrainChunk, + comp::character::Animation, }; use specs::{ join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder, @@ -235,28 +236,7 @@ impl Server { match client.state { ClientState::Connecting => match msg { ClientMsg::Connect { player, character } => { - - // Write client components - state.write_component(entity, player); - state.write_component(entity, comp::phys::Pos(Vec3::zero())); - state.write_component(entity, comp::phys::Vel(Vec3::zero())); - state.write_component(entity, comp::phys::Dir(Vec3::unit_y())); - if let Some(character) = character { - state.write_component(entity, character); - } - state.write_component(entity, comp::phys::ForceUpdate); - - client.state = ClientState::Connected; - - // Return a handshake with the state of the current world - client.notify(ServerMsg::Handshake { - ecs_state: state.ecs().gen_state_package(), - player_entity: state - .ecs() - .uid_from_entity(entity) - .unwrap() - .into(), - }); + Self::initialize_client(state, entity, client, player, character); } _ => disconnect = true, }, @@ -341,6 +321,51 @@ impl Server { Ok(frontend_events) } + /// Initialize a new client states with important information + fn initialize_client( + state: &mut State, + entity: specs::Entity, + client: &mut Client, + player: comp::Player, + character: Option, + ) { + // Save player metadata (for example the username) + state.write_component(entity, player); + + // Give the player it's character if he wants one + // (Chat only clients don't need one for example) + if let Some(character) = character { + state.write_component(entity, character); + + // Every character has to have these components + state.write_component(entity, comp::phys::Pos(Vec3::zero())); + state.write_component(entity, comp::phys::Vel(Vec3::zero())); + state.write_component(entity, comp::phys::Dir(Vec3::unit_y())); + // Make sure everything is accepted + state.write_component(entity, comp::phys::ForceUpdate); + + // Set initial animation + state.write_component(entity, comp::AnimationHistory { + last: None, + current: Animation::Idle + }); + } + + client.state = ClientState::Connected; + + // Return a handshake with the state of the current world + // (All components Sphynx tracks) + client.notify(ServerMsg::Handshake { + ecs_state: state.ecs().gen_state_package(), + player_entity: state + .ecs() + .uid_from_entity(entity) + .unwrap() + .into(), + }); + + } + /// Sync client states with the most up to date information fn sync_clients(&mut self) { // Sync 'logical' state using Sphynx From 61578b238edf6fe2f7576d61cb906473f20b2305 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 22:26:11 +0200 Subject: [PATCH 14/72] Sync animation states on initial connection Former-commit-id: 4ed67b6cbf56fceb03fa6a66b25b78925b91fc8a --- server/src/lib.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/server/src/lib.rs b/server/src/lib.rs index ebd76783a5..305667195b 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -364,6 +364,18 @@ impl Server { .into(), }); + // Sync logical information other players have authority over, not the server + for (other_entity, &uid, &animationHistory) in ( + &state.ecs().internal().entities(), + &state.ecs().internal().read_storage::(), + &state.ecs().internal().read_storage::(), + ).join() { + // AnimationHistory + client.postbox.send_message(ServerMsg::EntityAnimation { + entity: uid.into(), + animationHistory: animationHistory, + }); + } } /// Sync client states with the most up to date information From ec161531640d37aa85e35c2770f333cb2c628fdf Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 22:32:36 +0200 Subject: [PATCH 15/72] Rename animationHistory to animation_history Former-commit-id: bb2c882332fa9c3fd7f2c7fbd6143cd5f85153d8 --- client/src/lib.rs | 10 +++++----- common/src/msg/server.rs | 2 +- server/src/lib.rs | 16 ++++++++-------- voxygen/src/scene/figure.rs | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/client/src/lib.rs b/client/src/lib.rs index 53d47a7084..4931912b66 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -168,9 +168,9 @@ impl Client { } // Update the server about the player's currently playing animation and the previous one - if let Some(animationHistory) = self.state.read_storage::().get(self.player).cloned() { - if Some(animationHistory.current) != animationHistory.last { - self.postbox.send_message(ClientMsg::PlayerAnimation(animationHistory)); + if let Some(animation_history) = self.state.read_storage::().get(self.player).cloned() { + if Some(animation_history.current) != animation_history.last { + self.postbox.send_message(ClientMsg::PlayerAnimation(animation_history)); } } @@ -230,9 +230,9 @@ impl Client { }, None => {}, }, - ServerMsg::EntityAnimation { entity, animationHistory } => match self.state.ecs().entity_from_uid(entity) { + ServerMsg::EntityAnimation { entity, animation_history } => match self.state.ecs().entity_from_uid(entity) { Some(entity) => { - self.state.write_component(entity, animationHistory); + self.state.write_component(entity, animation_history); }, None => {}, }, diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 4b5a1b5517..3372b524fb 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -25,7 +25,7 @@ pub enum ServerMsg { }, EntityAnimation { entity: u64, - animationHistory: comp::AnimationHistory, + animation_history: comp::AnimationHistory, }, TerrainChunkUpdate { key: Vec3, diff --git a/server/src/lib.rs b/server/src/lib.rs index 305667195b..fa9a390eb7 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -246,7 +246,7 @@ impl Server { ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong), ClientMsg::Pong => {} ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)), - ClientMsg::PlayerAnimation(animationHistory) => state.write_component(entity, animationHistory), + ClientMsg::PlayerAnimation(animation_history) => state.write_component(entity, animation_history), ClientMsg::PlayerPhysics { pos, vel, dir } => { state.write_component(entity, pos); state.write_component(entity, vel); @@ -365,7 +365,7 @@ impl Server { }); // Sync logical information other players have authority over, not the server - for (other_entity, &uid, &animationHistory) in ( + for (other_entity, &uid, &animation_history) in ( &state.ecs().internal().entities(), &state.ecs().internal().read_storage::(), &state.ecs().internal().read_storage::(), @@ -373,7 +373,7 @@ impl Server { // AnimationHistory client.postbox.send_message(ServerMsg::EntityAnimation { entity: uid.into(), - animationHistory: animationHistory, + animation_history: animation_history, }); } } @@ -406,28 +406,28 @@ impl Server { } // Sync animation states - for (entity, &uid, &animationHistory) in ( + for (entity, &uid, &animation_history) in ( &self.state.ecs().internal().entities(), &self.state.ecs().internal().read_storage::(), &self.state.ecs().internal().read_storage::(), ).join() { // Check if we need to sync - if Some(animationHistory.current) == animationHistory.last { + if Some(animation_history.current) == animation_history.last { continue; } self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation { entity: uid.into(), - animationHistory, + animation_history, }); } // Update animation last/current state - for (entity, mut animationHistory) in ( + for (entity, mut animation_history) in ( &self.state.ecs().internal().entities(), &mut self.state.ecs().internal().write_storage::() ).join() { - animationHistory.last = Some(animationHistory.current); + animation_history.last = Some(animation_history.current); } // Remove all force flags diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 02089eb724..66f1a65b27 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -83,7 +83,7 @@ impl Figures { pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) { let time = client.state().get_time(); let ecs = client.state_mut().ecs_mut().internal_mut(); - for (entity, pos, dir, character, animationHistory) in ( + for (entity, pos, dir, character, animation_history) in ( &ecs.entities(), &ecs.read_storage::(), &ecs.read_storage::(), @@ -94,7 +94,7 @@ impl Figures { .entry(entity) .or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new())); - let target_skeleton = match animationHistory.current { + let target_skeleton = match animation_history.current { comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time), comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time), }; From 0635894557dacac4559f6bad238e50a1866a0541 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 22:38:52 +0200 Subject: [PATCH 16/72] Error Window, Alpha Version Display Former-commit-id: e2ad4e0974c513f806227720cdb2055c1847e9d7 --- voxygen/src/hud/mod.rs | 30 ++++++++++++++------- voxygen/src/menu/char_selection/ui.rs | 3 ++- voxygen/src/menu/main/ui.rs | 38 ++++++++++++++------------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 2aea2e7c2b..f152b45b47 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -20,6 +20,8 @@ widget_ids! { bag_space_add, inventorytest_button, inventorytest_button_label, + // Logo + v_logo, // Bag and Inventory bag, @@ -141,6 +143,8 @@ widget_ids! { // TODO: make macro to mimic widget_ids! for images ids or find another solution to simplify addition of new images. pub(self) struct Imgs { //Missing: ActionBar, Health/Mana/Energy Bar & Char Window BG/Frame + //Logo + v_logo: ImgId, // Bag bag: ImgId, bag_hover: ImgId, @@ -326,6 +330,7 @@ impl Imgs { // Window BG window_bg: load("element/misc_backgrounds/window_bg.png"), + v_logo: load("element/v_logo.png"), //Social Window social_bg: load("element/misc_backgrounds/small_bg.png"), @@ -476,6 +481,7 @@ impl Hud { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0); @@ -505,11 +511,17 @@ impl Hud { { events.push(Event::SendMessage(msg)); } + // Alpha Version + Text::new(version) + .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) + .font_size(14) + .color(TEXT_COLOR) + .set(self.ids.v_logo, ui_widgets); // Help Text if self.show_help { Image::new(self.imgs.window_frame_2) - .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) - .w_h(300.0, 370.0) + .top_left_with_margins_on(ui_widgets.window, 3.0, 3.0) + .w_h(300.0, 350.0) .set(self.ids.help_bg, ui_widgets); Text::new( @@ -535,14 +547,12 @@ impl Hud { .font_id(self.font_opensans) .font_size(18) .set(self.ids.help, ui_widgets); - if Button::image(self.imgs.button_dark) - .w_h(50.0, 30.0) - .bottom_right_with_margins_on(self.ids.help_bg, 10.0, 10.0) - .hover_image(self.imgs.button_dark_hover) - .press_image(self.imgs.button_dark_press) - .label("Close") - .label_font_size(10) - .label_color(TEXT_COLOR) + // X-button + if Button::image(self.imgs.close_button) + .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(self.ids.help_bg, 8.0, 4.0) .set(self.ids.button_help2, ui_widgets) .was_clicked() { diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index cb25d3f4a1..7a6e6cfe33 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -411,6 +411,7 @@ impl CharSelectionUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); // Character Selection ///////////////// // Supposed functionality: @@ -475,7 +476,7 @@ impl CharSelectionUi { Button::image(self.imgs.v_logo) .w_h(346.0, 111.0) .top_left_with_margins_on(self.ids.bg_selection, 30.0, 40.0) - .label("Alpha 0.1") + .label(version) .label_rgba(1.0, 1.0, 1.0, 1.0) .label_font_size(10) .label_y(conrod_core::position::Relative::Scalar(-40.0)) diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index cd839949e5..0068a6e740 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -6,7 +6,6 @@ use crate::{ use common::assets; use conrod_core::{ color, - color::BLACK, color::TRANSPARENT, image::Id as ImgId, position::{Dimension, Relative}, @@ -24,6 +23,8 @@ widget_ids! { // Login, Singleplayer login_button, login_text, + login_error, + login_error_bg, address_text, address_bg, address_field, @@ -39,8 +40,6 @@ widget_ids! { // Error error_frame, button_ok, - login_error, - login_error_bg, } } @@ -94,7 +93,7 @@ impl Imgs { button_press: load("element/buttons/button_press.png"), //Error - error_frame: load("element/frames/skin_eyes.png"), + error_frame: load("element/frames/window_2.png"), button_dark: load("element/buttons/button_dark.png"), button_dark_hover: load("element/buttons/button_dark_hover.png"), button_dark_press: load("element/buttons/button_dark_press.png"), @@ -162,6 +161,7 @@ impl MainMenuUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); // Background image, Veloren logo, Alpha-Version Label Image::new(self.imgs.bg) .middle_of(ui_widgets.window) @@ -169,7 +169,7 @@ impl MainMenuUi { Button::image(self.imgs.v_logo) .w_h(346.0, 111.0) .top_left_with_margins(30.0, 40.0) - .label("Alpha 0.1") + .label(version) .label_rgba(1.0, 1.0, 1.0, 1.0) .label_font_size(10) .label_y(Relative::Scalar(-40.0)) @@ -222,30 +222,32 @@ impl MainMenuUi { .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); - - Rectangle::fill_with([200.0, 100.0], color::BLACK) + Rectangle::fill_with([400.0, 100.0], color::TRANSPARENT) .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .up_from(self.ids.username_bg, 35.0) + .mid_top_with_margin_on(self.ids.username_bg, -35.0) .set(self.ids.login_error_bg, ui_widgets); - text.mid_top_with_margin_on(self.ids.login_error_bg, 10.0) - .set(self.ids.login_error, ui_widgets); Image::new(self.imgs.error_frame) - .middle_of(self.ids.login_error) + .w_h(400.0, 100.0) + .middle_of(self.ids.login_error_bg) .set(self.ids.error_frame, ui_widgets); + text.mid_top_with_margin_on(self.ids.error_frame, 10.0) + .set(self.ids.login_error, ui_widgets); if Button::image(self.imgs.button_dark) - .w_h(50.0, 30.0) - .mid_top_with_margin_on(self.ids.login_error_bg, 20.0) + .w_h(100.0, 30.0) + .mid_bottom_with_margin_on(self.ids.login_error_bg, 5.0) .hover_image(self.imgs.button_dark_hover) .press_image(self.imgs.button_dark_press) - .label("Ok") + .label_y(Relative::Scalar(2.0)) + .label("Okay") .label_font_size(10) .label_color(TEXT_COLOR) .set(self.ids.button_ok, ui_widgets) .was_clicked() - {} - }; - + { + self.login_error = None + }; + } // Server address Image::new(self.imgs.input_bg) .w_h(337.0, 67.0) @@ -318,7 +320,7 @@ impl MainMenuUi { .align_middle_x_of(self.ids.address_bg) .label("Singleplayer") .label_color(TEXT_COLOR) - .label_font_size(26) + .label_font_size(24) .label_y(Relative::Scalar(5.0)) .label_x(Relative::Scalar(2.0)) .set(self.ids.singleplayer_button, ui_widgets) From 86898c26a0fca3c767078c09b5d70272d819c657 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Wed, 17 Apr 2019 22:44:10 +0200 Subject: [PATCH 17/72] Rename lastAnimation to last_animation Former-commit-id: 7eabea72ad5ee2cfed20b3927a828eb55fae8e33 --- common/src/sys/control.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/sys/control.rs b/common/src/sys/control.rs index 9179ea744a..b2568c6975 100644 --- a/common/src/sys/control.rs +++ b/common/src/sys/control.rs @@ -31,10 +31,10 @@ impl<'a> System<'a> for Sys { Animation::Idle }; - let lastAnimation = anims.get_mut(entity).map(|h| h.current); + let last_animation = anims.get_mut(entity).map(|h| h.current); anims.insert(entity, AnimationHistory { - last: lastAnimation, + last: last_animation, current: animation, }); } From d7edd5ede7ca9e1bf08926b36791128a69a16683 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 22:46:43 +0200 Subject: [PATCH 18/72] Help window Closing button fixed Former-commit-id: 80adaac65b93562e0be6adad412db6cf413d0a64 --- voxygen/src/hud/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index f152b45b47..026126e909 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -552,7 +552,7 @@ impl Hud { .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) .hover_image(self.imgs.close_button_hover) .press_image(self.imgs.close_button_press) - .top_right_with_margins_on(self.ids.help_bg, 8.0, 4.0) + .top_right_with_margins_on(self.ids.help_bg, 8.0, 3.0) .set(self.ids.button_help2, ui_widgets) .was_clicked() { From b23ba127d7cc3c7c5140e0dfd6d30e0fd7eb2e34 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Mon, 15 Apr 2019 22:51:32 +0200 Subject: [PATCH 19/72] Error Window Former-commit-id: a736d656b95783434e53ef27e5311ea2da553587 --- voxygen/src/menu/main/mod.rs | 15 +++++++++------ voxygen/src/menu/main/ui.rs | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 05412179d2..36d8781725 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -62,7 +62,7 @@ impl PlayState for MainMenuState { global_state.window.renderer_mut().clear(BG_COLOR); // Poll client creation - match client_init.as_ref().and_then(|init| init.poll()) { + match client_init.as_ref().and_then(|init| init.poll()) { Some(Ok(client)) => { self.main_menu_ui.connected(); return PlayStateResult::Push(Box::new(CharSelectionState::new( @@ -72,11 +72,14 @@ impl PlayState for MainMenuState { } Some(Err(err)) => { client_init = None; - self.main_menu_ui.login_error(match err { - InitError::BadAddress(_) | InitError::NoAddress => "No such host is known", - InitError::ConnectionFailed(_) => "Could not connect to address", - }.to_string()); - }, + self.main_menu_ui.login_error( + match err { + InitError::BadAddress(_) | InitError::NoAddress => "Server not found", + InitError::ConnectionFailed(_) => "Connection failed", + } + .to_string(), + ); + } None => {} } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 6483690be5..2ea5c7d0e9 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -37,6 +37,8 @@ widget_ids! { servers_button, settings_button, quit_button, + // Error + error_frame, } } @@ -53,6 +55,8 @@ struct Imgs { button: ImgId, button_hover: ImgId, button_press: ImgId, + + error_frame: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { @@ -83,6 +87,9 @@ impl Imgs { button: load("element/buttons/button.png"), button_hover: load("element/buttons/button_hover.png"), button_press: load("element/buttons/button_press.png"), + + //Error + error_frame: load("element/frames/skin_eyes.png"), } } } @@ -217,20 +224,24 @@ impl MainMenuUi { // Login error if let Some(msg) = &self.login_error { let text = Text::new(&msg) - .rgba(0.5, 0.0, 0.0, 1.0) + .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); let x = match text.get_x_dimension(ui_widgets) { Dimension::Absolute(x) => x + 10.0, _ => 0.0, }; - Rectangle::fill([x, 40.0]) - .rgba(0.2, 0.3, 0.3, 0.7) + Rectangle::fill([x, 60.0]) + .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .up_from(self.ids.username_bg, 35.0) + .mid_bottom_with_margin_on(self.ids.username_bg, 0.0) .set(self.ids.login_error_bg, ui_widgets); text.middle_of(self.ids.login_error_bg) .set(self.ids.login_error, ui_widgets); + Image::new(self.imgs.error_frame) + .h(60.0) + .middle_of(self.ids.login_error) + .set(self.ids.error_frame, ui_widgets); } // Server address Image::new(self.imgs.input_bg) From 0cfe56bc7f3c4ef9546ca1073979f9584e9ecab4 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 19:41:22 +0200 Subject: [PATCH 20/72] Rebase and Login Error Former-commit-id: 7383aaad0d91aa3000a38a419c317e6a52f04b27 --- voxygen/src/hud/chat.rs | 72 +++++++++++--------------- voxygen/src/hud/mod.rs | 1 - voxygen/src/menu/char_selection/mod.rs | 10 +--- voxygen/src/menu/main/client_init.rs | 4 +- voxygen/src/menu/main/mod.rs | 6 --- voxygen/src/menu/main/ui.rs | 57 ++++++++++---------- 6 files changed, 64 insertions(+), 86 deletions(-) diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index d9f770b4f8..ef6c3bdd83 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -1,11 +1,10 @@ use crate::ui::Ui; use conrod_core::{ - color, input::Key, position::Dimension, text::font::Id as FontId, widget::{Button, Id, List, Rectangle, Text, TextEdit}, - widget_ids, Colorable, Positionable, Sizeable, UiCell, Widget, + widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, }; use std::collections::VecDeque; @@ -85,59 +84,48 @@ impl Chat { // Chat input with rectangle as background let text_edit = TextEdit::new(&self.input) - .w(460.0) - .restrict_to_height(false) - .line_spacing(2.0) - .font_size(15) - .font_id(font); - let y = match text_edit.get_y_dimension(ui_widgets) { - Dimension::Absolute(y) => y + 6.0, - _ => 0.0, - }; - Rectangle::fill([470.0, y]) - .rgba(0.0, 0.0, 0.0, 0.8) - .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) .w(470.0) + .restrict_to_height(false) + .font_size(15) + .font_id(font) + .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0); + let dims = match ( + text_edit.get_x_dimension(ui_widgets), + text_edit.get_y_dimension(ui_widgets), + ) { + (Dimension::Absolute(x), Dimension::Absolute(y)) => [x, y], + _ => [0.0, 0.0], + }; + Rectangle::fill(dims) + .rgba(0.0, 0.0, 0.0, 0.8) + .x_position(text_edit.get_x_position(ui_widgets)) + .y_position(text_edit.get_y_position(ui_widgets)) .set(self.ids.input_bg, ui_widgets); - if let Some(str) = text_edit - .top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0) - .set(self.ids.input, ui_widgets) - { + if let Some(str) = text_edit.set(self.ids.input, ui_widgets) { self.input = str.to_string(); self.input.retain(|c| c != '\n'); } // Message box - Rectangle::fill([470.0, 174.0]) + Rectangle::fill([470.0, 167.0]) .rgba(0.0, 0.0, 0.0, 0.4) - .up_from(self.ids.input_bg, 0.0) + .up_from(self.ids.input, 0.0) .set(self.ids.message_box_bg, ui_widgets); - let (mut items, _) = List::flow_down(self.messages.len() + 1) - .top_left_of(self.ids.message_box_bg) - .w_h(470.0, 174.0) - .scroll_kids_vertically() + let (mut items, scrollbar) = List::flow_down(self.messages.len()) + .top_left_with_margins_on(self.ids.message_box_bg, 0.0, 5.0) + .w_h(460.0, 160.0) + .scrollbar_next_to() + .scrollbar_thickness(18.0) + .scrollbar_color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .set(self.ids.message_box, ui_widgets); while let Some(item) = items.next(ui_widgets) { - // This would be easier if conrod used the v-metrics from rusttype - let widget = if item.i < self.messages.len() { - let text = Text::new(&self.messages[item.i]) + item.set( + Text::new(&self.messages[item.i]) .font_size(15) .font_id(font) - .w(470.0) - .rgba(1.0, 1.0, 1.0, 1.0) - .line_spacing(2.0); - // Add space between messages - let y = match text.get_y_dimension(ui_widgets) { - Dimension::Absolute(y) => y + 2.0, - _ => 0.0, - }; - text.h(y) - } else { - // Spacer at bottom of the last message so that it is not cut off - // Needs to be larger than the space above - Text::new("").font_size(6).font_id(font).w(470.0) - }; - item.set(widget, ui_widgets); + .rgba(1.0, 1.0, 1.0, 1.0), + ui_widgets, + ) } // Chat Arrow diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index ecdf6508c9..2aea2e7c2b 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -515,7 +515,6 @@ impl Hud { Text::new( "Tab = Free Cursor \n\ Esc = Open/Close Menus \n\ - Q = Back to Login \n\ \n\ F1 = Toggle this Window \n\ F2 = Toggle Interface \n\ diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 04504bb6c6..3ba0130622 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -45,10 +45,7 @@ impl PlayState for CharSelectionState { // Handle window events for event in global_state.window.fetch_events() { match event { - Event::Close => { - global_state.singleplayer = None; - return PlayStateResult::Shutdown; - }, + Event::Close => return PlayStateResult::Shutdown, // Pass events to ui Event::Ui(event) => { self.char_selection_ui.handle_event(event); @@ -63,10 +60,7 @@ impl PlayState for CharSelectionState { // Maintain the UI for event in self.char_selection_ui.maintain(global_state.window.renderer_mut()) { match event { - ui::Event::Logout => { - global_state.singleplayer = None; - return PlayStateResult::Pop; - }, + ui::Event::Logout => return PlayStateResult::Pop, ui::Event::Play => return PlayStateResult::Push( Box::new(SessionState::new(&mut global_state.window, self.client.clone())) ), diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index 124939f957..25473bdabb 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -22,10 +22,10 @@ pub struct ClientInit { impl ClientInit { pub fn new( connection_args: (String, u16, bool), - client_args: (comp::Player, Option, Option, u64), + client_args: (comp::Player, Option, u64), ) -> Self { let (server_address, default_port, prefer_ipv6) = connection_args; - let (player, character, animation, view_distance) = client_args; + let (player, character, view_distance) = client_args; let (tx, rx) = channel(); diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 36d8781725..983a2d41b5 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -5,12 +5,10 @@ use super::char_selection::CharSelectionState; use crate::{ window::{Event, Window}, GlobalState, PlayState, PlayStateResult, - singleplayer::Singleplayer, }; use client_init::{ClientInit, Error as InitError}; use common::{clock::Clock, comp}; use std::time::Duration; -use std::thread; use ui::{Event as MainMenuEvent, MainMenuUi}; use vek::*; @@ -100,14 +98,10 @@ impl PlayState for MainMenuState { ( comp::Player::new(username.clone()), Some(comp::Character::test()), - Some(comp::Animation::Idle), 300, ), ))); } - MainMenuEvent::StartSingleplayer => { - global_state.singleplayer = Some(Singleplayer::new()); - } MainMenuEvent::Quit => return PlayStateResult::Shutdown, } } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 2ea5c7d0e9..cd839949e5 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -1,11 +1,12 @@ use crate::{ - DEFAULT_PUBLIC_SERVER, render::Renderer, ui::{self, ScaleMode, Ui}, window::Window, }; use common::assets; use conrod_core::{ + color, + color::BLACK, color::TRANSPARENT, image::Id as ImgId, position::{Dimension, Relative}, @@ -23,8 +24,6 @@ widget_ids! { // Login, Singleplayer login_button, login_text, - login_error, - login_error_bg, address_text, address_bg, address_field, @@ -39,6 +38,9 @@ widget_ids! { quit_button, // Error error_frame, + button_ok, + login_error, + login_error_bg, } } @@ -57,6 +59,9 @@ struct Imgs { button_press: ImgId, error_frame: ImgId, + button_dark: ImgId, + button_dark_hover: ImgId, + button_dark_press: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { @@ -90,6 +95,9 @@ impl Imgs { //Error error_frame: load("element/frames/skin_eyes.png"), + button_dark: load("element/buttons/button_dark.png"), + button_dark_hover: load("element/buttons/button_dark_hover.png"), + button_dark_press: load("element/buttons/button_dark_press.png"), } } } @@ -99,7 +107,6 @@ pub enum Event { username: String, server_address: String, }, - StartSingleplayer, Quit, } @@ -146,7 +153,7 @@ impl MainMenuUi { font_metamorph, font_opensans, username: "Username".to_string(), - server_address: DEFAULT_PUBLIC_SERVER.to_string(), + server_address: "veloren.mac94.de".to_string(), login_error: None, connecting: None, } @@ -181,18 +188,6 @@ impl MainMenuUi { }); }; } - - macro_rules! singleplayer { - () => { - self.login_error = None; - events.push(Event::StartSingleplayer); - events.push(Event::LoginAttempt { - username: "singleplayer".to_string(), - server_address: "localhost".to_string(), - }); - }; - } - const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); // Username // TODO: get a lower resolution and cleaner input_bg.png @@ -227,22 +222,30 @@ impl MainMenuUi { .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); - let x = match text.get_x_dimension(ui_widgets) { - Dimension::Absolute(x) => x + 10.0, - _ => 0.0, - }; - Rectangle::fill([x, 60.0]) + + Rectangle::fill_with([200.0, 100.0], color::BLACK) .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .mid_bottom_with_margin_on(self.ids.username_bg, 0.0) + .up_from(self.ids.username_bg, 35.0) .set(self.ids.login_error_bg, ui_widgets); - text.middle_of(self.ids.login_error_bg) + text.mid_top_with_margin_on(self.ids.login_error_bg, 10.0) .set(self.ids.login_error, ui_widgets); Image::new(self.imgs.error_frame) - .h(60.0) .middle_of(self.ids.login_error) .set(self.ids.error_frame, ui_widgets); - } + if Button::image(self.imgs.button_dark) + .w_h(50.0, 30.0) + .mid_top_with_margin_on(self.ids.login_error_bg, 20.0) + .hover_image(self.imgs.button_dark_hover) + .press_image(self.imgs.button_dark_press) + .label("Ok") + .label_font_size(10) + .label_color(TEXT_COLOR) + .set(self.ids.button_ok, ui_widgets) + .was_clicked() + {} + }; + // Server address Image::new(self.imgs.input_bg) .w_h(337.0, 67.0) @@ -321,7 +324,7 @@ impl MainMenuUi { .set(self.ids.singleplayer_button, ui_widgets) .was_clicked() { - singleplayer!(); + login!(); } // Quit if Button::image(self.imgs.button) From 3959353cc9356baae0d334cccb9ff0af4f261bf0 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 22:38:52 +0200 Subject: [PATCH 21/72] Error Window, Alpha Version Display Former-commit-id: 739fc652a7d7f0894c1ae715f83a87e56a51e947 --- voxygen/src/hud/mod.rs | 30 ++++++++++++++------- voxygen/src/menu/char_selection/ui.rs | 3 ++- voxygen/src/menu/main/ui.rs | 38 ++++++++++++++------------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 2aea2e7c2b..f152b45b47 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -20,6 +20,8 @@ widget_ids! { bag_space_add, inventorytest_button, inventorytest_button_label, + // Logo + v_logo, // Bag and Inventory bag, @@ -141,6 +143,8 @@ widget_ids! { // TODO: make macro to mimic widget_ids! for images ids or find another solution to simplify addition of new images. pub(self) struct Imgs { //Missing: ActionBar, Health/Mana/Energy Bar & Char Window BG/Frame + //Logo + v_logo: ImgId, // Bag bag: ImgId, bag_hover: ImgId, @@ -326,6 +330,7 @@ impl Imgs { // Window BG window_bg: load("element/misc_backgrounds/window_bg.png"), + v_logo: load("element/v_logo.png"), //Social Window social_bg: load("element/misc_backgrounds/small_bg.png"), @@ -476,6 +481,7 @@ impl Hud { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0); @@ -505,11 +511,17 @@ impl Hud { { events.push(Event::SendMessage(msg)); } + // Alpha Version + Text::new(version) + .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) + .font_size(14) + .color(TEXT_COLOR) + .set(self.ids.v_logo, ui_widgets); // Help Text if self.show_help { Image::new(self.imgs.window_frame_2) - .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) - .w_h(300.0, 370.0) + .top_left_with_margins_on(ui_widgets.window, 3.0, 3.0) + .w_h(300.0, 350.0) .set(self.ids.help_bg, ui_widgets); Text::new( @@ -535,14 +547,12 @@ impl Hud { .font_id(self.font_opensans) .font_size(18) .set(self.ids.help, ui_widgets); - if Button::image(self.imgs.button_dark) - .w_h(50.0, 30.0) - .bottom_right_with_margins_on(self.ids.help_bg, 10.0, 10.0) - .hover_image(self.imgs.button_dark_hover) - .press_image(self.imgs.button_dark_press) - .label("Close") - .label_font_size(10) - .label_color(TEXT_COLOR) + // X-button + if Button::image(self.imgs.close_button) + .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(self.ids.help_bg, 8.0, 4.0) .set(self.ids.button_help2, ui_widgets) .was_clicked() { diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index cb25d3f4a1..7a6e6cfe33 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -411,6 +411,7 @@ impl CharSelectionUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); // Character Selection ///////////////// // Supposed functionality: @@ -475,7 +476,7 @@ impl CharSelectionUi { Button::image(self.imgs.v_logo) .w_h(346.0, 111.0) .top_left_with_margins_on(self.ids.bg_selection, 30.0, 40.0) - .label("Alpha 0.1") + .label(version) .label_rgba(1.0, 1.0, 1.0, 1.0) .label_font_size(10) .label_y(conrod_core::position::Relative::Scalar(-40.0)) diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index cd839949e5..0068a6e740 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -6,7 +6,6 @@ use crate::{ use common::assets; use conrod_core::{ color, - color::BLACK, color::TRANSPARENT, image::Id as ImgId, position::{Dimension, Relative}, @@ -24,6 +23,8 @@ widget_ids! { // Login, Singleplayer login_button, login_text, + login_error, + login_error_bg, address_text, address_bg, address_field, @@ -39,8 +40,6 @@ widget_ids! { // Error error_frame, button_ok, - login_error, - login_error_bg, } } @@ -94,7 +93,7 @@ impl Imgs { button_press: load("element/buttons/button_press.png"), //Error - error_frame: load("element/frames/skin_eyes.png"), + error_frame: load("element/frames/window_2.png"), button_dark: load("element/buttons/button_dark.png"), button_dark_hover: load("element/buttons/button_dark_hover.png"), button_dark_press: load("element/buttons/button_dark_press.png"), @@ -162,6 +161,7 @@ impl MainMenuUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); // Background image, Veloren logo, Alpha-Version Label Image::new(self.imgs.bg) .middle_of(ui_widgets.window) @@ -169,7 +169,7 @@ impl MainMenuUi { Button::image(self.imgs.v_logo) .w_h(346.0, 111.0) .top_left_with_margins(30.0, 40.0) - .label("Alpha 0.1") + .label(version) .label_rgba(1.0, 1.0, 1.0, 1.0) .label_font_size(10) .label_y(Relative::Scalar(-40.0)) @@ -222,30 +222,32 @@ impl MainMenuUi { .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); - - Rectangle::fill_with([200.0, 100.0], color::BLACK) + Rectangle::fill_with([400.0, 100.0], color::TRANSPARENT) .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .up_from(self.ids.username_bg, 35.0) + .mid_top_with_margin_on(self.ids.username_bg, -35.0) .set(self.ids.login_error_bg, ui_widgets); - text.mid_top_with_margin_on(self.ids.login_error_bg, 10.0) - .set(self.ids.login_error, ui_widgets); Image::new(self.imgs.error_frame) - .middle_of(self.ids.login_error) + .w_h(400.0, 100.0) + .middle_of(self.ids.login_error_bg) .set(self.ids.error_frame, ui_widgets); + text.mid_top_with_margin_on(self.ids.error_frame, 10.0) + .set(self.ids.login_error, ui_widgets); if Button::image(self.imgs.button_dark) - .w_h(50.0, 30.0) - .mid_top_with_margin_on(self.ids.login_error_bg, 20.0) + .w_h(100.0, 30.0) + .mid_bottom_with_margin_on(self.ids.login_error_bg, 5.0) .hover_image(self.imgs.button_dark_hover) .press_image(self.imgs.button_dark_press) - .label("Ok") + .label_y(Relative::Scalar(2.0)) + .label("Okay") .label_font_size(10) .label_color(TEXT_COLOR) .set(self.ids.button_ok, ui_widgets) .was_clicked() - {} - }; - + { + self.login_error = None + }; + } // Server address Image::new(self.imgs.input_bg) .w_h(337.0, 67.0) @@ -318,7 +320,7 @@ impl MainMenuUi { .align_middle_x_of(self.ids.address_bg) .label("Singleplayer") .label_color(TEXT_COLOR) - .label_font_size(26) + .label_font_size(24) .label_y(Relative::Scalar(5.0)) .label_x(Relative::Scalar(2.0)) .set(self.ids.singleplayer_button, ui_widgets) From c8e60a4c7503ff1a2f2cde21d6a689ce253f1174 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 22:46:43 +0200 Subject: [PATCH 22/72] Help window Closing button fixed Former-commit-id: 6b57d04e52d25b3268b45abdf6603f197d442698 --- voxygen/src/hud/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index f152b45b47..026126e909 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -552,7 +552,7 @@ impl Hud { .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) .hover_image(self.imgs.close_button_hover) .press_image(self.imgs.close_button_press) - .top_right_with_margins_on(self.ids.help_bg, 8.0, 4.0) + .top_right_with_margins_on(self.ids.help_bg, 8.0, 3.0) .set(self.ids.button_help2, ui_widgets) .was_clicked() { From 2c5bfaa1185b1fea9b6e82d956fa51ad809a89a5 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Mon, 15 Apr 2019 22:51:32 +0200 Subject: [PATCH 23/72] Error Window Former-commit-id: 0f4f92c39632f8cbd1750036d19eb1cfbf39f374 --- voxygen/src/menu/main/mod.rs | 15 +++++++++------ voxygen/src/menu/main/ui.rs | 19 +++++++++++++++---- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 05412179d2..36d8781725 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -62,7 +62,7 @@ impl PlayState for MainMenuState { global_state.window.renderer_mut().clear(BG_COLOR); // Poll client creation - match client_init.as_ref().and_then(|init| init.poll()) { + match client_init.as_ref().and_then(|init| init.poll()) { Some(Ok(client)) => { self.main_menu_ui.connected(); return PlayStateResult::Push(Box::new(CharSelectionState::new( @@ -72,11 +72,14 @@ impl PlayState for MainMenuState { } Some(Err(err)) => { client_init = None; - self.main_menu_ui.login_error(match err { - InitError::BadAddress(_) | InitError::NoAddress => "No such host is known", - InitError::ConnectionFailed(_) => "Could not connect to address", - }.to_string()); - }, + self.main_menu_ui.login_error( + match err { + InitError::BadAddress(_) | InitError::NoAddress => "Server not found", + InitError::ConnectionFailed(_) => "Connection failed", + } + .to_string(), + ); + } None => {} } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 6483690be5..2ea5c7d0e9 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -37,6 +37,8 @@ widget_ids! { servers_button, settings_button, quit_button, + // Error + error_frame, } } @@ -53,6 +55,8 @@ struct Imgs { button: ImgId, button_hover: ImgId, button_press: ImgId, + + error_frame: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { @@ -83,6 +87,9 @@ impl Imgs { button: load("element/buttons/button.png"), button_hover: load("element/buttons/button_hover.png"), button_press: load("element/buttons/button_press.png"), + + //Error + error_frame: load("element/frames/skin_eyes.png"), } } } @@ -217,20 +224,24 @@ impl MainMenuUi { // Login error if let Some(msg) = &self.login_error { let text = Text::new(&msg) - .rgba(0.5, 0.0, 0.0, 1.0) + .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); let x = match text.get_x_dimension(ui_widgets) { Dimension::Absolute(x) => x + 10.0, _ => 0.0, }; - Rectangle::fill([x, 40.0]) - .rgba(0.2, 0.3, 0.3, 0.7) + Rectangle::fill([x, 60.0]) + .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .up_from(self.ids.username_bg, 35.0) + .mid_bottom_with_margin_on(self.ids.username_bg, 0.0) .set(self.ids.login_error_bg, ui_widgets); text.middle_of(self.ids.login_error_bg) .set(self.ids.login_error, ui_widgets); + Image::new(self.imgs.error_frame) + .h(60.0) + .middle_of(self.ids.login_error) + .set(self.ids.error_frame, ui_widgets); } // Server address Image::new(self.imgs.input_bg) From a23e71a258c4784cc51d5dc759e6cd3204cce967 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 19:41:22 +0200 Subject: [PATCH 24/72] Rebase and Login Error Former-commit-id: 226fca5f37aa9c94fdd3e1a030c7de4703deba4c --- voxygen/src/hud/chat.rs | 72 +++++++++++--------------- voxygen/src/hud/mod.rs | 1 - voxygen/src/menu/char_selection/mod.rs | 10 +--- voxygen/src/menu/main/client_init.rs | 4 +- voxygen/src/menu/main/mod.rs | 6 --- voxygen/src/menu/main/ui.rs | 57 ++++++++++---------- 6 files changed, 64 insertions(+), 86 deletions(-) diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index d9f770b4f8..ef6c3bdd83 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -1,11 +1,10 @@ use crate::ui::Ui; use conrod_core::{ - color, input::Key, position::Dimension, text::font::Id as FontId, widget::{Button, Id, List, Rectangle, Text, TextEdit}, - widget_ids, Colorable, Positionable, Sizeable, UiCell, Widget, + widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, }; use std::collections::VecDeque; @@ -85,59 +84,48 @@ impl Chat { // Chat input with rectangle as background let text_edit = TextEdit::new(&self.input) - .w(460.0) - .restrict_to_height(false) - .line_spacing(2.0) - .font_size(15) - .font_id(font); - let y = match text_edit.get_y_dimension(ui_widgets) { - Dimension::Absolute(y) => y + 6.0, - _ => 0.0, - }; - Rectangle::fill([470.0, y]) - .rgba(0.0, 0.0, 0.0, 0.8) - .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) .w(470.0) + .restrict_to_height(false) + .font_size(15) + .font_id(font) + .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0); + let dims = match ( + text_edit.get_x_dimension(ui_widgets), + text_edit.get_y_dimension(ui_widgets), + ) { + (Dimension::Absolute(x), Dimension::Absolute(y)) => [x, y], + _ => [0.0, 0.0], + }; + Rectangle::fill(dims) + .rgba(0.0, 0.0, 0.0, 0.8) + .x_position(text_edit.get_x_position(ui_widgets)) + .y_position(text_edit.get_y_position(ui_widgets)) .set(self.ids.input_bg, ui_widgets); - if let Some(str) = text_edit - .top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0) - .set(self.ids.input, ui_widgets) - { + if let Some(str) = text_edit.set(self.ids.input, ui_widgets) { self.input = str.to_string(); self.input.retain(|c| c != '\n'); } // Message box - Rectangle::fill([470.0, 174.0]) + Rectangle::fill([470.0, 167.0]) .rgba(0.0, 0.0, 0.0, 0.4) - .up_from(self.ids.input_bg, 0.0) + .up_from(self.ids.input, 0.0) .set(self.ids.message_box_bg, ui_widgets); - let (mut items, _) = List::flow_down(self.messages.len() + 1) - .top_left_of(self.ids.message_box_bg) - .w_h(470.0, 174.0) - .scroll_kids_vertically() + let (mut items, scrollbar) = List::flow_down(self.messages.len()) + .top_left_with_margins_on(self.ids.message_box_bg, 0.0, 5.0) + .w_h(460.0, 160.0) + .scrollbar_next_to() + .scrollbar_thickness(18.0) + .scrollbar_color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .set(self.ids.message_box, ui_widgets); while let Some(item) = items.next(ui_widgets) { - // This would be easier if conrod used the v-metrics from rusttype - let widget = if item.i < self.messages.len() { - let text = Text::new(&self.messages[item.i]) + item.set( + Text::new(&self.messages[item.i]) .font_size(15) .font_id(font) - .w(470.0) - .rgba(1.0, 1.0, 1.0, 1.0) - .line_spacing(2.0); - // Add space between messages - let y = match text.get_y_dimension(ui_widgets) { - Dimension::Absolute(y) => y + 2.0, - _ => 0.0, - }; - text.h(y) - } else { - // Spacer at bottom of the last message so that it is not cut off - // Needs to be larger than the space above - Text::new("").font_size(6).font_id(font).w(470.0) - }; - item.set(widget, ui_widgets); + .rgba(1.0, 1.0, 1.0, 1.0), + ui_widgets, + ) } // Chat Arrow diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index ecdf6508c9..2aea2e7c2b 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -515,7 +515,6 @@ impl Hud { Text::new( "Tab = Free Cursor \n\ Esc = Open/Close Menus \n\ - Q = Back to Login \n\ \n\ F1 = Toggle this Window \n\ F2 = Toggle Interface \n\ diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 04504bb6c6..3ba0130622 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -45,10 +45,7 @@ impl PlayState for CharSelectionState { // Handle window events for event in global_state.window.fetch_events() { match event { - Event::Close => { - global_state.singleplayer = None; - return PlayStateResult::Shutdown; - }, + Event::Close => return PlayStateResult::Shutdown, // Pass events to ui Event::Ui(event) => { self.char_selection_ui.handle_event(event); @@ -63,10 +60,7 @@ impl PlayState for CharSelectionState { // Maintain the UI for event in self.char_selection_ui.maintain(global_state.window.renderer_mut()) { match event { - ui::Event::Logout => { - global_state.singleplayer = None; - return PlayStateResult::Pop; - }, + ui::Event::Logout => return PlayStateResult::Pop, ui::Event::Play => return PlayStateResult::Push( Box::new(SessionState::new(&mut global_state.window, self.client.clone())) ), diff --git a/voxygen/src/menu/main/client_init.rs b/voxygen/src/menu/main/client_init.rs index 124939f957..25473bdabb 100644 --- a/voxygen/src/menu/main/client_init.rs +++ b/voxygen/src/menu/main/client_init.rs @@ -22,10 +22,10 @@ pub struct ClientInit { impl ClientInit { pub fn new( connection_args: (String, u16, bool), - client_args: (comp::Player, Option, Option, u64), + client_args: (comp::Player, Option, u64), ) -> Self { let (server_address, default_port, prefer_ipv6) = connection_args; - let (player, character, animation, view_distance) = client_args; + let (player, character, view_distance) = client_args; let (tx, rx) = channel(); diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 36d8781725..983a2d41b5 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -5,12 +5,10 @@ use super::char_selection::CharSelectionState; use crate::{ window::{Event, Window}, GlobalState, PlayState, PlayStateResult, - singleplayer::Singleplayer, }; use client_init::{ClientInit, Error as InitError}; use common::{clock::Clock, comp}; use std::time::Duration; -use std::thread; use ui::{Event as MainMenuEvent, MainMenuUi}; use vek::*; @@ -100,14 +98,10 @@ impl PlayState for MainMenuState { ( comp::Player::new(username.clone()), Some(comp::Character::test()), - Some(comp::Animation::Idle), 300, ), ))); } - MainMenuEvent::StartSingleplayer => { - global_state.singleplayer = Some(Singleplayer::new()); - } MainMenuEvent::Quit => return PlayStateResult::Shutdown, } } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 2ea5c7d0e9..cd839949e5 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -1,11 +1,12 @@ use crate::{ - DEFAULT_PUBLIC_SERVER, render::Renderer, ui::{self, ScaleMode, Ui}, window::Window, }; use common::assets; use conrod_core::{ + color, + color::BLACK, color::TRANSPARENT, image::Id as ImgId, position::{Dimension, Relative}, @@ -23,8 +24,6 @@ widget_ids! { // Login, Singleplayer login_button, login_text, - login_error, - login_error_bg, address_text, address_bg, address_field, @@ -39,6 +38,9 @@ widget_ids! { quit_button, // Error error_frame, + button_ok, + login_error, + login_error_bg, } } @@ -57,6 +59,9 @@ struct Imgs { button_press: ImgId, error_frame: ImgId, + button_dark: ImgId, + button_dark_hover: ImgId, + button_dark_press: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { @@ -90,6 +95,9 @@ impl Imgs { //Error error_frame: load("element/frames/skin_eyes.png"), + button_dark: load("element/buttons/button_dark.png"), + button_dark_hover: load("element/buttons/button_dark_hover.png"), + button_dark_press: load("element/buttons/button_dark_press.png"), } } } @@ -99,7 +107,6 @@ pub enum Event { username: String, server_address: String, }, - StartSingleplayer, Quit, } @@ -146,7 +153,7 @@ impl MainMenuUi { font_metamorph, font_opensans, username: "Username".to_string(), - server_address: DEFAULT_PUBLIC_SERVER.to_string(), + server_address: "veloren.mac94.de".to_string(), login_error: None, connecting: None, } @@ -181,18 +188,6 @@ impl MainMenuUi { }); }; } - - macro_rules! singleplayer { - () => { - self.login_error = None; - events.push(Event::StartSingleplayer); - events.push(Event::LoginAttempt { - username: "singleplayer".to_string(), - server_address: "localhost".to_string(), - }); - }; - } - const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); // Username // TODO: get a lower resolution and cleaner input_bg.png @@ -227,22 +222,30 @@ impl MainMenuUi { .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); - let x = match text.get_x_dimension(ui_widgets) { - Dimension::Absolute(x) => x + 10.0, - _ => 0.0, - }; - Rectangle::fill([x, 60.0]) + + Rectangle::fill_with([200.0, 100.0], color::BLACK) .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .mid_bottom_with_margin_on(self.ids.username_bg, 0.0) + .up_from(self.ids.username_bg, 35.0) .set(self.ids.login_error_bg, ui_widgets); - text.middle_of(self.ids.login_error_bg) + text.mid_top_with_margin_on(self.ids.login_error_bg, 10.0) .set(self.ids.login_error, ui_widgets); Image::new(self.imgs.error_frame) - .h(60.0) .middle_of(self.ids.login_error) .set(self.ids.error_frame, ui_widgets); - } + if Button::image(self.imgs.button_dark) + .w_h(50.0, 30.0) + .mid_top_with_margin_on(self.ids.login_error_bg, 20.0) + .hover_image(self.imgs.button_dark_hover) + .press_image(self.imgs.button_dark_press) + .label("Ok") + .label_font_size(10) + .label_color(TEXT_COLOR) + .set(self.ids.button_ok, ui_widgets) + .was_clicked() + {} + }; + // Server address Image::new(self.imgs.input_bg) .w_h(337.0, 67.0) @@ -321,7 +324,7 @@ impl MainMenuUi { .set(self.ids.singleplayer_button, ui_widgets) .was_clicked() { - singleplayer!(); + login!(); } // Quit if Button::image(self.imgs.button) From 2e671899e0b41c1af0272bdb8c41652d630db57b Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 22:38:52 +0200 Subject: [PATCH 25/72] Error Window, Alpha Version Display Former-commit-id: 59ee7e42ca522cdcdbec7b07dbee4d3249213aab --- voxygen/src/hud/mod.rs | 30 ++++++++++++++------- voxygen/src/menu/char_selection/ui.rs | 3 ++- voxygen/src/menu/main/ui.rs | 38 ++++++++++++++------------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 2aea2e7c2b..f152b45b47 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -20,6 +20,8 @@ widget_ids! { bag_space_add, inventorytest_button, inventorytest_button_label, + // Logo + v_logo, // Bag and Inventory bag, @@ -141,6 +143,8 @@ widget_ids! { // TODO: make macro to mimic widget_ids! for images ids or find another solution to simplify addition of new images. pub(self) struct Imgs { //Missing: ActionBar, Health/Mana/Energy Bar & Char Window BG/Frame + //Logo + v_logo: ImgId, // Bag bag: ImgId, bag_hover: ImgId, @@ -326,6 +330,7 @@ impl Imgs { // Window BG window_bg: load("element/misc_backgrounds/window_bg.png"), + v_logo: load("element/v_logo.png"), //Social Window social_bg: load("element/misc_backgrounds/small_bg.png"), @@ -476,6 +481,7 @@ impl Hud { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0); @@ -505,11 +511,17 @@ impl Hud { { events.push(Event::SendMessage(msg)); } + // Alpha Version + Text::new(version) + .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) + .font_size(14) + .color(TEXT_COLOR) + .set(self.ids.v_logo, ui_widgets); // Help Text if self.show_help { Image::new(self.imgs.window_frame_2) - .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) - .w_h(300.0, 370.0) + .top_left_with_margins_on(ui_widgets.window, 3.0, 3.0) + .w_h(300.0, 350.0) .set(self.ids.help_bg, ui_widgets); Text::new( @@ -535,14 +547,12 @@ impl Hud { .font_id(self.font_opensans) .font_size(18) .set(self.ids.help, ui_widgets); - if Button::image(self.imgs.button_dark) - .w_h(50.0, 30.0) - .bottom_right_with_margins_on(self.ids.help_bg, 10.0, 10.0) - .hover_image(self.imgs.button_dark_hover) - .press_image(self.imgs.button_dark_press) - .label("Close") - .label_font_size(10) - .label_color(TEXT_COLOR) + // X-button + if Button::image(self.imgs.close_button) + .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(self.ids.help_bg, 8.0, 4.0) .set(self.ids.button_help2, ui_widgets) .was_clicked() { diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index cb25d3f4a1..7a6e6cfe33 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -411,6 +411,7 @@ impl CharSelectionUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); // Character Selection ///////////////// // Supposed functionality: @@ -475,7 +476,7 @@ impl CharSelectionUi { Button::image(self.imgs.v_logo) .w_h(346.0, 111.0) .top_left_with_margins_on(self.ids.bg_selection, 30.0, 40.0) - .label("Alpha 0.1") + .label(version) .label_rgba(1.0, 1.0, 1.0, 1.0) .label_font_size(10) .label_y(conrod_core::position::Relative::Scalar(-40.0)) diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index cd839949e5..0068a6e740 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -6,7 +6,6 @@ use crate::{ use common::assets; use conrod_core::{ color, - color::BLACK, color::TRANSPARENT, image::Id as ImgId, position::{Dimension, Relative}, @@ -24,6 +23,8 @@ widget_ids! { // Login, Singleplayer login_button, login_text, + login_error, + login_error_bg, address_text, address_bg, address_field, @@ -39,8 +40,6 @@ widget_ids! { // Error error_frame, button_ok, - login_error, - login_error_bg, } } @@ -94,7 +93,7 @@ impl Imgs { button_press: load("element/buttons/button_press.png"), //Error - error_frame: load("element/frames/skin_eyes.png"), + error_frame: load("element/frames/window_2.png"), button_dark: load("element/buttons/button_dark.png"), button_dark_hover: load("element/buttons/button_dark_hover.png"), button_dark_press: load("element/buttons/button_dark_press.png"), @@ -162,6 +161,7 @@ impl MainMenuUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); + let version = env!("Cargo_PKG_VERSION"); // Background image, Veloren logo, Alpha-Version Label Image::new(self.imgs.bg) .middle_of(ui_widgets.window) @@ -169,7 +169,7 @@ impl MainMenuUi { Button::image(self.imgs.v_logo) .w_h(346.0, 111.0) .top_left_with_margins(30.0, 40.0) - .label("Alpha 0.1") + .label(version) .label_rgba(1.0, 1.0, 1.0, 1.0) .label_font_size(10) .label_y(Relative::Scalar(-40.0)) @@ -222,30 +222,32 @@ impl MainMenuUi { .rgba(1.0, 1.0, 1.0, 1.0) .font_size(30) .font_id(self.font_opensans); - - Rectangle::fill_with([200.0, 100.0], color::BLACK) + Rectangle::fill_with([400.0, 100.0], color::TRANSPARENT) .rgba(0.1, 0.1, 0.1, 1.0) .parent(ui_widgets.window) - .up_from(self.ids.username_bg, 35.0) + .mid_top_with_margin_on(self.ids.username_bg, -35.0) .set(self.ids.login_error_bg, ui_widgets); - text.mid_top_with_margin_on(self.ids.login_error_bg, 10.0) - .set(self.ids.login_error, ui_widgets); Image::new(self.imgs.error_frame) - .middle_of(self.ids.login_error) + .w_h(400.0, 100.0) + .middle_of(self.ids.login_error_bg) .set(self.ids.error_frame, ui_widgets); + text.mid_top_with_margin_on(self.ids.error_frame, 10.0) + .set(self.ids.login_error, ui_widgets); if Button::image(self.imgs.button_dark) - .w_h(50.0, 30.0) - .mid_top_with_margin_on(self.ids.login_error_bg, 20.0) + .w_h(100.0, 30.0) + .mid_bottom_with_margin_on(self.ids.login_error_bg, 5.0) .hover_image(self.imgs.button_dark_hover) .press_image(self.imgs.button_dark_press) - .label("Ok") + .label_y(Relative::Scalar(2.0)) + .label("Okay") .label_font_size(10) .label_color(TEXT_COLOR) .set(self.ids.button_ok, ui_widgets) .was_clicked() - {} - }; - + { + self.login_error = None + }; + } // Server address Image::new(self.imgs.input_bg) .w_h(337.0, 67.0) @@ -318,7 +320,7 @@ impl MainMenuUi { .align_middle_x_of(self.ids.address_bg) .label("Singleplayer") .label_color(TEXT_COLOR) - .label_font_size(26) + .label_font_size(24) .label_y(Relative::Scalar(5.0)) .label_x(Relative::Scalar(2.0)) .set(self.ids.singleplayer_button, ui_widgets) From 1ea7b5031d5ee7263d0d315c4d2f49e3dd7eb525 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 22:46:43 +0200 Subject: [PATCH 26/72] Help window Closing button fixed Former-commit-id: 75c539985527e38b13bf7aa382d3b9491ef19fed --- voxygen/src/hud/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index f152b45b47..026126e909 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -552,7 +552,7 @@ impl Hud { .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) .hover_image(self.imgs.close_button_hover) .press_image(self.imgs.close_button_press) - .top_right_with_margins_on(self.ids.help_bg, 8.0, 4.0) + .top_right_with_margins_on(self.ids.help_bg, 8.0, 3.0) .set(self.ids.button_help2, ui_widgets) .was_clicked() { From 15e498c3f5f7832e7159ccc37f048ae06564836c Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 19:41:22 +0200 Subject: [PATCH 27/72] Rebase and Login Error Former-commit-id: 1b7736d80dde1a10ba04936c2cfe3df4d64ec57f --- voxygen/src/menu/main/ui.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 0068a6e740..489f4ce367 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -23,8 +23,6 @@ widget_ids! { // Login, Singleplayer login_button, login_text, - login_error, - login_error_bg, address_text, address_bg, address_field, From f7af7417cecfb112a47749d3c3d8beb286bffb78 Mon Sep 17 00:00:00 2001 From: Pfauenauge90 <44173739+Pfauenauge90@users.noreply.github.com> Date: Wed, 17 Apr 2019 22:38:52 +0200 Subject: [PATCH 28/72] Error Window, Alpha Version Display Former-commit-id: 0cdf4980eacf57db6dc275aabc26f49a0db274a6 --- voxygen/src/menu/main/ui.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 489f4ce367..0068a6e740 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -23,6 +23,8 @@ widget_ids! { // Login, Singleplayer login_button, login_text, + login_error, + login_error_bg, address_text, address_bg, address_field, From 56e50f4d587967698daeeed4f5530fb0dcfd45b8 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 18 Apr 2019 14:21:25 +0100 Subject: [PATCH 29/72] Minor fixes Former-commit-id: 54c2b050fd9be82916d66c872fa9ab5f5354f9dd --- voxygen/src/hud/mod.rs | 2 +- voxygen/src/menu/char_selection/ui.rs | 2 +- voxygen/src/menu/main/ui.rs | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 026126e909..589b283f85 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -481,7 +481,7 @@ impl Hud { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); - let version = env!("Cargo_PKG_VERSION"); + let version = env!("CARGO_PKG_VERSION"); const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0); diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index 7a6e6cfe33..34ebd08c70 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -411,7 +411,7 @@ impl CharSelectionUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); - let version = env!("Cargo_PKG_VERSION"); + let version = env!("CARGO_PKG_VERSION"); // Character Selection ///////////////// // Supposed functionality: diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 0068a6e740..798c386182 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -2,6 +2,7 @@ use crate::{ render::Renderer, ui::{self, ScaleMode, Ui}, window::Window, + DEFAULT_PUBLIC_SERVER, }; use common::assets; use conrod_core::{ @@ -152,7 +153,7 @@ impl MainMenuUi { font_metamorph, font_opensans, username: "Username".to_string(), - server_address: "veloren.mac94.de".to_string(), + server_address: DEFAULT_PUBLIC_SERVER.to_string(), login_error: None, connecting: None, } @@ -161,7 +162,7 @@ impl MainMenuUi { fn update_layout(&mut self) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); - let version = env!("Cargo_PKG_VERSION"); + let version = env!("CARGO_PKG_VERSION"); // Background image, Veloren logo, Alpha-Version Label Image::new(self.imgs.bg) .middle_of(ui_widgets.window) From 40c2625a4cfbef124d4f337a0e7c0416b328f987 Mon Sep 17 00:00:00 2001 From: yeet Date: Thu, 18 Apr 2019 15:53:03 +0200 Subject: [PATCH 30/72] Fix Singleplayer After a certains person's MR has been merged, for some reason all traces of working Singleplayer have disappeared Former-commit-id: 4119e4609cd39bb1896c7f28d45f5c1a7ec9c129 --- voxygen/src/menu/char_selection/mod.rs | 10 ++++++++-- voxygen/src/menu/main/mod.rs | 6 +++++- voxygen/src/menu/main/ui.rs | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 3ba0130622..04504bb6c6 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -45,7 +45,10 @@ impl PlayState for CharSelectionState { // Handle window events for event in global_state.window.fetch_events() { match event { - Event::Close => return PlayStateResult::Shutdown, + Event::Close => { + global_state.singleplayer = None; + return PlayStateResult::Shutdown; + }, // Pass events to ui Event::Ui(event) => { self.char_selection_ui.handle_event(event); @@ -60,7 +63,10 @@ impl PlayState for CharSelectionState { // Maintain the UI for event in self.char_selection_ui.maintain(global_state.window.renderer_mut()) { match event { - ui::Event::Logout => return PlayStateResult::Pop, + ui::Event::Logout => { + global_state.singleplayer = None; + return PlayStateResult::Pop; + }, ui::Event::Play => return PlayStateResult::Push( Box::new(SessionState::new(&mut global_state.window, self.client.clone())) ), diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 983a2d41b5..9b0247a775 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -5,6 +5,7 @@ use super::char_selection::CharSelectionState; use crate::{ window::{Event, Window}, GlobalState, PlayState, PlayStateResult, + singleplayer::Singleplayer, }; use client_init::{ClientInit, Error as InitError}; use common::{clock::Clock, comp}; @@ -101,7 +102,10 @@ impl PlayState for MainMenuState { 300, ), ))); - } + }, + MainMenuEvent::StartSingleplayer => { + global_state.singleplayer = Some(Singleplayer::new()); + }, MainMenuEvent::Quit => return PlayStateResult::Shutdown, } } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 798c386182..1a10e3ad14 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -107,6 +107,7 @@ pub enum Event { username: String, server_address: String, }, + StartSingleplayer, Quit, } @@ -189,6 +190,20 @@ impl MainMenuUi { }); }; } + + //Singleplayer + //Used when the singleplayer button is pressed + macro_rules! singleplayer { + () => { + self.login_error = None; + events.push(Event::StartSingleplayer); + events.push(Event::LoginAttempt { + username: "singleplayer".to_string(), + server_address: "localhost".to_string(), + }); + }; + } + const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0); // Username // TODO: get a lower resolution and cleaner input_bg.png @@ -327,6 +342,7 @@ impl MainMenuUi { .set(self.ids.singleplayer_button, ui_widgets) .was_clicked() { + singleplayer!(); login!(); } // Quit From f494afd70f39035fd33abf7f74dd57c8f004f631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Fri, 19 Apr 2019 00:23:11 +0200 Subject: [PATCH 31/72] first test of ci Former-commit-id: 4fbb5698fc411dbf95c53da74896eb164f540fed --- .gitlab-ci.yml | 238 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..5c02c1aec1 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,238 @@ +#cache: +# paths: +# - target/ + +stages: + - build + - test + - deploy + - post-run + +# our own git fetch command like https://gitlab.com/gitlab-org/gitlab-runner/blob/master/shells/abstract.go +# speeds up building because we skip the git clean and dont need any gitlab caches +variables: + GIT_STRATEGY: none +before_script: + - if [ -d .git ]; then + echo "is git dir"; + else + git clone $CI_REPOSITORY_URL . ; + fi; + - rm -f .git/index.lock + - rm -f .git/shallow.lock + - rm -f .git/HEAD.lock + - rm -f .git/hocks/post-checkout + - git remote set-url origin $CI_REPOSITORY_URL + - git fetch origin --prune +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/* + - git checkout -f -q $CI_COMMIT_SHA + - if [ ! -z "${SOURCE_PROJECT}" -a "${SOURCE_PROJECT}" != " " ]; then + echo "THIS SEEMS TO BE A MERGE PIPELINE FROM ${SOURCE_PROJECT}/${SOURCE_BRANCH}"; + git pull "https://gitlab.com/${SOURCE_PROJECT}/veloren.git" "${SOURCE_BRANCH}"; + fi; + - git submodule update --init --recursive + - git status + - if [ -d target ]; then + ls -la target; + fi; +# - git submodule update --init --recursive + +clean-code: + stage: build + script: + - rustup component add rustfmt-preview + - cargo fmt --all -- --check + allow_failure: true + +build-voxygen: + stage: build + script: + - (cd voxygen && cargo build) + +build-server-cli: + stage: build + script: + - (cd server-cli && cargo build) + +unittests: + stage: test + script: + - cargo test + +#benchmarktests: +# stage: test +# script: +# - cargo bench + +nightly-linux-debug: + stage: deploy + script: + - (cd voxygen && VELOREN_ASSETS=assets cargo build) + - (cd server-cli && VELOREN_ASSETS=assets cargo build) + - rm -r -f nightly + - mkdir nightly + - cp target/debug/server-cli nightly + - cp target/debug/voxygen nightly + - cp -r assets nightly/ + - cp -r voxygen/shaders nightly/ + - cp -r voxygen/fonts nightly/ + - rm -f nightly-linux-debug.tar.bz2 + - tar -cvjSf nightly-linux-debug.tar.bz2 nightly + when: always + artifacts: + paths: + - nightly-linux-debug.tar.bz2 + expire_in: 1 week + only: + refs: + - master + +nightly-windows-debug: + stage: deploy + script: + - (cd voxygen && VELOREN_ASSETS=assets cargo build --target=x86_64-pc-windows-gnu) + - (cd server-cli && VELOREN_ASSETS=assets cargo build --target=x86_64-pc-windows-gnu) + - rm -r -f nightly + - mkdir nightly + - cp target/x86_64-pc-windows-gnu/debug/server-cli.exe nightly + - cp target/x86_64-pc-windows-gnu/debug/voxygen.exe nightly + - cp -r assets nightly/ + - cp -r voxygen/shaders nightly/ + - cp -r voxygen/fonts nightly/ + - rm -f nightly-windows-debug.zip + - zip -r nightly-windows-debug.zip nightly + artifacts: + paths: + - nightly-windows-debug.zip + expire_in: 1 week + only: + refs: + - master + +nightly-linux-optimized: + stage: deploy + script: + - (cd voxygen && VELOREN_ASSETS=assets cargo build --release) + - (cd server-cli && VELOREN_ASSETS=assets cargo build --release) + - rm -r -f nightly + - mkdir nightly + - cp target/release/server-cli nightly + - cp target/release/voxygen nightly + - cp -r assets nightly/ + - cp -r voxygen/shaders nightly/ + - cp -r voxygen/fonts nightly/ + - rm -f nightly-linux-optimized.tar.bz2 + - tar -cvjSf nightly-linux-optimized.tar.bz2 nightly + when: manual + artifacts: + paths: + - nightly-linux-optimized.tar.bz2 + expire_in: 2 days + only: + refs: + - master + +nightly-windows-optimized: + stage: deploy + script: + - (cd voxygen && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) + - (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) + - rm -r -f nightly + - mkdir nightly + - cp target/x86_64-pc-windows-gnu/release/server-cli.exe nightly + - cp target/x86_64-pc-windows-gnu/release/voxygen.exe nightly + - cp -r assets nightly/ + - cp -r voxygen/shaders nightly/ + - cp -r voxygen/fonts nightly/ + - rm -f nightly-windows-optimized.zip + - zip -r nightly-windows-optimized.zip nightly + when: manual + artifacts: + paths: + - nightly-windows-optimized.zip + expire_in: 2 days + only: + refs: + - master + +stable-linux-optimized: + stage: deploy + script: + - (cd voxygen && VELOREN_ASSETS=assets cargo build --release) + - (cd server-cli && VELOREN_ASSETS=assets cargo build --release) + - rm -r -f stable + - mkdir stable + - cp target/release/server-cli stable + - cp target/release/voxygen stable + - cp -r assets nightly/ + - cp -r voxygen/shaders nightly/ + - cp -r voxygen/fonts nightly/ + - rm -f stable-linux-optimized.tar.bz2 + - tar -cvjSf stable-linux-optimized.tar.bz2 stable + artifacts: + paths: + - stable-linux-optimized.tar.bz2 + expire_in: 30d + only: + refs: + - /^v[0-9]+\.[0-9]+\.[0-9]+/ + +stable-windows-optimized: + stage: deploy + script: + - (cd voxygen && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) + - (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) + - rm -r -f stable + - mkdir stable + - cp target/x86_64-pc-windows-gnu/release/server-cli.exe stable + - cp target/x86_64-pc-windows-gnu/release/voxygen.exe stable + - cp -r assets nightly/ + - cp -r voxygen/shaders nightly/ + - cp -r voxygen/fonts nightly/ + - rm -f stable-windows-optimized.zip + - zip -r stable-windows-optimized.zip stable + artifacts: + paths: + - stable-windows-optimized.zip + expire_in: 30d + only: + refs: + - /^v[0-9]+\.[0-9]+\.[0-9]+/ + +# nightly-windows-release: +# stage: deploy +# script: +# - (cd voxygen && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) +# - (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) +# - rm -r -f nightly +# - mkdir nightly +# - cp target/x86_64-pc-windows-gnu/debug/server-cli.exe nightly +# - cp target/x86_64-pc-windows-gnu/debug/voxygen.exe nightly +# - cp -r assets nightly/ +# - cp -r voxygen/shaders nightly/ +# - cp -r voxygen/fonts nightly/ +# - rm -f nightly-windows-release.zip +# - zip -r nightly-windows-release.zip nightly +# artifacts: +# paths: +# - nightly-windows-release.zip +# expire_in: 1 week +# only: +# refs: +# - master + +coverage: + stage: post-run + script: + - if cargo install --list | grep -i "cargo-tarpaulin"; then + echo "tarpaulin already installed"; + else + RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install cargo-tarpaulin; + fi + - cargo tarpaulin --skip-clean --all || echo "There is a problem in tarpaulin which sometimes fails" + +clippy: + stage: post-run + script: + - rustup component add clippy-preview --toolchain=nightly + - cargo clippy --all -- -D clippy || echo "This job is disabled, because we are not activly using it now, so we dont want to see yellow failed partly" + allow_failure: true From 48b4d3cae2dc5881b385956c30e5eb7d881f9d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=A4rtens?= Date: Fri, 19 Apr 2019 01:24:13 +0200 Subject: [PATCH 32/72] fix ci Former-commit-id: 75e3fa7c0811585f200262a2ae3aedc0af683e48 --- .gitlab-ci.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5c02c1aec1..71691d120f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -70,8 +70,8 @@ nightly-linux-debug: - (cd server-cli && VELOREN_ASSETS=assets cargo build) - rm -r -f nightly - mkdir nightly - - cp target/debug/server-cli nightly - - cp target/debug/voxygen nightly + - cp target/debug/veloren-server-cli nightly + - cp target/debug/veloren-voxygen nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - cp -r voxygen/fonts nightly/ @@ -93,8 +93,8 @@ nightly-windows-debug: - (cd server-cli && VELOREN_ASSETS=assets cargo build --target=x86_64-pc-windows-gnu) - rm -r -f nightly - mkdir nightly - - cp target/x86_64-pc-windows-gnu/debug/server-cli.exe nightly - - cp target/x86_64-pc-windows-gnu/debug/voxygen.exe nightly + - cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe nightly + - cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - cp -r voxygen/fonts nightly/ @@ -115,8 +115,8 @@ nightly-linux-optimized: - (cd server-cli && VELOREN_ASSETS=assets cargo build --release) - rm -r -f nightly - mkdir nightly - - cp target/release/server-cli nightly - - cp target/release/voxygen nightly + - cp target/release/veloren-server-cli nightly + - cp target/release/veloren-voxygen nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - cp -r voxygen/fonts nightly/ @@ -138,8 +138,8 @@ nightly-windows-optimized: - (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) - rm -r -f nightly - mkdir nightly - - cp target/x86_64-pc-windows-gnu/release/server-cli.exe nightly - - cp target/x86_64-pc-windows-gnu/release/voxygen.exe nightly + - cp target/x86_64-pc-windows-gnu/release/veloren-server-cli.exe nightly + - cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - cp -r voxygen/fonts nightly/ @@ -161,8 +161,8 @@ stable-linux-optimized: - (cd server-cli && VELOREN_ASSETS=assets cargo build --release) - rm -r -f stable - mkdir stable - - cp target/release/server-cli stable - - cp target/release/voxygen stable + - cp target/release/veloren-server-cli stable + - cp target/release/veloren-voxygen stable - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - cp -r voxygen/fonts nightly/ @@ -183,8 +183,8 @@ stable-windows-optimized: - (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) - rm -r -f stable - mkdir stable - - cp target/x86_64-pc-windows-gnu/release/server-cli.exe stable - - cp target/x86_64-pc-windows-gnu/release/voxygen.exe stable + - cp target/x86_64-pc-windows-gnu/release/veloren-server-cli.exe stable + - cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe stable - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - cp -r voxygen/fonts nightly/ @@ -205,8 +205,8 @@ stable-windows-optimized: # - (cd server-cli && VELOREN_ASSETS=assets cargo build --release --target=x86_64-pc-windows-gnu) # - rm -r -f nightly # - mkdir nightly -# - cp target/x86_64-pc-windows-gnu/debug/server-cli.exe nightly -# - cp target/x86_64-pc-windows-gnu/debug/voxygen.exe nightly +# - cp target/x86_64-pc-windows-gnu/debug/veloren-server-cli.exe nightly +# - cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe nightly # - cp -r assets nightly/ # - cp -r voxygen/shaders nightly/ # - cp -r voxygen/fonts nightly/ From 2e695260692c90c6a54f594ff39f213fe073dbaf Mon Sep 17 00:00:00 2001 From: Imbris Date: Mon, 15 Apr 2019 02:07:56 -0400 Subject: [PATCH 33/72] initial setup for .vox rendering Former-commit-id: bc3d2432c41d9dc3e1f57e569f3aecb9be3fe79a --- Cargo.lock | 42 +++++ voxygen/Cargo.toml | 3 + voxygen/src/hud/mod.rs | 4 +- voxygen/src/menu/char_selection/ui.rs | 2 +- voxygen/src/menu/main/ui.rs | 2 +- voxygen/src/ui/graphic.rs | 92 ++++++++++ voxygen/src/ui/mod.rs | 157 ++++++++++------- voxygen/src/ui/veuc.rs | 241 ++++++++++++++++++++++++++ 8 files changed, 474 insertions(+), 69 deletions(-) create mode 100644 voxygen/src/ui/graphic.rs create mode 100644 voxygen/src/ui/veuc.rs diff --git a/Cargo.lock b/Cargo.lock index 1a1ab9e19a..a21ae7f43d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,6 +461,33 @@ dependencies = [ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "euc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "euclid" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "euclid_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "failure" version = "0.1.5" @@ -668,6 +695,14 @@ dependencies = [ "x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "guillotiere" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hibitset" version = "0.5.4" @@ -1943,12 +1978,15 @@ dependencies = [ "conrod_core 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", "conrod_winit 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", "dot_vox 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "euc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "gfx 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_device_gl 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_window_glutin 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", "glsl-include 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "guillotiere 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2215,6 +2253,9 @@ dependencies = [ "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" +"checksum euc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0151594c4feeeb99ff35ac1b467383a46fcb2705275615bed0a47f25ffe2ccf8" +"checksum euclid 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7a4719a544a67ed3fc33784c2bd2c6581663dfe83b719a6ae05c6dabc3b51c73" +"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" @@ -2238,6 +2279,7 @@ dependencies = [ "checksum gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5" "checksum glsl-include 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31c109a006ad24fd612da10d185b51000ef502155578f3634416f102f0d63b6c" "checksum glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "535c6eda58adbb227604b2db10a022ffd6339d7ea3e970f338e7d98aeb24fcc3" +"checksum guillotiere 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e965c66630b3a0369feafb06d945f15a4f59aaecc209eb1c4a2b57bb48ee06" "checksum hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6527bc88f32e0d3926c7572874b2bf17a19b36978aacd0aacf75f7d27a5992d0" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum image 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "545f000e8aa4e569e93f49c446987133452e0091c2494ac3efd3606aa3d309f2" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index 4b9c11fa2b..a4f2f5875d 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -22,6 +22,7 @@ glutin = "0.19" winit = {version = "0.18", features = ["serde"]} conrod_core = { git = "https://gitlab.com/veloren/conrod.git" } conrod_winit = { git = "https://gitlab.com/veloren/conrod.git" } +euc = "0.2" # ECS specs = "0.14" @@ -41,3 +42,5 @@ config = "0.9" serde = "1.0" serde_derive = "1.0" toml = "0.4" +guillotiere = "0.4" +fnv = "1.0" diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 589b283f85..87b66ae8a6 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -2,7 +2,7 @@ mod chat; use crate::{ render::Renderer, - ui::{ScaleMode, ToggleButton, Ui}, + ui::{self, ScaleMode, ToggleButton, Ui}, window::{Event as WinEvent, Key, Window}, }; use common::assets; @@ -257,7 +257,7 @@ impl Imgs { .as_slice(), ) .unwrap(); - ui.new_image(renderer, &image).unwrap() + ui.new_graphic(ui::Graphic::Image(image)) }; Imgs { // Bag diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index 34ebd08c70..1a2be0245e 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -235,7 +235,7 @@ impl Imgs { .as_slice(), ) .unwrap(); - ui.new_image(renderer, &image).unwrap() + ui.new_graphic(ui::Graphic::Image(image)) }; Imgs { v_logo: load("element/v_logo.png"), diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 1a10e3ad14..41e5b17561 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -74,7 +74,7 @@ impl Imgs { .as_slice(), ) .unwrap(); - ui.new_image(renderer, &image).unwrap() + ui.new_graphic(ui::Graphic::Image(image)) }; Imgs { bg: load("background/bg_main.png"), diff --git a/voxygen/src/ui/graphic.rs b/voxygen/src/ui/graphic.rs new file mode 100644 index 0000000000..8e93f8b168 --- /dev/null +++ b/voxygen/src/ui/graphic.rs @@ -0,0 +1,92 @@ +use common::figure::Segment; +use image::DynamicImage; +use guillotiere::{ + AtlasAllocator, + Allocation, + size2, +}; +use fnv::FnvHashMap; +use vek::*; + +pub enum Graphic { + Image(DynamicImage), + Voxel(Segment), +} +#[derive(PartialEq, Eq, Hash, Copy, Clone)] +pub struct Id(u32); + +type Parameters = (Id, Vec2, Aabr); + +pub struct GraphicCache { + atlas: AtlasAllocator, + graphic_map: FnvHashMap, + rect_map: FnvHashMap>, + next_id: u32, +} +impl GraphicCache { + pub fn new(size: Vec2) -> Self { + Self { + atlas: AtlasAllocator::new(size2(i32::from(size.x), i32::from(size.y))), + graphic_map: FnvHashMap::default(), + rect_map: FnvHashMap::default(), + next_id: 0, + } + } + pub fn new_graphic(&mut self, graphic: Graphic) -> Id { + let id = self.next_id; + self.next_id = id.wrapping_add(1); + + let id = Id(id); + self.graphic_map.insert(id, graphic); + + id + } + pub fn cache_res(&mut self, graphic_id: Id, dims: Vec2, source: Aabr, mut cacher: F) -> Option> where F: FnMut(Aabr, Vec<[u8; 4]>) { + match self.rect_map.get(&(graphic_id, dims, source.map(|e| e.to_bits()))) { //<-------- TODO: Replace this with rounded representation of source + Some(aabr) => Some(*aabr), + None => match self.graphic_map.get(&graphic_id) { + Some(graphic) => { + // Allocate rectangle + let aabr = match self.atlas.allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2))) { + Some(Allocation{id, rectangle}) => { + let (min, max) = (rectangle.min, rectangle.max); + Aabr { + min: Vec2::new(min.x as u16 + 1, min.y as u16 + 1), + max: Vec2::new(max.x as u16 - 1, max.y as u16 - 1), + } + } + // Out of room + // TODO: make more room by 1. expanding cache size, 2. removing unused allocations, 3. rearranging rectangles + None => return None, + }; + + // Render image + // TODO: use source + let data = match graphic { + Graphic::Image(ref image) => { + image + .resize_exact(u32::from(aabr.size().w), u32::from(aabr.size().h), image::FilterType::Nearest) + .to_rgba() + .pixels() + .map(|p| p.data) + .collect::>() + } + Graphic::Voxel(segment) => { + super::veuc::draw_vox(&segment, aabr.size().into()) + } + }; + + // Draw to allocated area + cacher(aabr, data); + + // Insert area into map for retrieval + self.rect_map.insert((graphic_id, dims, source.map(|e| e.to_bits())), aabr); + + // Return area + Some(aabr) + } + None => None, + } + } + } +} \ No newline at end of file diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 4cd1b89da4..e6015af6c0 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -1,7 +1,14 @@ mod widgets; +mod graphic; +mod veuc; pub use widgets::toggle_button::ToggleButton; +pub use graphic::Graphic; +use graphic::{ + GraphicCache, + Id as GraphicId, +}; use image::DynamicImage; use conrod_core::{ Ui as CrUi, @@ -81,9 +88,10 @@ impl Event { } pub struct Cache { - blank_texture: Texture, glyph_cache: GlyphCache<'static>, glyph_cache_tex: Texture, + graphic_cache: graphic::GraphicCache, + graphic_cache_tex: Texture, } // TODO: Should functions be returning UiError instead of Error? @@ -93,23 +101,27 @@ impl Cache { const SCALE_TOLERANCE: f32 = 0.1; const POSITION_TOLERANCE: f32 = 0.1; + let graphic_cache_dims = Vec2::new(w * 4, h * 4); Ok(Self { - blank_texture: renderer.create_texture(&DynamicImage::new_rgba8(1, 1))?, glyph_cache: GlyphCache::builder() .dimensions(w as u32, h as u32) .scale_tolerance(SCALE_TOLERANCE) .position_tolerance(POSITION_TOLERANCE) .build(), glyph_cache_tex: renderer.create_dynamic_texture((w, h).into())?, + graphic_cache: GraphicCache::new(graphic_cache_dims), + graphic_cache_tex: renderer.create_dynamic_texture(graphic_cache_dims)?, }) } - pub fn blank_texture(&self) -> &Texture { &self.blank_texture } pub fn glyph_cache_tex(&self) -> &Texture { &self.glyph_cache_tex } pub fn glyph_cache_mut_and_tex(&mut self) -> (&mut GlyphCache<'static>, &Texture) { (&mut self.glyph_cache, &self.glyph_cache_tex) } + pub fn graphic_cache_tex(&self) -> &Texture { &self.graphic_cache_tex } + pub fn graphic_cache_mut_and_tex(&mut self) -> (&mut GraphicCache, &Texture) { (&mut self.graphic_cache, &self.graphic_cache_tex) } + pub fn new_graphic(&mut self, graphic: Graphic) -> GraphicId { self.graphic_cache.new_graphic(graphic) } } enum DrawKind { - Image(ImgId), + Image, // Text and non-textured geometry Plain, } @@ -121,9 +133,9 @@ enum DrawCommand { Scissor(Aabr), } impl DrawCommand { - fn image(model: Model, img_id: ImgId) -> DrawCommand { + fn image(model: Model) -> DrawCommand { DrawCommand::Draw { - kind: DrawKind::Image(img_id), + kind: DrawKind::Image, model, } } @@ -198,7 +210,7 @@ impl Scale { pub struct Ui { ui: CrUi, - image_map: Map>, + image_map: Map, cache: Cache, // Draw commands for the next render draw_commands: Vec, @@ -230,10 +242,12 @@ impl Ui { self.ui.handle_event(Input::Resize(w, h)); } - pub fn new_image(&mut self, renderer: &mut Renderer, image: &DynamicImage) -> Result { - Ok(self.image_map.insert(renderer.create_texture(image)?)) + pub fn new_graphic(&mut self, graphic: Graphic) -> ImgId { + self.image_map.insert(self.cache.new_graphic(graphic)) } + // TODO: add function that creates a blank graphic + pub fn new_font(&mut self, font: Font) -> FontId { self.ui.fonts.insert(font) } @@ -246,7 +260,7 @@ impl Ui { self.ui.set_widgets() } - // Accepts option so widget can be unfocused + // Accepts Option so widget can be unfocused pub fn focus_widget(&mut self, id: Option) { self.ui.keyboard_capture(match id { Some(id) => id, @@ -259,7 +273,7 @@ impl Ui { self.ui.global_input().current.widget_capturing_keyboard } - // Get whether the a widget besides the window is capturing the mouse + // Get whether a widget besides the window is capturing the mouse pub fn no_widget_capturing_mouse(&self) -> bool { self.ui.global_input().current.widget_capturing_mouse.filter(|id| id != &self.ui.window ).is_none() } @@ -305,7 +319,13 @@ impl Ui { self.draw_commands.clear(); let mut mesh = Mesh::new(); - let mut current_img = None; + // TODO: this could be removed entirely if the draw call just used both textures + enum State { + Image, + Plain, + }; + + let mut current_state = State::Plain; let window_scizzor = default_scissor(renderer); let mut current_scizzor = window_scizzor; @@ -314,9 +334,10 @@ impl Ui { // `Plain` state. macro_rules! switch_to_plain_state { () => { - if let Some(image_id) = current_img.take() { - self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)); + if let State::Image = current_state { + self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap())); mesh.clear(); + current_state = State::Plain; } }; } @@ -324,7 +345,7 @@ impl Ui { let p_scale_factor = self.scale.scale_factor_physical(); while let Some(prim) = primitives.next() { - let Primitive {kind, scizzor, id, rect} = prim; + let Primitive {kind, scizzor, id: _id, rect} = prim; // Check for a change in the scizzor let new_scizzor = { @@ -348,12 +369,12 @@ impl Ui { }; if new_scizzor != current_scizzor { // Finish the current command - match current_img.take() { - None => - self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())), - Some(image_id) => - self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)), - } + self.draw_commands.push(match current_state { + State::Plain => + DrawCommand::plain(renderer.create_model(&mesh).unwrap()), + State::Image => + DrawCommand::image(renderer.create_model(&mesh).unwrap()), + }); mesh.clear(); // Update the scizzor and produce a command. @@ -375,52 +396,58 @@ impl Ui { use conrod_core::render::PrimitiveKind; match kind { PrimitiveKind::Image { image_id, color, source_rect } => { - // Switch to the `Image` state for this image if we're not in it already. - let new_image_id = image_id; - match current_img { - // If we're already in the drawing mode for this image, we're done. - Some(image_id) if image_id == new_image_id => (), - // If we were in the `Plain` drawing state, switch to Image drawing state. - None => { - self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())); - mesh.clear(); - current_img = Some(new_image_id); - } - // If we were drawing a different image, switch state to draw *this* image. - Some(image_id) => { - self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)); - mesh.clear(); - current_img = Some(new_image_id); - } + if let State::Plain = current_state { + self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())); + mesh.clear(); + current_state = State::Image; } let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa()); - // Transform the source rectangle into uv coordinates - let (image_w, image_h) = self.image_map - .get(&image_id) - .expect("Image does not exist in image map") - .get_dimensions() - .map(|e| e as f64) - .into_tuple(); - let (uv_l, uv_r, uv_t, uv_b) = 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) + let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex(); + + let resolution = Vec2::new( + (rect.w() * p_scale_factor) as u16, + (rect.h() * p_scale_factor) 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), } - None => (0.0, 1.0, 0.0, 1.0), }; - let uv = Aabr { - min: Vec2::new(uv_l, uv_b), - max: Vec2::new(uv_r, uv_t), + let graphic_id = self.image_map.get(&image_id).expect("Image does not exist in image map"); + let (cache_w, cache_h) = cache_tex.get_dimensions().map(|e| e as f32).into_tuple(); + + // Cache graphic at particular resolution + let uv_aabr = match graphic_cache.cache_res(*graphic_id, resolution, source_aabr, |aabr, data| { + let offset = aabr.min.into_array(); + let size = aabr.size().into_array(); + renderer.update_texture(cache_tex, offset, size, &data); + }) { + Some(aabr) => Aabr { + min: Vec2::new(aabr.min.x as f32 / cache_w, aabr.max.y as f32 / cache_h), + max: Vec2::new(aabr.max.x as f32 / cache_w, aabr.min.y as f32 / cache_h), + }, + None => continue, }; + mesh.push_quad(create_ui_quad( gl_aabr(rect), - uv, + uv_aabr, color, UiMode::Image, )); @@ -535,12 +562,12 @@ impl Ui { } } // Enter the final command - match current_img { - None => - self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())), - Some(image_id) => - self.draw_commands.push(DrawCommand::image(renderer.create_model(&mesh).unwrap(), image_id)), - } + self.draw_commands.push(match current_state { + State::Plain => + DrawCommand::plain(renderer.create_model(&mesh).unwrap()), + State::Image => + DrawCommand::image(renderer.create_model(&mesh).unwrap()), + }); // Handle window resizing if let Some(new_dims) = self.window_resized.take() { @@ -560,8 +587,8 @@ impl Ui { } DrawCommand::Draw { kind, model } => { let tex = match kind { - DrawKind::Image(image_id) => { - self.image_map.get(&image_id).expect("Image does not exist in image map") + DrawKind::Image => { + self.cache.graphic_cache_tex() } DrawKind::Plain => { self.cache.glyph_cache_tex() diff --git a/voxygen/src/ui/veuc.rs b/voxygen/src/ui/veuc.rs new file mode 100644 index 0000000000..65e95f78af --- /dev/null +++ b/voxygen/src/ui/veuc.rs @@ -0,0 +1,241 @@ +use euc::{ + Pipeline, + rasterizer, + buffer::Buffer2d, + Interpolate, +}; +use common::{ + figure::Segment, + vol::{ + Vox, + SizedVol, + ReadVol, + }, +}; +use vek::*; + + +trait Shader { + type VertExtra; + type VsOut: Clone + Interpolate; + fn vert(&self, v_color: Rgba, v_pos: Vec3, vert_extra: &Self::VertExtra) -> (Vec3, Self::VsOut); + fn frag(&self, vs_out: &Self::VsOut) -> Rgba; +} + +struct Voxel where S: Shader { + mvp: Mat4, + shader: S, +} + +struct SimpleShader; +impl Shader for SimpleShader { + type VertExtra = (); + type VsOut = Rgba; + fn vert(&self, v_color: Rgba, v_pos: Vec3, _: &Self::VertExtra) -> (Vec3, Self::VsOut) { + ( + v_pos, + v_color, + ) + } + fn frag(&self, vs_out: &Self::VsOut) -> Rgba { + *vs_out + } +} + +impl<'a, S> Pipeline for Voxel where S: Shader { + type Vertex = (Vec3, Rgb, S::VertExtra); + type VsOut = S::VsOut; + type Pixel = [u8; 4]; + + #[inline(always)] + fn vert(&self, (v_pos, v_color, v_extra): &Self::Vertex) -> ([f32; 3], Self::VsOut) { + let (pos, out) = self.shader.vert( + srgb_to_linear(Rgba::from_opaque(*v_color)), + Vec3::from(self.mvp * Vec4::from_point(*v_pos)), + v_extra, + ); + ( + pos.into_array(), + out, + ) + } + #[inline(always)] + fn frag(&self, vs_out: &Self::VsOut) -> Self::Pixel { + let color = self.shader.frag(vs_out); + linear_to_srgb(color).map(|e| (e * 255.0) as u8).into_array() + } +} + +pub fn draw_vox(segment: &Segment, output_size: Vec2) -> Vec<[u8; 4]> { + let dims = output_size.map(|e| e as usize).into_array(); + let mut color = Buffer2d::new(dims, [50; 4]); + let mut depth = Buffer2d::new(dims, 1.0); + + let mvp = + Mat4::rotation_y(0.6) * + Mat4::::scaling_3d(1.0 / 14.0) * + Mat4::translation_2d([-14.0, -14.0]) * + Mat4::rotation_x(-std::f32::consts::PI / 2.0 ); + Voxel { + mvp, + shader: SimpleShader, + } + .draw::, _>( + &generate_mesh(segment, Vec3::from(0.0)), + &mut color, + &mut depth, + ); + + // TODO: remove this clone + color.as_ref().to_vec() +} + +type Vert = as Pipeline>::Vertex; + +// TODO: generalise meshing code +fn create_quad( + origin: Vec3, + unit_x: Vec3, + unit_y: Vec3, + //norm: Vec3, + col: Rgb, +) -> [Vert; 6] { + let a = (origin, col, ()); + let b = (origin + unit_x, col, ()); + let c = (origin + unit_x + unit_y, col, ()); + let d = (origin + unit_y, col, ()); + [ + a, b, c, // Tri 1 + c, d, a, // Tri 2 + ] +} +fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { + let mut vertices = Vec::new(); + + for pos in segment.iter_positions() { + if let Some(col) = segment + .get(pos) + .ok() + .and_then(|vox| vox.get_color()) + { + let col = col.map(|e| e as f32 / 255.0); + + // -x + if segment.get(pos - Vec3::unit_x()) + .map(|v| v.is_empty()) + .unwrap_or(true) + { + vertices.extend_from_slice(&create_quad( + offs + pos.map(|e| e as f32) + Vec3::unit_y(), + -Vec3::unit_y(), + Vec3::unit_z(), + //-Vec3::unit_x(), + col, + )); + } + // +x + if segment.get(pos + Vec3::unit_x()) + .map(|v| v.is_empty()) + .unwrap_or(true) + { + vertices.extend_from_slice(&create_quad( + offs + pos.map(|e| e as f32) + Vec3::unit_x(), + Vec3::unit_y(), + Vec3::unit_z(), + //Vec3::unit_x(), + col, + )); + } + // -y + if segment.get(pos - Vec3::unit_y()) + .map(|v| v.is_empty()) + .unwrap_or(true) + { + vertices.extend_from_slice(&create_quad( + offs + pos.map(|e| e as f32), + Vec3::unit_x(), + Vec3::unit_z(), + //-Vec3::unit_y(), + col, + )); + } + // +y + if segment.get(pos + Vec3::unit_y()) + .map(|v| v.is_empty()) + .unwrap_or(true) + { + vertices.extend_from_slice(&create_quad( + offs + pos.map(|e| e as f32) + Vec3::unit_y(), + Vec3::unit_z(), + Vec3::unit_x(), + //Vec3::unit_y(), + col, + )); + } + // -z + if segment.get(pos - Vec3::unit_z()) + .map(|v| v.is_empty()) + .unwrap_or(true) + { + vertices.extend_from_slice(&create_quad( + offs + pos.map(|e| e as f32), + Vec3::unit_y(), + Vec3::unit_x(), + //-Vec3::unit_z(), + col, + )); + } + // +z + if segment.get(pos + Vec3::unit_z()) + .map(|v| v.is_empty()) + .unwrap_or(true) + { + vertices.extend_from_slice(&create_quad( + offs + pos.map(|e| e as f32) + Vec3::unit_z(), + Vec3::unit_x(), + Vec3::unit_y(), + //Vec3::unit_z(), + col, + )); + } + } + } + + vertices +} + +// TODO: put these in utility a module +#[inline(always)] +fn to_linear(x: f32) -> f32 { + if x <= 0.04045 { + x / 12.92 + } else { + ((x + 0.055) / 1.055).powf(2.4) + } +} +#[inline(always)] +fn to_srgb(x: f32) -> f32 { + if x <= 0.0031308 { + x * 12.92 + } else { + x.powf(1.0 / 2.4) * 1.055 - 0.055 + } +} +#[inline(always)] +fn srgb_to_linear(c: Rgba) -> Rgba { + Rgba { + r: to_linear(c.r), + g: to_linear(c.g), + b: to_linear(c.b), + a: c.a, + } +} +#[inline(always)] +fn linear_to_srgb(c: Rgba) -> Rgba { + Rgba { + r: to_srgb(c.r), + g: to_srgb(c.g), + b: to_srgb(c.b), + a: c.a, + } +} \ No newline at end of file From 0b4e268dee59bafc0d62d91b5fc52d54adce7cf1 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 19 Apr 2019 14:14:00 -0400 Subject: [PATCH 34/72] add blank graphic, ao for voxel graphics in the ui Former-commit-id: ceaba13fdd47707a8804886b5db2260a8cbba2f1 --- voxygen/src/hud/mod.rs | 157 ++++++++++++----------- voxygen/src/menu/main/ui.rs | 17 ++- voxygen/src/ui/graphic.rs | 5 + voxygen/src/ui/mod.rs | 13 +- voxygen/src/ui/veuc.rs | 245 ++++++++++++++++++++++-------------- 5 files changed, 255 insertions(+), 182 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 87b66ae8a6..83ab013899 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -144,7 +144,7 @@ widget_ids! { pub(self) struct Imgs { //Missing: ActionBar, Health/Mana/Energy Bar & Char Window BG/Frame //Logo - v_logo: ImgId, + //v_logo: ImgId, // Bag bag: ImgId, bag_hover: ImgId, @@ -249,7 +249,7 @@ pub(self) struct Imgs { } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { - let mut load = |filename| { + let mut load = |filename, ui: &mut Ui| { let fullpath: String = ["/voxygen/", filename].concat(); let image = image::load_from_memory( assets::load(fullpath.as_str()) @@ -261,113 +261,112 @@ impl Imgs { }; Imgs { // Bag - bag: load("element/buttons/bag/closed.png"), - bag_hover: load("element/buttons/bag/closed_hover.png"), - bag_press: load("element/buttons/bag/closed_press.png"), - bag_open: load("element/buttons/bag/open.png"), - bag_open_hover: load("element/buttons/bag/open_hover.png"), - bag_open_press: load("element/buttons/bag/open_press.png"), - bag_contents: load("element/frames/bag.png"), - inv_grid: load("element/frames/inv_grid.png"), - inv_slot: load("element/buttons/inv_slot.png"), + bag: load("element/buttons/bag/closed.png", ui), + bag_hover: load("element/buttons/bag/closed_hover.png", ui), + bag_press: load("element/buttons/bag/closed_press.png", ui), + bag_open: load("element/buttons/bag/open.png", ui), + bag_open_hover: load("element/buttons/bag/open_hover.png", ui), + bag_open_press: load("element/buttons/bag/open_press.png", ui), + bag_contents: load("element/frames/bag.png", ui), + inv_grid: load("element/frames/inv_grid.png", ui), + inv_slot: load("element/buttons/inv_slot.png", ui), // Close button - close_button: load("element/buttons/x.png"), - close_button_hover: load("element/buttons/x_hover.png"), - close_button_press: load("element/buttons/x_press.png"), + close_button: load("element/buttons/x.png", ui), + close_button_hover: load("element/buttons/x_hover.png", ui), + close_button_press: load("element/buttons/x_press.png", ui), // Esc-Menu - esc_bg: load("element/frames/menu.png"), - fireplace: load("element/misc_backgrounds/fireplace.png"), - button_dark: load("element/buttons/button_dark.png"), - button_dark_hover: load("element/buttons/button_dark_hover.png"), - button_dark_press: load("element/buttons/button_dark_press.png"), + esc_bg: load("element/frames/menu.png", ui), + fireplace: load("element/misc_backgrounds/fireplace.png", ui), + button_dark: load("element/buttons/button_dark.png", ui), + button_dark_hover: load("element/buttons/button_dark_hover.png", ui), + button_dark_press: load("element/buttons/button_dark_press.png", ui), // MiniMap - mmap_frame: load("element/frames/mmap.png"), - mmap_frame_bg: load("element/misc_backgrounds/mmap_bg.png"), - mmap_icons: load("element/buttons/mmap_icons.png"), + mmap_frame: load("element/frames/mmap.png", ui), + mmap_frame_bg: load("element/misc_backgrounds/mmap_bg.png", ui), + mmap_icons: load("element/buttons/mmap_icons.png", ui), // Settings at Mini-Map - mmap_button: load("element/buttons/border.png"), - mmap_button_hover: load("element/buttons/border_mo.png"), - mmap_button_press: load("element/buttons/border_press.png"), - mmap_button_open: load("element/buttons/border_pressed.png"), + mmap_button: load("element/buttons/border.png", ui), + mmap_button_hover: load("element/buttons/border_mo.png", ui), + mmap_button_press: load("element/buttons/border_press.png", ui), + mmap_button_open: load("element/buttons/border_pressed.png", ui), // Skillbar Module - sb_grid: load("element/skill_bar/sbar_grid.png"), - sb_grid_bg: load("element/skill_bar/sbar_grid_bg.png"), - l_click: load("element/skill_bar/l.png"), - r_click: load("element/skill_bar/r.png"), - mana_bar: load("element/skill_bar/mana_bar.png"), - health_bar: load("element/skill_bar/health_bar.png"), - xp_bar: load("element/skill_bar/xp_bar.png"), + sb_grid: load("element/skill_bar/sbar_grid.png", ui), + sb_grid_bg: load("element/skill_bar/sbar_grid_bg.png", ui), + l_click: load("element/skill_bar/l.png", ui), + r_click: load("element/skill_bar/r.png", ui), + mana_bar: load("element/skill_bar/mana_bar.png", ui), + health_bar: load("element/skill_bar/health_bar.png", ui), + xp_bar: load("element/skill_bar/xp_bar.png", ui), //Buff Frame(s) - //buff_frame: load("element/skill_bar/buff_frame.png"), - //buff_frame_bg: load("element/skill_bar/buff_frame_bg.png"), - //buff_frame_red: load("element/skill_bar/buff_frame_red.png"), - //buff_frame_green: load("element/skill_bar/buff_frame_green.png"), + //buff_frame: load("element/skill_bar/buff_frame.png", ui), + //buff_frame_bg: load("element/skill_bar/buff_frame_bg.png", ui), + //buff_frame_red: load("element/skill_bar/buff_frame_red.png", ui), + //buff_frame_green: load("element/skill_bar/buff_frame_green.png", ui), //Missing: Buff Frame Animation (.gif ?!) (we could do animation in ui.maintain(), or in shader?) - window_frame: load("element/frames/window.png"), - window_frame_2: load("element/frames/window_2.png"), + window_frame: load("element/frames/window.png", ui), + window_frame_2: load("element/frames/window_2.png", ui), //Settings Window - settings_bg: load("element/frames/settings.png"), - settings_icon: load("element/icons/settings.png"), - settings_button_mo: load("element/buttons/blue_mo.png"), - check: load("element/buttons/check/no.png"), - check_mo: load("element/buttons/check/no_mo.png"), - check_press: load("element/buttons/check/press.png"), - check_checked: load("element/buttons/check/yes.png"), - check_checked_mo: load("element/buttons/check/yes_mo.png"), - slider: load("element/slider/track.png"), - slider_indicator: load("element/slider/indicator.png"), - button_blank: load("element/nothing.png"), - button_blue_mo: load("element/buttons/blue_mo.png"), - button_blue_press: load("element/buttons/blue_press.png"), + settings_bg: load("element/frames/settings.png", ui), + settings_icon: load("element/icons/settings.png", ui), + settings_button_mo: load("element/buttons/blue_mo.png", ui), + check: load("element/buttons/check/no.png", ui), + check_mo: load("element/buttons/check/no_mo.png", ui), + check_press: load("element/buttons/check/press.png", ui), + check_checked: load("element/buttons/check/yes.png", ui), + check_checked_mo: load("element/buttons/check/yes_mo.png", ui), + slider: load("element/slider/track.png", ui), + slider_indicator: load("element/slider/indicator.png", ui), + button_blank: ui.new_graphic(ui::Graphic::Blank), + button_blue_mo: load("element/buttons/blue_mo.png", ui), + button_blue_press: load("element/buttons/blue_press.png", ui), // Window BG - window_bg: load("element/misc_backgrounds/window_bg.png"), - v_logo: load("element/v_logo.png"), + window_bg: load("element/misc_backgrounds/window_bg.png", ui), //Social Window - social_bg: load("element/misc_backgrounds/small_bg.png"), - social_icon: load("element/icons/social.png"), + social_bg: load("element/misc_backgrounds/small_bg.png", ui), + social_icon: load("element/icons/social.png", ui), //Map Window - map_bg: load("element/misc_backgrounds/small_bg.png"), - map_icon: load("element/icons/map.png"), - map_frame: load("element/frames/window_map.png"), + map_bg: load("element/misc_backgrounds/small_bg.png", ui), + map_icon: load("element/icons/map.png", ui), + map_frame: load("element/frames/window_map.png", ui), // Spell Book Window - spellbook_bg: load("element/misc_backgrounds/small_bg.png"), - spellbook_icon: load("element/icons/spellbook.png"), + spellbook_bg: load("element/misc_backgrounds/small_bg.png", ui), + spellbook_icon: load("element/icons/spellbook.png", ui), //Char Window - charwindow: load("element/misc_backgrounds/charwindow.png"), - charwindow_icon: load("element/icons/charwindow.png"), - charwindow_tab_bg: load("element/frames/tab.png"), - charwindow_tab: load("element/buttons/tab.png"), - charwindow_expbar: load("element/misc_backgrounds/small_bg.png"), - progress_frame: load("element/frames/progress_bar.png"), - progress: load("element/misc_backgrounds/progress.png"), + charwindow: load("element/misc_backgrounds/charwindow.png", ui), + charwindow_icon: load("element/icons/charwindow.png", ui), + charwindow_tab_bg: load("element/frames/tab.png", ui), + charwindow_tab: load("element/buttons/tab.png", ui), + charwindow_expbar: load("element/misc_backgrounds/small_bg.png", ui), + progress_frame: load("element/frames/progress_bar.png", ui), + progress: load("element/misc_backgrounds/progress.png", ui), //Quest-Log Window - questlog_bg: load("element/misc_backgrounds/small_bg.png"), - questlog_icon: load("element/icons/questlog.png"), + questlog_bg: load("element/misc_backgrounds/small_bg.png", ui), + questlog_icon: load("element/icons/questlog.png", ui), // Chat-Arrows - chat_arrow: load("element/buttons/arrow/chat_arrow.png"), - chat_arrow_mo: load("element/buttons/arrow/chat_arrow_mo.png"), - chat_arrow_press: load("element/buttons/arrow/chat_arrow_press.png"), - chat_arrow_up: load("element/buttons/arrow/chat_arrow_up.png"), - chat_arrow_up_mo: load("element/buttons/arrow/chat_arrow_up_mo.png"), - chat_arrow_up_press: load("element/buttons/arrow/chat_arrow_up_press.png"), - chat_arrow_down: load("element/buttons/arrow/chat_arrow_down.png"), - chat_arrow_down_mo: load("element/buttons/arrow/chat_arrow_down_mo.png"), - chat_arrow_down_press: load("element/buttons/arrow/chat_arrow_down_press.png"), + chat_arrow: load("element/buttons/arrow/chat_arrow.png", ui), + chat_arrow_mo: load("element/buttons/arrow/chat_arrow_mo.png", ui), + chat_arrow_press: load("element/buttons/arrow/chat_arrow_press.png", ui), + chat_arrow_up: load("element/buttons/arrow/chat_arrow_up.png", ui), + chat_arrow_up_mo: load("element/buttons/arrow/chat_arrow_up_mo.png", ui), + chat_arrow_up_press: load("element/buttons/arrow/chat_arrow_up_press.png", ui), + chat_arrow_down: load("element/buttons/arrow/chat_arrow_down.png", ui), + chat_arrow_down_mo: load("element/buttons/arrow/chat_arrow_down_mo.png", ui), + chat_arrow_down_press: load("element/buttons/arrow/chat_arrow_down_press.png", ui), } } } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 41e5b17561..ee80b48c7c 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -4,7 +4,10 @@ use crate::{ window::Window, DEFAULT_PUBLIC_SERVER, }; -use common::assets; +use common::{ + assets, + figure::Segment, +}; use conrod_core::{ color, color::TRANSPARENT, @@ -41,6 +44,7 @@ widget_ids! { // Error error_frame, button_ok, + test_vox, } } @@ -62,10 +66,13 @@ struct Imgs { button_dark: ImgId, button_dark_hover: ImgId, button_dark_press: ImgId, + test_vox: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { - // TODO: update paths + fn load_segment(filename: &'static str) -> Segment { + Segment::from(dot_vox::load(&(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/voxygen/").to_string() + filename)).unwrap()) + } let mut load = |filename| { let fullpath: String = ["/voxygen/", filename].concat(); let image = image::load_from_memory( @@ -98,6 +105,7 @@ impl Imgs { button_dark: load("element/buttons/button_dark.png"), button_dark_hover: load("element/buttons/button_dark_hover.png"), button_dark_press: load("element/buttons/button_dark_press.png"), + test_vox: ui.new_graphic(ui::Graphic::Voxel(load_segment("test.vox"))), } } } @@ -178,6 +186,11 @@ impl MainMenuUi { .label_x(Relative::Scalar(-100.0)) .set(self.ids.v_logo, ui_widgets); + Image::new(self.imgs.test_vox) + .w_h(750.0, 750.0) + .top_right_with_margins_on(self.ids.bg, 50.0, 50.0) + .set(self.ids.test_vox, ui_widgets); + // Input fields // Used when the login button is pressed, or enter is pressed within input field macro_rules! login { diff --git a/voxygen/src/ui/graphic.rs b/voxygen/src/ui/graphic.rs index 8e93f8b168..0affe2012f 100644 --- a/voxygen/src/ui/graphic.rs +++ b/voxygen/src/ui/graphic.rs @@ -11,6 +11,7 @@ use vek::*; pub enum Graphic { Image(DynamicImage), Voxel(Segment), + Blank, } #[derive(PartialEq, Eq, Hash, Copy, Clone)] pub struct Id(u32); @@ -41,6 +42,9 @@ impl GraphicCache { id } + pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { + self.graphic_map.get(&id) + } pub fn cache_res(&mut self, graphic_id: Id, dims: Vec2, source: Aabr, mut cacher: F) -> Option> where F: FnMut(Aabr, Vec<[u8; 4]>) { match self.rect_map.get(&(graphic_id, dims, source.map(|e| e.to_bits()))) { //<-------- TODO: Replace this with rounded representation of source Some(aabr) => Some(*aabr), @@ -74,6 +78,7 @@ impl GraphicCache { Graphic::Voxel(segment) => { super::veuc::draw_vox(&segment, aabr.size().into()) } + Graphic::Blank => return None, }; // Draw to allocated area diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index e6015af6c0..f91c83934a 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -246,8 +246,6 @@ impl Ui { self.image_map.insert(self.cache.new_graphic(graphic)) } - // TODO: add function that creates a blank graphic - pub fn new_font(&mut self, font: Font) -> FontId { self.ui.fonts.insert(font) } @@ -320,6 +318,7 @@ impl Ui { let mut mesh = Mesh::new(); // TODO: this could be removed entirely if the draw call just used both textures + // however this allows for flexibility if we want to interleave other draw calls later enum State { Image, Plain, @@ -396,6 +395,14 @@ impl Ui { use conrod_core::render::PrimitiveKind; match kind { PrimitiveKind::Image { image_id, color, source_rect } => { + let graphic_id = self.image_map.get(&image_id).expect("Image does not exist in image map"); + let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex(); + + match graphic_cache.get_graphic(*graphic_id) { + Some(Graphic::Blank) | None => continue, + _ => {} + } + // Switch to the `Image` state for this image if we're not in it already. if let State::Plain = current_state { self.draw_commands.push(DrawCommand::plain(renderer.create_model(&mesh).unwrap())); @@ -405,7 +412,6 @@ impl Ui { let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa()); - let (graphic_cache, cache_tex) = self.cache.graphic_cache_mut_and_tex(); let resolution = Vec2::new( (rect.w() * p_scale_factor) as u16, @@ -429,7 +435,6 @@ impl Ui { max: Vec2::new(uv_r, uv_t), } }; - let graphic_id = self.image_map.get(&image_id).expect("Image does not exist in image map"); let (cache_w, cache_h) = cache_tex.get_dimensions().map(|e| e as f32).into_tuple(); // Cache graphic at particular resolution diff --git a/voxygen/src/ui/veuc.rs b/voxygen/src/ui/veuc.rs index 65e95f78af..6f89dae2fd 100644 --- a/voxygen/src/ui/veuc.rs +++ b/voxygen/src/ui/veuc.rs @@ -15,54 +15,43 @@ use common::{ use vek::*; -trait Shader { - type VertExtra; - type VsOut: Clone + Interpolate; - fn vert(&self, v_color: Rgba, v_pos: Vec3, vert_extra: &Self::VertExtra) -> (Vec3, Self::VsOut); - fn frag(&self, vs_out: &Self::VsOut) -> Rgba; -} - -struct Voxel where S: Shader { +struct Voxel { mvp: Mat4, - shader: S, } -struct SimpleShader; -impl Shader for SimpleShader { - type VertExtra = (); +#[derive(Copy, Clone)] +struct Vert { + pos: Vec3, + col: Rgb, + norm: Vec3, + ao_level: u8, +} +impl Vert { + fn new(pos: Vec3, col: Rgb, norm: Vec3, ao_level: u8) -> Self { + Vert { + pos, + col, + norm, + ao_level, + } + } +} + +impl<'a> Pipeline for Voxel { + type Vertex = Vert; type VsOut = Rgba; - fn vert(&self, v_color: Rgba, v_pos: Vec3, _: &Self::VertExtra) -> (Vec3, Self::VsOut) { - ( - v_pos, - v_color, - ) - } - fn frag(&self, vs_out: &Self::VsOut) -> Rgba { - *vs_out - } -} - -impl<'a, S> Pipeline for Voxel where S: Shader { - type Vertex = (Vec3, Rgb, S::VertExtra); - type VsOut = S::VsOut; type Pixel = [u8; 4]; #[inline(always)] - fn vert(&self, (v_pos, v_color, v_extra): &Self::Vertex) -> ([f32; 3], Self::VsOut) { - let (pos, out) = self.shader.vert( - srgb_to_linear(Rgba::from_opaque(*v_color)), - Vec3::from(self.mvp * Vec4::from_point(*v_pos)), - v_extra, - ); - ( - pos.into_array(), - out, - ) + fn vert(&self, Vert { pos, col, norm, ao_level}: &Self::Vertex) -> ([f32; 3], Self::VsOut) { + let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25)); + let color = light * srgb_to_linear(Rgba::from_opaque(*col)); + let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array(); + (position, color) } #[inline(always)] - fn frag(&self, vs_out: &Self::VsOut) -> Self::Pixel { - let color = self.shader.frag(vs_out); - linear_to_srgb(color).map(|e| (e * 255.0) as u8).into_array() + fn frag(&self, color: &Self::VsOut) -> Self::Pixel { + linear_to_srgb(*color).map(|e| (e * 255.0) as u8).into_array() } } @@ -71,14 +60,17 @@ pub fn draw_vox(segment: &Segment, output_size: Vec2) -> Vec<[u8; 4]> { let mut color = Buffer2d::new(dims, [50; 4]); let mut depth = Buffer2d::new(dims, 1.0); + let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple(); + let mvp = - Mat4::rotation_y(0.6) * - Mat4::::scaling_3d(1.0 / 14.0) * - Mat4::translation_2d([-14.0, -14.0]) * - Mat4::rotation_x(-std::f32::consts::PI / 2.0 ); + Mat4::::orthographic_rh_no(FrustumPlanes { + left: -1.0, right: 1.0, bottom: -1.0, top: 1.0, + near: 0.0, far: 1.0 + }) * + Mat4::scaling_3d(2.0 / w.max(h)) * + Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]); Voxel { mvp, - shader: SimpleShader, } .draw::, _>( &generate_mesh(segment, Vec3::from(0.0)), @@ -90,25 +82,46 @@ pub fn draw_vox(segment: &Segment, output_size: Vec2) -> Vec<[u8; 4]> { color.as_ref().to_vec() } -type Vert = as Pipeline>::Vertex; - -// TODO: generalise meshing code +fn ao_level(side1: bool, corner: bool, side2: bool) -> u8 { + if side1 && side2 { + 0 + } else { + 3 - [side1, corner, side2].iter().filter(|e| **e).count() as u8 + } +} +// TODO: generalize meshing code.... fn create_quad( origin: Vec3, unit_x: Vec3, unit_y: Vec3, - //norm: Vec3, + norm: Vec3, col: Rgb, + occluders: [bool; 8], ) -> [Vert; 6] { - let a = (origin, col, ()); - let b = (origin + unit_x, col, ()); - let c = (origin + unit_x + unit_y, col, ()); - let d = (origin + unit_y, col, ()); + + let a_ao = ao_level(occluders[0], occluders[1], occluders[2]); + let b_ao = ao_level(occluders[2], occluders[3], occluders[4]); + let c_ao = ao_level(occluders[4], occluders[5], occluders[6]); + let d_ao = ao_level(occluders[6], occluders[7], occluders[0]); + + let a = Vert::new(origin, col, norm, a_ao); + let b = Vert::new(origin + unit_x, col, norm, b_ao); + let c = Vert::new(origin + unit_x + unit_y, col, norm, c_ao); + let d = Vert::new(origin + unit_y, col, norm, d_ao); + + // Flip to fix anisotropy + let (a, b, c, d) = if a_ao + c_ao > b_ao + d_ao { + (d, a, b, c) + } else { + (a, b, c, d) + }; + [ a, b, c, // Tri 1 c, d, a, // Tri 2 ] } + fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { let mut vertices = Vec::new(); @@ -120,82 +133,120 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { { let col = col.map(|e| e as f32 / 255.0); + let is_empty = |pos| { + segment.get(pos) + .map(|v| v.is_empty()) + .unwrap_or(true) + }; + + let occluders = |unit_x, unit_y, dir| { + // would be nice to generate unit_x and unit_y from a given direction + [ + !is_empty(pos + dir - unit_x), + !is_empty(pos + dir - unit_x - unit_y), + !is_empty(pos + dir - unit_y), + !is_empty(pos + dir + unit_x - unit_y), + !is_empty(pos + dir + unit_x), + !is_empty(pos + dir + unit_x + unit_y), + !is_empty(pos + dir + unit_y), + !is_empty(pos + dir - unit_x + unit_y), + ] + }; + // -x - if segment.get(pos - Vec3::unit_x()) - .map(|v| v.is_empty()) - .unwrap_or(true) + if is_empty(pos - Vec3::unit_x()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_y(), -Vec3::unit_y(), Vec3::unit_z(), - //-Vec3::unit_x(), + -Vec3::unit_x(), col, + occluders( + -Vec3::unit_y(), + Vec3::unit_z(), + -Vec3::unit_x(), + ), )); } // +x - if segment.get(pos + Vec3::unit_x()) - .map(|v| v.is_empty()) - .unwrap_or(true) + if is_empty(pos + Vec3::unit_x()) { - vertices.extend_from_slice(&create_quad( + vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z(), - //Vec3::unit_x(), + Vec3::unit_x(), col, + occluders( + Vec3::unit_y(), + Vec3::unit_z(), + Vec3::unit_x(), + ), )); } // -y - if segment.get(pos - Vec3::unit_y()) - .map(|v| v.is_empty()) - .unwrap_or(true) + if is_empty(pos - Vec3::unit_y()) { - vertices.extend_from_slice(&create_quad( + vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32), Vec3::unit_x(), Vec3::unit_z(), - //-Vec3::unit_y(), + -Vec3::unit_y(), col, + occluders( + Vec3::unit_x(), + Vec3::unit_z(), + -Vec3::unit_y(), + ), )); } // +y - if segment.get(pos + Vec3::unit_y()) - .map(|v| v.is_empty()) - .unwrap_or(true) + if is_empty(pos + Vec3::unit_y()) { - vertices.extend_from_slice(&create_quad( + vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_y(), Vec3::unit_z(), Vec3::unit_x(), - //Vec3::unit_y(), + Vec3::unit_y(), col, + occluders( + Vec3::unit_z(), + Vec3::unit_x(), + Vec3::unit_y(), + ), )); } // -z - if segment.get(pos - Vec3::unit_z()) - .map(|v| v.is_empty()) - .unwrap_or(true) + if is_empty(pos - Vec3::unit_z()) { - vertices.extend_from_slice(&create_quad( + vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32), Vec3::unit_y(), Vec3::unit_x(), - //-Vec3::unit_z(), + -Vec3::unit_z(), col, + occluders( + Vec3::unit_y(), + Vec3::unit_x(), + -Vec3::unit_z(), + ), )); } // +z - if segment.get(pos + Vec3::unit_z()) - .map(|v| v.is_empty()) - .unwrap_or(true) + if is_empty(pos + Vec3::unit_z()) { - vertices.extend_from_slice(&create_quad( + vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_z(), Vec3::unit_x(), Vec3::unit_y(), - //Vec3::unit_z(), + Vec3::unit_z(), col, + occluders( + Vec3::unit_x(), + Vec3::unit_y(), + Vec3::unit_z(), + ), )); } } @@ -206,23 +257,15 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { // TODO: put these in utility a module #[inline(always)] -fn to_linear(x: f32) -> f32 { - if x <= 0.04045 { - x / 12.92 - } else { - ((x + 0.055) / 1.055).powf(2.4) - } -} -#[inline(always)] -fn to_srgb(x: f32) -> f32 { - if x <= 0.0031308 { - x * 12.92 - } else { - x.powf(1.0 / 2.4) * 1.055 - 0.055 - } -} -#[inline(always)] fn srgb_to_linear(c: Rgba) -> Rgba { + #[inline(always)] + fn to_linear(x: f32) -> f32 { + if x <= 0.04045 { + x / 12.92 + } else { + ((x + 0.055) / 1.055).powf(2.4) + } + } Rgba { r: to_linear(c.r), g: to_linear(c.g), @@ -232,6 +275,14 @@ fn srgb_to_linear(c: Rgba) -> Rgba { } #[inline(always)] fn linear_to_srgb(c: Rgba) -> Rgba { + #[inline(always)] + fn to_srgb(x: f32) -> f32 { + if x <= 0.0031308 { + x * 12.92 + } else { + x.powf(1.0 / 2.4) * 1.055 - 0.055 + } + } Rgba { r: to_srgb(c.r), g: to_srgb(c.g), From 7707636c4ebcd71df3af9fbea16bba14cd86a1e5 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 19 Apr 2019 14:55:38 -0400 Subject: [PATCH 35/72] rearrange ui graphic code Former-commit-id: d0ea7feee59a1daf4ad93e9b9224750deb75ee45 --- voxygen/src/render/pipelines/ui.rs | 8 +- voxygen/src/ui/{ => graphic}/graphic.rs | 59 ++++--- voxygen/src/ui/graphic/mod.rs | 4 + .../src/ui/{veuc.rs => graphic/renderer.rs} | 155 +++++------------- voxygen/src/ui/mod.rs | 33 ++-- voxygen/src/ui/util.rs | 36 ++++ 6 files changed, 132 insertions(+), 163 deletions(-) rename voxygen/src/ui/{ => graphic}/graphic.rs (62%) create mode 100644 voxygen/src/ui/graphic/mod.rs rename voxygen/src/ui/{veuc.rs => graphic/renderer.rs} (61%) create mode 100644 voxygen/src/ui/util.rs diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 0f3a3b4800..0c2147c667 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -65,13 +65,13 @@ impl Mode { } } -pub fn create_quad(rect: Aabr, uv_rect: Aabr, color: [f32; 4], mode: Mode) -> Quad { +pub fn create_quad(rect: Aabr, uv_rect: Aabr, color: Rgba, mode: Mode) -> Quad { let mode_val = mode.value(); let v = |pos, uv| { Vertex { pos, uv, - color, + color: color.into_array(), mode: mode_val, } }; @@ -90,13 +90,13 @@ pub fn create_quad(rect: Aabr, uv_rect: Aabr, color: [f32; 4], mode: M ) } -pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: [f32; 4], mode: Mode) -> Tri { +pub fn create_tri(tri: [[f32; 2]; 3], uv_tri: [[f32; 2]; 3], color: Rgba, mode: Mode) -> Tri { let mode_val = mode.value(); let v = |pos, uv| { Vertex { pos, uv, - color, + color: color.into_array(), mode: mode_val, } }; diff --git a/voxygen/src/ui/graphic.rs b/voxygen/src/ui/graphic/graphic.rs similarity index 62% rename from voxygen/src/ui/graphic.rs rename to voxygen/src/ui/graphic/graphic.rs index 0affe2012f..0a53580a67 100644 --- a/voxygen/src/ui/graphic.rs +++ b/voxygen/src/ui/graphic/graphic.rs @@ -1,11 +1,7 @@ use common::figure::Segment; -use image::DynamicImage; -use guillotiere::{ - AtlasAllocator, - Allocation, - size2, -}; use fnv::FnvHashMap; +use guillotiere::{size2, Allocation, AtlasAllocator}; +use image::DynamicImage; use vek::*; pub enum Graphic { @@ -45,14 +41,30 @@ impl GraphicCache { pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { self.graphic_map.get(&id) } - pub fn cache_res(&mut self, graphic_id: Id, dims: Vec2, source: Aabr, mut cacher: F) -> Option> where F: FnMut(Aabr, Vec<[u8; 4]>) { - match self.rect_map.get(&(graphic_id, dims, source.map(|e| e.to_bits()))) { //<-------- TODO: Replace this with rounded representation of source + pub fn cache_res( + &mut self, + graphic_id: Id, + dims: Vec2, + source: Aabr, + mut cacher: F, + ) -> Option> + where + F: FnMut(Aabr, Vec<[u8; 4]>), + { + match self + .rect_map + .get(&(graphic_id, dims, source.map(|e| e.to_bits()))) + { + //<-------- TODO: Replace this with rounded representation of source Some(aabr) => Some(*aabr), None => match self.graphic_map.get(&graphic_id) { Some(graphic) => { // Allocate rectangle - let aabr = match self.atlas.allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2))) { - Some(Allocation{id, rectangle}) => { + let aabr = match self + .atlas + .allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2))) + { + Some(Allocation { id, rectangle }) => { let (min, max) = (rectangle.min, rectangle.max); Aabr { min: Vec2::new(min.x as u16 + 1, min.y as u16 + 1), @@ -67,16 +79,18 @@ impl GraphicCache { // Render image // TODO: use source let data = match graphic { - Graphic::Image(ref image) => { - image - .resize_exact(u32::from(aabr.size().w), u32::from(aabr.size().h), image::FilterType::Nearest) - .to_rgba() - .pixels() - .map(|p| p.data) - .collect::>() - } + Graphic::Image(ref image) => image + .resize_exact( + u32::from(aabr.size().w), + u32::from(aabr.size().h), + image::FilterType::Nearest, + ) + .to_rgba() + .pixels() + .map(|p| p.data) + .collect::>(), Graphic::Voxel(segment) => { - super::veuc::draw_vox(&segment, aabr.size().into()) + super::renderer::draw_vox(&segment, aabr.size().into()) } Graphic::Blank => return None, }; @@ -85,13 +99,14 @@ impl GraphicCache { cacher(aabr, data); // Insert area into map for retrieval - self.rect_map.insert((graphic_id, dims, source.map(|e| e.to_bits())), aabr); + self.rect_map + .insert((graphic_id, dims, source.map(|e| e.to_bits())), aabr); // Return area Some(aabr) } None => None, - } + }, } } -} \ No newline at end of file +} diff --git a/voxygen/src/ui/graphic/mod.rs b/voxygen/src/ui/graphic/mod.rs new file mode 100644 index 0000000000..a7b96f903f --- /dev/null +++ b/voxygen/src/ui/graphic/mod.rs @@ -0,0 +1,4 @@ +mod graphic; +mod renderer; + +pub use graphic::{Graphic, GraphicCache, Id}; diff --git a/voxygen/src/ui/veuc.rs b/voxygen/src/ui/graphic/renderer.rs similarity index 61% rename from voxygen/src/ui/veuc.rs rename to voxygen/src/ui/graphic/renderer.rs index 6f89dae2fd..36aecf47f4 100644 --- a/voxygen/src/ui/veuc.rs +++ b/voxygen/src/ui/graphic/renderer.rs @@ -1,20 +1,11 @@ -use euc::{ - Pipeline, - rasterizer, - buffer::Buffer2d, - Interpolate, -}; +use super::super::{linear_to_srgb, srgb_to_linear}; use common::{ figure::Segment, - vol::{ - Vox, - SizedVol, - ReadVol, - }, + vol::{ReadVol, SizedVol, Vox}, }; +use euc::{buffer::Buffer2d, rasterizer, Pipeline}; use vek::*; - struct Voxel { mvp: Mat4, } @@ -43,15 +34,25 @@ impl<'a> Pipeline for Voxel { type Pixel = [u8; 4]; #[inline(always)] - fn vert(&self, Vert { pos, col, norm, ao_level}: &Self::Vertex) -> ([f32; 3], Self::VsOut) { - let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25)); + fn vert( + &self, + Vert { + pos, + col, + norm, + ao_level, + }: &Self::Vertex, + ) -> ([f32; 3], Self::VsOut) { + let light = Rgba::from_opaque(Rgb::from(*ao_level as f32 / 4.0 + 0.25)); let color = light * srgb_to_linear(Rgba::from_opaque(*col)); let position = Vec3::from(self.mvp * Vec4::from_point(*pos)).into_array(); (position, color) } #[inline(always)] fn frag(&self, color: &Self::VsOut) -> Self::Pixel { - linear_to_srgb(*color).map(|e| (e * 255.0) as u8).into_array() + linear_to_srgb(*color) + .map(|e| (e * 255.0) as u8) + .into_array() } } @@ -62,17 +63,16 @@ pub fn draw_vox(segment: &Segment, output_size: Vec2) -> Vec<[u8; 4]> { let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple(); - let mvp = - Mat4::::orthographic_rh_no(FrustumPlanes { - left: -1.0, right: 1.0, bottom: -1.0, top: 1.0, - near: 0.0, far: 1.0 - }) * - Mat4::scaling_3d(2.0 / w.max(h)) * - Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]); - Voxel { - mvp, - } - .draw::, _>( + let mvp = Mat4::::orthographic_rh_no(FrustumPlanes { + left: -1.0, + right: 1.0, + bottom: -1.0, + top: 1.0, + near: 0.0, + far: 1.0, + }) * Mat4::scaling_3d(2.0 / w.max(h)) + * Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]); + Voxel { mvp }.draw::, _>( &generate_mesh(segment, Vec3::from(0.0)), &mut color, &mut depth, @@ -98,7 +98,6 @@ fn create_quad( col: Rgb, occluders: [bool; 8], ) -> [Vert; 6] { - let a_ao = ao_level(occluders[0], occluders[1], occluders[2]); let b_ao = ao_level(occluders[2], occluders[3], occluders[4]); let c_ao = ao_level(occluders[4], occluders[5], occluders[6]); @@ -126,18 +125,10 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { let mut vertices = Vec::new(); for pos in segment.iter_positions() { - if let Some(col) = segment - .get(pos) - .ok() - .and_then(|vox| vox.get_color()) - { + if let Some(col) = segment.get(pos).ok().and_then(|vox| vox.get_color()) { let col = col.map(|e| e as f32 / 255.0); - let is_empty = |pos| { - segment.get(pos) - .map(|v| v.is_empty()) - .unwrap_or(true) - }; + let is_empty = |pos| segment.get(pos).map(|v| v.is_empty()).unwrap_or(true); let occluders = |unit_x, unit_y, dir| { // would be nice to generate unit_x and unit_y from a given direction @@ -154,99 +145,69 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { }; // -x - if is_empty(pos - Vec3::unit_x()) - { + if is_empty(pos - Vec3::unit_x()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_y(), -Vec3::unit_y(), Vec3::unit_z(), -Vec3::unit_x(), col, - occluders( - -Vec3::unit_y(), - Vec3::unit_z(), - -Vec3::unit_x(), - ), + occluders(-Vec3::unit_y(), Vec3::unit_z(), -Vec3::unit_x()), )); } // +x - if is_empty(pos + Vec3::unit_x()) - { + if is_empty(pos + Vec3::unit_x()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z(), Vec3::unit_x(), col, - occluders( - Vec3::unit_y(), - Vec3::unit_z(), - Vec3::unit_x(), - ), + occluders(Vec3::unit_y(), Vec3::unit_z(), Vec3::unit_x()), )); } // -y - if is_empty(pos - Vec3::unit_y()) - { + if is_empty(pos - Vec3::unit_y()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32), Vec3::unit_x(), Vec3::unit_z(), -Vec3::unit_y(), col, - occluders( - Vec3::unit_x(), - Vec3::unit_z(), - -Vec3::unit_y(), - ), + occluders(Vec3::unit_x(), Vec3::unit_z(), -Vec3::unit_y()), )); } // +y - if is_empty(pos + Vec3::unit_y()) - { + if is_empty(pos + Vec3::unit_y()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_y(), Vec3::unit_z(), Vec3::unit_x(), Vec3::unit_y(), col, - occluders( - Vec3::unit_z(), - Vec3::unit_x(), - Vec3::unit_y(), - ), + occluders(Vec3::unit_z(), Vec3::unit_x(), Vec3::unit_y()), )); } // -z - if is_empty(pos - Vec3::unit_z()) - { + if is_empty(pos - Vec3::unit_z()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32), Vec3::unit_y(), Vec3::unit_x(), -Vec3::unit_z(), col, - occluders( - Vec3::unit_y(), - Vec3::unit_x(), - -Vec3::unit_z(), - ), + occluders(Vec3::unit_y(), Vec3::unit_x(), -Vec3::unit_z()), )); } // +z - if is_empty(pos + Vec3::unit_z()) - { + if is_empty(pos + Vec3::unit_z()) { vertices.extend_from_slice(&create_quad( offs + pos.map(|e| e as f32) + Vec3::unit_z(), Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z(), col, - occluders( - Vec3::unit_x(), - Vec3::unit_y(), - Vec3::unit_z(), - ), + occluders(Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z()), )); } } @@ -254,39 +215,3 @@ fn generate_mesh(segment: &Segment, offs: Vec3) -> Vec { vertices } - -// TODO: put these in utility a module -#[inline(always)] -fn srgb_to_linear(c: Rgba) -> Rgba { - #[inline(always)] - fn to_linear(x: f32) -> f32 { - if x <= 0.04045 { - x / 12.92 - } else { - ((x + 0.055) / 1.055).powf(2.4) - } - } - Rgba { - r: to_linear(c.r), - g: to_linear(c.g), - b: to_linear(c.b), - a: c.a, - } -} -#[inline(always)] -fn linear_to_srgb(c: Rgba) -> Rgba { - #[inline(always)] - fn to_srgb(x: f32) -> f32 { - if x <= 0.0031308 { - x * 12.92 - } else { - x.powf(1.0 / 2.4) * 1.055 - 0.055 - } - } - Rgba { - r: to_srgb(c.r), - g: to_srgb(c.g), - b: to_srgb(c.b), - a: c.a, - } -} \ No newline at end of file diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index f91c83934a..2a20caaae1 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -1,15 +1,15 @@ mod widgets; mod graphic; -mod veuc; +mod util; pub use widgets::toggle_button::ToggleButton; pub use graphic::Graphic; +pub(self) use util::{srgb_to_linear, linear_to_srgb}; use graphic::{ GraphicCache, Id as GraphicId, }; -use image::DynamicImage; use conrod_core::{ Ui as CrUi, UiBuilder, @@ -23,7 +23,7 @@ use conrod_core::{ widget::{Id as WidgId, id::Generator}, render::Primitive, event::Input, - input::{touch::Touch, Widget, Motion, Button, MouseButton}, + input::{touch::Touch, Widget, Motion, Button}, }; use vek::*; use crate::{ @@ -410,7 +410,7 @@ impl Ui { current_state = State::Image; } - let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa()); + let color = srgb_to_linear(color.unwrap_or(conrod_core::color::WHITE).to_fsa().into()); let resolution = Vec2::new( @@ -481,7 +481,7 @@ impl Ui { renderer.update_texture(cache_tex, offset, size, &new_data); }).unwrap(); - let color = srgb_to_linear(color.to_fsa()); + let color = srgb_to_linear(color.to_fsa().into()); for g in positioned_glyphs { if let Ok(Some((uv_rect, screen_rect))) = glyph_cache.rect_for(font_id.index(), g) { @@ -509,7 +509,7 @@ impl Ui { } } PrimitiveKind::Rectangle { color } => { - let color = srgb_to_linear(color.to_fsa()); + let color = srgb_to_linear(color.to_fsa().into()); // Don't draw a transparent rectangle if color[3] == 0.0 { continue; @@ -529,7 +529,7 @@ impl Ui { } PrimitiveKind::TrianglesSingleColor { color, triangles } => { // Don't draw transparent triangle or switch state if there are actually no triangles - let color: [f32; 4] = srgb_to_linear(color.into()); + let color = srgb_to_linear(Rgba::from(Into::<[f32; 4]>::into(color))); if triangles.is_empty() || color[3] == 0.0 { continue; } @@ -561,9 +561,10 @@ impl Ui { } _ => {} - // TODO: Add these - //PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);} + // TODO: Add this //PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);} + // Other uneeded for now + //PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);} } } // Enter the final command @@ -612,16 +613,4 @@ fn default_scissor(renderer: &mut Renderer) -> Aabr { min: Vec2 { x: 0, y: 0 }, max: Vec2 { x: screen_w, y: screen_h } } -} - -fn srgb_to_linear(color: [f32; 4]) -> [f32; 4] { - fn linearize(comp: f32) -> f32 { - if comp <= 0.04045 { - comp / 12.92 - } else { - ((comp + 0.055) / 1.055).powf(2.4) - } - } - - [linearize(color[0]), linearize(color[1]), linearize(color[2]), color[3]] -} +} \ No newline at end of file diff --git a/voxygen/src/ui/util.rs b/voxygen/src/ui/util.rs new file mode 100644 index 0000000000..6359ddd8dd --- /dev/null +++ b/voxygen/src/ui/util.rs @@ -0,0 +1,36 @@ +use vek::*; + +#[inline(always)] +pub fn srgb_to_linear(c: Rgba) -> Rgba { + #[inline(always)] + fn to_linear(x: f32) -> f32 { + if x <= 0.04045 { + x / 12.92 + } else { + ((x + 0.055) / 1.055).powf(2.4) + } + } + Rgba { + r: to_linear(c.r), + g: to_linear(c.g), + b: to_linear(c.b), + a: c.a, + } +} +#[inline(always)] +pub fn linear_to_srgb(c: Rgba) -> Rgba { + #[inline(always)] + fn to_srgb(x: f32) -> f32 { + if x <= 0.0031308 { + x * 12.92 + } else { + x.powf(1.0 / 2.4) * 1.055 - 0.055 + } + } + Rgba { + r: to_srgb(c.r), + g: to_srgb(c.g), + b: to_srgb(c.b), + a: c.a, + } +} From b4fdc472e587c5366c6318426b8ec29645752fa5 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 19 Apr 2019 19:08:10 -0400 Subject: [PATCH 36/72] merge conflict fix Former-commit-id: 31fca905c387211f926031012f6c025e3d82f531 --- voxygen/src/scene/mod.rs | 51 ---------------------------------------- 1 file changed, 51 deletions(-) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 5c740cbf35..b7fb9352f3 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -4,20 +4,11 @@ pub mod terrain; use vek::*; use dot_vox; -<<<<<<< HEAD use common::{ comp, figure::Segment, }; use client::Client; -======= - -// Project -use common::figure::Segment; -use client::Client; - -// Crate ->>>>>>> fc56d4d1bc9f9ea9b40dc42f600e164d11e2eb40 use crate::{ render::{ Consts, @@ -79,34 +70,7 @@ impl Scene { .unwrap(), }, terrain: Terrain::new(), -<<<<<<< HEAD figures: Figures::new(renderer), -======= - - test_figure: Figure::new( - renderer, - [ - Some(load_segment("dragonhead.vox").generate_mesh(Vec3::new(2.0, -12.0, 2.0))), - Some(load_segment("dragon_body.vox").generate_mesh(Vec3::new(0.0, 0.0, 0.0))), - Some(load_segment("dragon_lfoot.vox").generate_mesh(Vec3::new(10.0, 10.0, -80.0))), - Some(load_segment("dragon_rfoot.vox").generate_mesh(Vec3::new(0.0, 10.0, -4.0))), - Some(load_segment("dragon_rfoot.vox").generate_mesh(Vec3::new(0.0, -10.0, -4.0))), - Some(load_segment("dragon_lfoot.vox").generate_mesh(Vec3::new(0.0, 0.0, 0.0))), - None, - None, - None, - None, - None, - None, - None, - None, - None, - None, - ], - CharacterSkeleton::new(), - ) - .unwrap(), ->>>>>>> fc56d4d1bc9f9ea9b40dc42f600e164d11e2eb40 } } @@ -142,7 +106,6 @@ impl Scene { } /// Maintain data such as GPU constant buffers, models, etc. To be called once per tick. -<<<<<<< HEAD pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) { // Get player position let player_pos = client @@ -157,9 +120,6 @@ impl Scene { // Alter camera position to match player self.camera.set_focus_pos(player_pos + Vec3::unit_z() * 1.5); -======= - pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) { ->>>>>>> fc56d4d1bc9f9ea9b40dc42f600e164d11e2eb40 // Compute camera matrices let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents(); @@ -177,18 +137,7 @@ impl Scene { // Maintain the terrain and figures self.terrain.maintain(renderer, client); -<<<<<<< HEAD self.figures.maintain(renderer, client); -======= - - // TODO: Don't do this here - RunAnimation::update_skeleton( - &mut self.test_figure.skeleton, - client.state().get_time(), - ); - self.test_figure.update_locals(renderer, FigureLocals::default()).unwrap(); - self.test_figure.update_skeleton(renderer).unwrap(); ->>>>>>> fc56d4d1bc9f9ea9b40dc42f600e164d11e2eb40 } /// Render the scene using the provided `Renderer` From 86167f819e17fbf8fd3990021f85127c2a02c037 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 2 Mar 2019 18:05:21 -0500 Subject: [PATCH 37/72] adding test assets Former-commit-id: 41e7862329adacfcb262d82dcee0e01c9c031d16 --- voxygen/test_assets/body.vox | Bin 0 -> 6984 bytes voxygen/test_assets/dragon_body.vox | Bin 0 -> 9540 bytes voxygen/test_assets/dragon_lfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_rfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_tail.vox | Bin 0 -> 2080 bytes voxygen/test_assets/dragon_wingL_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingL_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragon_wingR_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingR_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragonhead.vox | Bin 0 -> 3040 bytes voxygen/test_assets/foot_BL.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_BR.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_FL.vox | Bin 0 -> 1192 bytes voxygen/test_assets/foot_FR.vox | Bin 0 -> 1192 bytes voxygen/test_assets/lionhead.vox | Bin 0 -> 5164 bytes voxygen/test_assets/sabremale.vox | Bin 0 -> 7436 bytes 16 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 voxygen/test_assets/body.vox create mode 100644 voxygen/test_assets/dragon_body.vox create mode 100644 voxygen/test_assets/dragon_lfoot.vox create mode 100644 voxygen/test_assets/dragon_rfoot.vox create mode 100644 voxygen/test_assets/dragon_tail.vox create mode 100644 voxygen/test_assets/dragon_wingL_in.vox create mode 100644 voxygen/test_assets/dragon_wingL_out.vox create mode 100644 voxygen/test_assets/dragon_wingR_in.vox create mode 100644 voxygen/test_assets/dragon_wingR_out.vox create mode 100644 voxygen/test_assets/dragonhead.vox create mode 100644 voxygen/test_assets/foot_BL.vox create mode 100644 voxygen/test_assets/foot_BR.vox create mode 100644 voxygen/test_assets/foot_FL.vox create mode 100644 voxygen/test_assets/foot_FR.vox create mode 100644 voxygen/test_assets/lionhead.vox create mode 100644 voxygen/test_assets/sabremale.vox diff --git a/voxygen/test_assets/body.vox b/voxygen/test_assets/body.vox new file mode 100644 index 0000000000000000000000000000000000000000..d6c7aa48dcc2c87e2cddbfa2b1ccb66f309a022f GIT binary patch literal 6984 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 IXVT@r0oGHx%>V!Z literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_lfoot.vox b/voxygen/test_assets/dragon_lfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..80828a713720e4be9d073de8f5282fa58a8c93bb GIT binary patch literal 1408 zcmchWZA@Eb6vxkV@9m4j7Z|0iFrjuZTA1Ud45%n`wkqoPZ3d|&EL&JZyJbt{XyU3((qzSoBqid*I2H`C7mUU^jlF7ABATA#{TlZ$iHs^SC=pfTdPYc0yq8hT zj7f>0smDtktem}y9PjD`fqB)w7NJ{q3`$0o`g+`FfZ z>-E*t)P#6Ejt7&3eOFeo&GH9+vsjSL1|Zipe;VCgH8_5>8S&vRq{sY7Paa2ldJv82 z2y(qv*pAs@f2#_vSr5o(0EIV!<~D;?t;h`!3QrTZP7ronCz!*8ClZ8w_SUO}`aljk zPv;^ynvV<1PopDF=t&Y@T_l`c^j}D(6d4d#eJ4{e-en z?mb0lSs~C%Jb%OtNWdKaIWW@W#MH?;#1A!M>Qp_oJ~gT6{DLiNQM z-&>BcpBgv;f^uFbo# zf8P=)F@l0<0hXs9zC-zrN=i!bc6kyt)q^;3@jSK+6yokz>--aI~3L9^3eOb_HCch)uY69m34AS^}IH!>yDW< SP({jXB)_ literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_rfoot.vox b/voxygen/test_assets/dragon_rfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..1e2bcfe32d72e45c57b712337b993ed77f354f69 GIT binary patch literal 1408 zcmc(eZA?>F7{{M`?(NHDFCeAZ;!0OR+T!G;2y`GTLZ=0bLuRKP65TYj>r6={M4M&{ zb~9s+jj;wKQ4tMci;*d5NtbeNq+f1 z|K~jCIp>~xZ)o2^`y>$s+XFo;^sbJmFA(-Wtr{L|X~W-o@K89=Dydl_wOHtsoX{&d zk|`%K;wd^Mj10#zqo{eoc}8YPVb2IgW)#)y*fX+`i6cvtzU?h$i zK{P~atVlT_OWd1Pkzx|7%qnwEVuXQndR9HFj#bBV>}6JAluikQU==ypAaat5BDfEG z6`hF52JXWMMdq{0IYq~Ly@)A#!79i9dbkD2;cjF{1ISJsMRsZs zP1zUz8Z3=&FD5;l($w%sHcql9NtgktvQ>x712 z0lH2WB0N%zkC&cDXOhsHCcL>oIJ3%Yd#$iV9H>aT(U|d}EN+5h%nJ8hIqL3Ip|qb+ zF~Yqk39ZWndX4u_7(wZ0L5n7gRuy5swgeA$mH}NaAWeiN<_G2%CViT)@C6}1Pq=%F zy^k>KC*<}M*54+C*`E#(#*cA+n9$)O3^WslI|&y!-`ikC#P2|&*NMsF^++CQ!sLk# z8uyWNgD zmjjL4x8kLG7sfx>jD;%>{CL-m_50Ph$a`ky2=~4v{QNy35pm)|%7c{~9r*31KE%%# zV(cpuZmn9dj`IKg`8^&FK5v>qP2DV7M$f{Mvf$2D!h<&m*PTwdTrTX`xD$K#EP_%A zl*CK0H1+r$?o|}nY&N`KnMQ5RAda0shfM>exc_w}mckZH@LfH5|7|T3TCYQW_Ygk; zoSB+O>RJY$F5brUcWc-&IEuEjGw8m&jJ}&|@cDdrL;x8X`~i85@bH_*=X=QC*MH6P zPl#&kE~wfj4Qd*!ifH$Ij`kOV literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_tail.vox b/voxygen/test_assets/dragon_tail.vox new file mode 100644 index 0000000000000000000000000000000000000000..050f21c65a3468e0a49993190171cc26cc9904a9 GIT binary patch literal 2080 zcmc(eYiO2r7{>qaY3}eIpVQp5x#npHQ|EMtrZx{tr%h9H=~B^Bat(2e5FNwNm9)$< z8&g4B7P3M#l}+C0gAEZ8L}W<>B_a`h?L$c4u71xW^}#QF?178>zW?`i-S_qU-{);x zyQy^07}L6>Wevf^bB)>1(%u~R3!Wkn136&R=Ju9fA|yPIL18$OEewZ2C|elvK_22P zLLMQHkcXo5K?H;hIfwuQ$G|agqU2HXXe2u^9LqZN9e56WkC+bfC@~B|*$j1tJsI|8 z*qdQ~hFuwUX4vha_s}~2IUY0UGUzNkSkxA^MQyXsVwTNr8xJ;KY&_X`vzcN0y})yf zI!X$2O$pUXav z+zVnjn+rD|B+(_&B$=5{KNm#c$A~!~N}dBR0xuTu`8~+fXwuXUz8(BKyoVQn9n=;a z3$GR&%fEB@mVXXE8q8uI-lHG_a_|+wcND||u!orDJ<|SN`oAOhV{tzg=N5Nl(X)7W zi@wDS%l~%hd;a~w^*HnB=fKPL!H#?%tIQJ9xeSQfO1?QtXJsEAYWt0sI2A1@QAZ z%L@?7=21uK<-y4#=5jv42lWK%3G^qR%i$~rlH|!CMzRU=1bG5p0xt=;3A`lmlE6!X z840{3@DhWwe#O!yCK~+BO?`d6dV72I=!DVAvo|%>`AdH~j>g7XI0FRHX;2R58>b(;SoO%$GT5$=vjmZZ#_0V>J1= z(X7ixxt&IdJ|mmjyI?fGwLq)(q}6`N)(6*~(ehrSbpuAPUotvy5AC{Qm2{M8T5qLl zN18OL+fmuEVpX1>qUu{SRk+1y+975S8ZEqTWL{x^Pp-^BQs%0o{+SsK&vkWw(Ijcr zvl=i)*T9e9H!!f@=+dV~W5Y(buTVD`oohDAt~Yw{rcpcf{x+lIJ2~HHw5-BtTfNb~ zhzxYierr zN!^g!Oii!#?uomg1l~-l@dgOMyx_0u(Z+NhnZ>OY0 z?@S-i+&Nv^dGv@TZY$K?Z>H;7dy!6XS5M#n;>Huftj!zlsC&0`;N-CSz8uj)LR6Tun_)dSoP%3-nl#aifRdKJoXE@9V$%{0mi8yi|T%9O?>U z>&%WIJ{M|KW@C4dPw)6Jh;1`Y2eBdC8$@5{KYna@<4_Q1oxUeKRiv6w$G^RQI8R0M EH>B;$0{{R3 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_in.vox b/voxygen/test_assets/dragon_wingL_in.vox new file mode 100644 index 0000000000000000000000000000000000000000..aa0a7eedb2afbf963d7ede5a3235f2f9b7bdf915 GIT binary patch literal 2884 zcmc)LTZ~m#9mnziz|5S>zMs9%KDW6s+-9JbYqw3=qN1qrvV`jUzj_)CCrDwKpd}4?1F8GY1i7q_x7SF)M<=D9PKCZY3H^0q`s_sX+X?Br z6VQLhXAF+VIGi$LaY~HGDKaLfz_^@V#^&@eKBt>8I`bK)Gmo(%?zVQ^!(2PP)($Z* zw{}-#{3MCJ=8BCQ|7*c3<;`;k+UulStCQTP6njU z`#u@C`6OE?qYoAC^^++%!1EsKF-Z1OH{|MB;|ek)s3Jzrx<{xXM8Nw2S#fJcHsPTK zpYz(sI|12GhU5VC1q>o(?^KW>K@}c*At!w@r0tMBR(0P&X4Ls)6CPS9^K2hV=tmI) zNE6ydh6Gi2%{=5}NJg$r+N-$lL4!T)bFT>xEtIM2BTHmIStL{Tc?B5~R1qU}ZMvkb zgmRs7L^jAWbxqPk%Uz=nB@~fzW-7=yHwjrKV=_mC8bZ_&pn;hAZjupgx5zR|D58Lr z^H)K}8B9<`j2sba2vJ9X27EN(p^OrW$T+_#s;D4G!nv-IF z-C*A}*dGnbb=I>^xlUb;^{w&yRpUA*D?FdDM-sQ5u1uRT<(Rf&>SLad9QI($J0a^B zavhL9^Y6i@98g!L{St~UIa@^(9L{ww9((wqt=4_-zi`8b4Vs>w)@P?okGyqD3$uUe zA6cfGH+Rc@-Wk8DJ-b%wnWr{s`p7O_JwC3hr=HQ(vu&-v`l8~oT#cuPH1x`Hjh^2q z+tDLCRF+++$Zq9|cbjT2nEFnd?t9l%JY))HOexp-+orX3Fs!d#nI4{Fz!M)chN^*XfEH1m|{{9)6LADh+sh%bp z8XD57(P6E-e~G@hdQ>OB*Qd)rAJ(5fT&BApFV~xV=j=t(N53=u-nl<{#`tw?`>Vh^Me^rf{hCcX(>634m-X0mz z=;){(s642zJaR=gb5zx-s;-^Aw}!7Y**gOR`tIV>TDhXFXJ3C!^@BBi{F}wPHqp>2 z=IZnFzh%>@xwf9%_mQTamtH=5Ni)BkRp-k4I`{iKdZ2w=TV6e{T|c{_eed4U*w~mp zGs%k3KQ;f3>C@ld>))sBum5$QQ>f+5hvafgS9>mZFP)srFLZ5E^7zzTdGX|r=5qg% nb91?I-t=6$_uR+j#%~>)%lppVRvI<5rfc%Q_x|(D=hFTSe|IGn literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_out.vox b/voxygen/test_assets/dragon_wingL_out.vox new file mode 100644 index 0000000000000000000000000000000000000000..879372f6d8d7af3fb5897159e1512c98499fe431 GIT binary patch literal 3544 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 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragonhead.vox b/voxygen/test_assets/dragonhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..0de9789f15d4495178dca869b50b40272cc46005 GIT binary patch literal 3040 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 S)HH5pGxbliZ6tnry!;FE;3mre literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_BR.vox b/voxygen/test_assets/foot_BR.vox new file mode 100644 index 0000000000000000000000000000000000000000..073a55c9e009ef5d5b79538af901e1f6f04bd83f GIT binary patch literal 1236 zcma)*e@L8l9LGP;^V~wR*)7lW$F1`^b-O!b?$q>5TW5N?d;GDSY1?fR7aMtqZ5$!n zaV)kg$%bW@=!BM8h{Tv}qEhsSlOba;#;_4V$QTj*+aD4A_v-t&KZmOiy!kwzpYQMI z^L)QO2M&2AM5Mhj+M$%(u!(d^&CU|Q%`A3D)^Q!lR(6A!Nn~Fb~g^cGQ3l2th?_h3k9`|2y zf%yXCA}lNXtnjk9bLT`j|LbNvgY+iT);5KYEKlX5*BXIBBRXru9`HCwpocFopCnVfsB` zh-NckutuUsYAbXSLH*1ZSupxj`wC!I& z(n<0Xc`Q#p`iJL=)ZKBrdB1F&ef1emTpXsLH=n!Tm9ZQvB;)Zswtp+n>UFs54vBs^ zJ2^-Cn?*iZxXILwbzV9>!oCaBw0^ll*R^%R;V=&cBujz6G1i3#KRi0$19iXtE3Tg4 W<~!R;Tfwbjmj6ky&Bjlzmwy2+<0jnz literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_FL.vox b/voxygen/test_assets/foot_FL.vox new file mode 100644 index 0000000000000000000000000000000000000000..23eab56821aed022d1485f7849650580a8a36cc5 GIT binary patch literal 1192 zcma)*Z%kWd6vofJWeE|7OiH0;mRewIiy12*6v0^pWWD^E48g722s13wG`OWPWNVt4 ztxCiNWwn7VaUvQ*%re|aOEi8!vXEuTvMjh56GN887{B_#7{C2|FZ0{N^d!%H?s?8V z=Y7w)?>lhdkZW2*x?4g$iX@#Q(iaN1KW#e7EdOGg;zNhSp0R-&NkIbG^us5e9O z90iMlZfLrML=!_aQ&+5OhNf8zUF5Q^bj^f_p=(-5Ghybdn5O9=O;^5dvZd=_$Ez)( z_G4Ng5Fn9A@GvFpzp_TT^>6;PT3KD~#%ow=oX4cg`HEv3)h9*sIWaL6e{0#RjBLE!x$|f ze6Em>mY<_7A@rt&w-$vn_f&4L182ldMZ!mYCP-<_ihI(5Z@vuwt=$wK6)MiD+S5Yw ziXd;O_2aonIv-iGGO>FH3ww*W|8gl9&yyBmS>Y#z-xSiPg~d;W)dk`94dn-gxpv{( zgTlt!LZm}DJs?a)Y>W>H(-C1XAdIyMmz3UH=OEJVCf@5|`a}(h{syK;T3P+@O@5z` zP*rZDxu%THS3H~;Xdr3`$z#IoyTZyRLcP;L$XCJ9`aQ(j8X54}h}4xb*-=Smu$uN} zKL=iGB>Z{{(V-sVC&NsA5GAuP&ic(Oq~39pI8sVpULGZdJE$%#!0&Zazh@UO)p(hD zeRwh(|nJO4hP=t(8B1=_7WbfXT0|+_-0FgEGQu z9-I9StGSE`t=_HsAMM)pSpUwFXYjd;@RjA$ z{ic%Tu$`34_1OH)@61|<`|c1Mfip7;B)`h=@zPB$|FF)BrzY5UewNP9SLnOGPB0kc rp@8Hn@E4YK;lX#0_V+-Yum6gxE4X>jwqi55Rm{|%6x%HP(yWrpBd!jLwE zjy9Xj6*rrO*upyJhR7&&tt7Is2PZ{Jp_Jmv7z`<8jJ@t*jJ^GKWA|3f7zz=p~KPQSUkr{1g^}{#$ zeLg}>rJ2^c3c6l#abmEEXh=vN6K3BPRz49L?N)-GDvmbpA=c5%pvO$4!Nyc)HQAwB z0o7nhRttX*s8k6-$UT`)5BwTT<|ENoCg zSj}Uz{}DBpaiQJ4b^l}CyB_P`Uj7UoXDObFVp`nA4EVM);Qjyo*Vor`v1yiC?;I_Y z=dmO$-1<_ue?++Ia^ZHn8Lb?rd;b!Wj8hsbWqIb&KRjzycgJq$z3MdkT2hQ$n4o;9 zjJw}dvmCaNayTBFe|}xQ*5Up;#75!F%mT@;vV6RBlgmG>^Wv#V_MM-l>+==*udn0x t`*|oJg$n+{ur56K?$P-ksQdL_arFc@-`Q3=AKWUI_dhANS@_BM@()`hBKH6Q literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/lionhead.vox b/voxygen/test_assets/lionhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..7d6727d68553a8bfa9c0b56db5003eab21bb2042 GIT binary patch literal 5164 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 E1MV8k_W%F@ literal 0 HcmV?d00001 From 4d0466a618378b26b7a31493c8bb4daf83252af5 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 19 Apr 2019 19:42:12 -0400 Subject: [PATCH 38/72] merge fix Former-commit-id: b83fed02f8a49e5914c8939bb2ec5e6f76bad2a2 --- voxygen/src/anim/character/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 369162da7e..f84cc18e09 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -18,10 +18,10 @@ use super::{ pub struct CharacterSkeleton { head: Bone, chest: Bone, - bl_foot: Bone, - br_foot: Bone, - r_hand: Bone, + belt: Bone, + shorts: Bone, l_hand: Bone, + r_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -32,10 +32,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - br_foot: Bone::default(), - bl_foot: Bone::default(), - r_hand: Bone::default(), + belt: Bone::default(), + shorts: Bone::default(), l_hand: Bone::default(), + r_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -50,10 +50,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.bl_foot.compute_base_matrix()), - FigureBoneData::new(self.br_foot.compute_base_matrix()), - FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.belt.compute_base_matrix()), + FigureBoneData::new(self.shorts.compute_base_matrix()), FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.r_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), From 3ff88ff4786143a7119f3183187688c29f7c8737 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 19 Apr 2019 20:20:01 -0400 Subject: [PATCH 39/72] animation adjustments Former-commit-id: 8720a7442a27103989eae7333b2a48265b94fd07 --- voxygen/src/anim/character/idle.rs | 45 +++++++++++++++++++----------- voxygen/src/anim/character/run.rs | 38 ++++++++++++++----------- voxygen/src/scene/figure.rs | 20 ++++++------- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index 55a0f8f425..b61ac2135c 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -22,28 +22,41 @@ impl Animation for IdleAnimation { time: f64, ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - next.head.offset = Vec3::unit_z() * 13.0 / 11.0; - next.head.ori = Quaternion::rotation_z(0.0); - next.chest.offset = Vec3::unit_z() * 9.0 / 11.0; - next.chest.ori = Quaternion::rotation_z(0.0); + let wave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 12.0).cos(); + let wave_slow = (time as f32 * 6.0 + PI).sin(); + let wave_slower = (time as f32 * 2.0 + PI).sin(); + let wavecos_slower = (time as f32 * 2.0 + PI).cos(); + let waveultra_slow = (time as f32 * 1.0 + PI).sin(); + let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); + let wave_dip = (wave_slow.abs() - 0.5).abs(); - next.belt.offset = Vec3::unit_z() * 7.0 / 11.0; - next.belt.ori = Quaternion::rotation_z(0.0); + next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / 11.0; + next.head.ori = Quaternion::rotation_y(waveultra_slow * 0.05); - next.shorts.offset = Vec3::unit_z() * 4.0 / 11.0; - next.shorts.ori = Quaternion::rotation_z(0.0); + next.chest.offset = Vec3::new(0.0, 0.0, 8.0 + waveultra_slow * 0.4) / 11.0; + next.chest.ori = Quaternion::rotation_y(0.0); - next.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / 11.0; - next.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / 11.0; + next.belt.offset = Vec3::new(0.0, 0.0, 6.0 + waveultra_slow * 0.4) / 11.0; + next.belt.ori = Quaternion::rotation_y(0.0); - next.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / 11.0; - next.l_foot.ori = Quaternion::rotation_x(0.0); - next.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / 11.0; - next.r_foot.ori = Quaternion::rotation_x(0.0); + next.shorts.offset = Vec3::new(0.0, 0.0, 3.0 + waveultra_slow * 0.4) / 11.0; + next.shorts.ori = Quaternion::rotation_y(0.0); - next.back.offset = Vec3::new(-9.0, 5.0, 18.0); - next.back.ori = Quaternion::rotation_y(2.5); + next.l_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3, 7.5, 11.0 + waveultra_slow * 1.1) / 11.0; + next.l_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); + next.r_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3 , - 7.5, 11.0 + waveultra_slow * 1.1) / 11.0; + next.r_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); + + next.l_foot.offset = Vec3::new(2.5, 3.4, 6.0) / 11.0; + next.l_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04); + next.r_foot.offset = Vec3::new(2.5, -3.4, 6.0) / 11.0; + next.r_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04); + + next.back.offset = Vec3::new(-6.5, 16.0, 15.0); + next.back.ori = Quaternion::rotation_x(2.5); next.back.scale = Vec3::one(); next diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index abab662168..08b7838d7a 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -22,32 +22,38 @@ impl Animation for RunAnimation { ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - let wave = (time as f32 * 12.0).sin(); - let wave_slow = (time as f32 * 6.0 + PI).sin(); + let wave = (time as f32 * 14.0).sin(); + let fuzzwave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 14.0).cos(); + let wave_slow = (time as f32 * 8.0 + PI).sin(); + let waveultra_slow = (time as f32 * 0.5 + PI).sin(); + let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); - next.head.offset = Vec3::unit_z() * 13.0 / 11.0; - next.head.ori = Quaternion::rotation_z(wave * 0.3); + next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *0.4)/ 11.0; + //next.head.ori = Quaternion::rotation_z(); - next.chest.offset = Vec3::unit_z() * 9.0 / 11.0; - next.chest.ori = Quaternion::rotation_z(wave * 0.3); + next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.3) / 11.0; + next.chest.ori = Quaternion::rotation_z(wave * 0.2); - next.belt.offset = Vec3::unit_z() * 7.0 / 11.0; + next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.3)/ 11.0; next.belt.ori = Quaternion::rotation_z(wave * 0.2); - next.shorts.offset = Vec3::unit_z() * 4.0 / 11.0; + next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.3) / 11.0; next.shorts.ori = Quaternion::rotation_z(wave * 0.1); - next.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0) / 11.0; - next.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0) / 11.0; + next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / 11.0; + next.l_hand.ori = Quaternion::rotation_y(wave * -1.8); + next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / 11.0; + next.r_hand.ori = Quaternion::rotation_y(wave * 1.8); - next.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0) / 11.0; - next.l_foot.ori = Quaternion::rotation_x(-wave + 1.0); - next.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0) / 11.0; - next.r_foot.ori = Quaternion::rotation_x(wave + 1.0); + next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.5) / 11.0; + next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); + next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.5) / 11.0; + next.r_foot.ori = Quaternion::rotation_y(wave * 1.0); - next.back.offset = Vec3::new(-9.0, 5.0, 18.0); - next.back.ori = Quaternion::rotation_y(2.5); + next.back.offset = Vec3::new(-6.0, 16.0, 15.0); + next.back.ori = Quaternion::rotation_x(2.5); next.back.scale = Vec3::one(); next diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 66f1a65b27..f75d768e89 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -47,15 +47,15 @@ impl Figures { } let bone_meshes = [ - Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -6.5, -6.0))), - Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))), - Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))), + Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.5, -7.0, -6.0))), + Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))), + Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), + Some(load_segment("pants.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), + Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))), + Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))), + Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))), + Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))), + Some(load_segment("sword.vox").generate_mesh(Vec3::new(0.0, -0.0, 0.0))), None, None, None, @@ -138,7 +138,7 @@ impl FigureState { let mat = Mat4::::identity() * Mat4::translation_3d(pos) * - Mat4::rotation_z(dir.y.atan2(dir.x) + f32::consts::PI / 2.0); + Mat4::rotation_z(dir.y.atan2(dir.x));// + f32//::consts)::PI / 2.0); let locals = FigureLocals::new(mat); renderer.update_consts(&mut self.locals, &[locals]).unwrap(); From 1143c58e37f566dcc0d7c7affca773516d456359 Mon Sep 17 00:00:00 2001 From: Imbris Date: Fri, 19 Apr 2019 21:35:12 -0400 Subject: [PATCH 40/72] add graphic cache clearing on resize Former-commit-id: 49b3a52036171fd8b66d9fae73bebb15fbf83a0b --- Cargo.lock | 30 ++++-------------- common/Cargo.toml | 2 +- voxygen/Cargo.toml | 2 +- voxygen/src/menu/main/ui.rs | 50 +++++++++++++++--------------- voxygen/src/ui/graphic/graphic.rs | 4 +++ voxygen/src/ui/graphic/renderer.rs | 5 +-- voxygen/src/ui/mod.rs | 6 ++++ 7 files changed, 46 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a21ae7f43d..d087b366d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -414,13 +414,13 @@ dependencies = [ [[package]] name = "dot_vox" -version = "1.0.1" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -897,14 +897,6 @@ dependencies = [ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memchr" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.2.0" @@ -1005,14 +997,6 @@ dependencies = [ "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nom" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nom" version = "4.2.3" @@ -1933,7 +1917,7 @@ name = "veloren-common" version = "0.2.0" dependencies = [ "bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "dot_vox 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1977,7 +1961,7 @@ dependencies = [ "config 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "conrod_core 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", "conrod_winit 0.63.0 (git+https://gitlab.com/veloren/conrod.git)", - "dot_vox 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "euc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2247,7 +2231,7 @@ dependencies = [ "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6073e9676dbebdddeabaeb63e3b7cefd23c86f5c41d381ee1237cc77b1079898" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" -"checksum dot_vox 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa4d1fc391ef151fff024e8427d206af1adbef4281fcd875090f74697000441" +"checksum dot_vox 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11afd3251e588f2770226659b2a1d55ec2f8aaf2ca42bdcdbd01ff53b4a81e70" "checksum downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b92dfd5c2f75260cbf750572f95d387e7ca0ba5e3fbe9e1a33f23025be020f" "checksum draw_state 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33cf9537e2d06891448799b96d5a8c8083e0e90522a7fdabe6ebf4f41d79d651" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" @@ -2305,7 +2289,6 @@ dependencies = [ "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" @@ -2317,7 +2300,6 @@ dependencies = [ "checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum noise 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a3a34d4f8a31f95919b7ead9f5b60afb9bda0cae98b9219432ffaa6f00b0141" -"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum nonzero_signed 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "02783a0482333b0d3f5f5411b8fb60454a596696da041da0470ac9ef3e6e37d8" "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" diff --git a/common/Cargo.toml b/common/Cargo.toml index e12e94bbab..da924061fd 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -10,7 +10,7 @@ sphynx = { git = "https://gitlab.com/veloren/sphynx.git", features = ["serde1"] specs = { version = "0.14", features = ["serde"] } shred = { version = "0.7", features = ["nightly"] } vek = { version = "0.9", features = ["serde"] } -dot_vox = "1.0" +dot_vox = "4.0" threadpool = "1.7" mio = "0.6" mio-extras = "2.0" diff --git a/voxygen/Cargo.toml b/voxygen/Cargo.toml index a4f2f5875d..40eda49ee8 100644 --- a/voxygen/Cargo.toml +++ b/voxygen/Cargo.toml @@ -36,7 +36,7 @@ failure = "0.1" lazy_static = "1.1" log = "0.4" pretty_env_logger = "0.3" -dot_vox = "1.0" +dot_vox = "4.0" image = "0.21" config = "0.9" serde = "1.0" diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index ee80b48c7c..1ab24d8c63 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -44,7 +44,6 @@ widget_ids! { // Error error_frame, button_ok, - test_vox, } } @@ -66,14 +65,10 @@ struct Imgs { button_dark: ImgId, button_dark_hover: ImgId, button_dark_press: ImgId, - test_vox: ImgId, } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { - fn load_segment(filename: &'static str) -> Segment { - Segment::from(dot_vox::load(&(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/voxygen/").to_string() + filename)).unwrap()) - } - let mut load = |filename| { + let mut load_img = |filename, ui: &mut Ui| { let fullpath: String = ["/voxygen/", filename].concat(); let image = image::load_from_memory( assets::load(fullpath.as_str()) @@ -83,29 +78,39 @@ impl Imgs { .unwrap(); ui.new_graphic(ui::Graphic::Image(image)) }; + let mut load_vox = |filename, ui: &mut Ui| { + let fullpath: String = ["/voxygen/", filename].concat(); + let dot_vox = dot_vox::load_bytes( + assets::load(fullpath.as_str()) + .expect("Error loading file") + .as_slice(), + ) + .unwrap(); + ui.new_graphic(ui::Graphic::Voxel(Segment::from(dot_vox))) + }; Imgs { - bg: load("background/bg_main.png"), - v_logo: load("element/v_logo.png"), + bg: load_img("background/bg_main.png", ui), + v_logo: load_img("element/v_logo.png", ui), // Input fields - input_bg: load("element/misc_backgrounds/textbox.png"), + input_bg: load_img("element/misc_backgrounds/textbox.png", ui), // Login button - login_button: load("element/buttons/button_login.png"), - login_button_hover: load("element/buttons/button_login_hover.png"), - login_button_press: load("element/buttons/button_login_press.png"), + login_button: load_img("element/buttons/button_login.png", ui), + login_button_hover: load_img("element/buttons/button_login_hover.png", ui), + login_button_press: load_img("element/buttons/button_login_press.png", ui), // Servers, settings, and quit buttons - button: load("element/buttons/button.png"), - button_hover: load("element/buttons/button_hover.png"), - button_press: load("element/buttons/button_press.png"), + //button: load_vox("element/buttons/button.vox", ui), + button: load_img("element/buttons/button.png", ui), + button_hover: load_img("element/buttons/button_hover.png", ui), + button_press: load_img("element/buttons/button_press.png", ui), //Error - error_frame: load("element/frames/window_2.png"), - button_dark: load("element/buttons/button_dark.png"), - button_dark_hover: load("element/buttons/button_dark_hover.png"), - button_dark_press: load("element/buttons/button_dark_press.png"), - test_vox: ui.new_graphic(ui::Graphic::Voxel(load_segment("test.vox"))), + error_frame: load_img("element/frames/window_2.png", ui), + button_dark: load_img("element/buttons/button_dark.png", ui), + button_dark_hover: load_img("element/buttons/button_dark_hover.png", ui), + button_dark_press: load_img("element/buttons/button_dark_press.png", ui), } } } @@ -186,11 +191,6 @@ impl MainMenuUi { .label_x(Relative::Scalar(-100.0)) .set(self.ids.v_logo, ui_widgets); - Image::new(self.imgs.test_vox) - .w_h(750.0, 750.0) - .top_right_with_margins_on(self.ids.bg, 50.0, 50.0) - .set(self.ids.test_vox, ui_widgets); - // Input fields // Used when the login button is pressed, or enter is pressed within input field macro_rules! login { diff --git a/voxygen/src/ui/graphic/graphic.rs b/voxygen/src/ui/graphic/graphic.rs index 0a53580a67..f81e9d2f2f 100644 --- a/voxygen/src/ui/graphic/graphic.rs +++ b/voxygen/src/ui/graphic/graphic.rs @@ -41,6 +41,10 @@ impl GraphicCache { pub fn get_graphic(&self, id: Id) -> Option<&Graphic> { self.graphic_map.get(&id) } + pub fn clear_cache(&mut self, new_size: Vec2) { + self.rect_map.clear(); + self.atlas = AtlasAllocator::new(size2(i32::from(new_size.x), i32::from(new_size.y))); + } pub fn cache_res( &mut self, graphic_id: Id, diff --git a/voxygen/src/ui/graphic/renderer.rs b/voxygen/src/ui/graphic/renderer.rs index 36aecf47f4..233681c28e 100644 --- a/voxygen/src/ui/graphic/renderer.rs +++ b/voxygen/src/ui/graphic/renderer.rs @@ -58,7 +58,7 @@ impl<'a> Pipeline for Voxel { pub fn draw_vox(segment: &Segment, output_size: Vec2) -> Vec<[u8; 4]> { let dims = output_size.map(|e| e as usize).into_array(); - let mut color = Buffer2d::new(dims, [50; 4]); + let mut color = Buffer2d::new(dims, [0; 4]); let mut depth = Buffer2d::new(dims, 1.0); let (w, h, d) = segment.get_size().map(|e| e as f32).into_tuple(); @@ -70,7 +70,8 @@ pub fn draw_vox(segment: &Segment, output_size: Vec2) -> Vec<[u8; 4]> { top: 1.0, near: 0.0, far: 1.0, - }) * Mat4::scaling_3d(2.0 / w.max(h)) + }) * Mat4::rotation_x(-std::f32::consts::PI / 2.0) + * Mat4::scaling_3d([2.0 / w, 2.0 / h, 2.0 / d]) * Mat4::translation_3d([-w / 2.0, -h / 2.0, -d / 2.0]); Voxel { mvp }.draw::, _>( &generate_mesh(segment, Vec3::from(0.0)), diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 2a20caaae1..39fcbee6dc 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -118,6 +118,10 @@ impl Cache { pub fn graphic_cache_tex(&self) -> &Texture { &self.graphic_cache_tex } pub fn graphic_cache_mut_and_tex(&mut self) -> (&mut GraphicCache, &Texture) { (&mut self.graphic_cache, &self.graphic_cache_tex) } pub fn new_graphic(&mut self, graphic: Graphic) -> GraphicId { self.graphic_cache.new_graphic(graphic) } + pub fn clear_graphic_cache(&mut self, renderer: &mut Renderer, new_size: Vec2) { + self.graphic_cache.clear_cache(new_size); + self.graphic_cache_tex = renderer.create_dynamic_texture(new_size).unwrap(); + } } enum DrawKind { @@ -580,6 +584,8 @@ impl Ui { self.scale.window_resized(new_dims, renderer); let (w, h) = self.scale.scaled_window_size().into_tuple(); self.ui.handle_event(Input::Resize(w, h)); + self.cache.clear_graphic_cache(renderer, new_dims.map(|e| (e * 4.0) as u16)); + // TODO: probably need to resize glyph cache, see conrod's gfx backend for reference } } } From 0daa8ef3f30a4fcfd11c74b8ec2e94f1ec0efa45 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 08:59:26 -0400 Subject: [PATCH 41/72] fix scaling artifacts Former-commit-id: 7b90e7d033438a0c83e254ea7bcc791ad83808b3 --- voxygen/src/render/texture.rs | 2 +- voxygen/src/ui/graphic/graphic.rs | 9 ++++----- voxygen/src/ui/mod.rs | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/voxygen/src/render/texture.rs b/voxygen/src/render/texture.rs index 59d574a698..d9d166dd4c 100644 --- a/voxygen/src/render/texture.rs +++ b/voxygen/src/render/texture.rs @@ -81,7 +81,7 @@ impl Texture

{ tex, srv, sampler: factory.create_sampler(gfx::texture::SamplerInfo::new( - gfx::texture::FilterMethod::Bilinear, + gfx::texture::FilterMethod::Scale, gfx::texture::WrapMode::Clamp, )), _phantom: PhantomData, diff --git a/voxygen/src/ui/graphic/graphic.rs b/voxygen/src/ui/graphic/graphic.rs index f81e9d2f2f..b42216b36a 100644 --- a/voxygen/src/ui/graphic/graphic.rs +++ b/voxygen/src/ui/graphic/graphic.rs @@ -57,22 +57,21 @@ impl GraphicCache { { match self .rect_map - .get(&(graphic_id, dims, source.map(|e| e.to_bits()))) + .get(&(graphic_id, dims, source.map(|e| e.to_bits()))) //<-------- TODO: Replace this with rounded representation of source { - //<-------- TODO: Replace this with rounded representation of source Some(aabr) => Some(*aabr), None => match self.graphic_map.get(&graphic_id) { Some(graphic) => { // Allocate rectangle let aabr = match self .atlas - .allocate(size2(i32::from(dims.x + 2), i32::from(dims.y + 2))) + .allocate(size2(i32::from(dims.x), i32::from(dims.y))) { Some(Allocation { id, rectangle }) => { let (min, max) = (rectangle.min, rectangle.max); Aabr { - min: Vec2::new(min.x as u16 + 1, min.y as u16 + 1), - max: Vec2::new(max.x as u16 - 1, max.y as u16 - 1), + min: Vec2::new(min.x as u16, min.y as u16), + max: Vec2::new(max.x as u16, max.y as u16), } } // Out of room diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 39fcbee6dc..f5cf7c4a07 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -584,7 +584,7 @@ impl Ui { self.scale.window_resized(new_dims, renderer); let (w, h) = self.scale.scaled_window_size().into_tuple(); self.ui.handle_event(Input::Resize(w, h)); - self.cache.clear_graphic_cache(renderer, new_dims.map(|e| (e * 4.0) as u16)); + self.cache.clear_graphic_cache(renderer, renderer.get_resolution().map(|e| e * 4)); // TODO: probably need to resize glyph cache, see conrod's gfx backend for reference } } From eef5dd28b51f32098a450f68600d81587be7349d Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 10:46:36 -0400 Subject: [PATCH 42/72] Fix chat spacing Former-commit-id: 2e823a1deb51e2fc77a1662b291ed1b5d01b3e70 --- voxygen/src/hud/chat.rs | 66 ++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index ef6c3bdd83..d9f770b4f8 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -1,10 +1,11 @@ use crate::ui::Ui; use conrod_core::{ + color, input::Key, position::Dimension, text::font::Id as FontId, widget::{Button, Id, List, Rectangle, Text, TextEdit}, - widget_ids, Color, Colorable, Positionable, Sizeable, UiCell, Widget, + widget_ids, Colorable, Positionable, Sizeable, UiCell, Widget, }; use std::collections::VecDeque; @@ -84,48 +85,59 @@ impl Chat { // Chat input with rectangle as background let text_edit = TextEdit::new(&self.input) - .w(470.0) + .w(460.0) .restrict_to_height(false) + .line_spacing(2.0) .font_size(15) - .font_id(font) - .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0); - let dims = match ( - text_edit.get_x_dimension(ui_widgets), - text_edit.get_y_dimension(ui_widgets), - ) { - (Dimension::Absolute(x), Dimension::Absolute(y)) => [x, y], - _ => [0.0, 0.0], + .font_id(font); + let y = match text_edit.get_y_dimension(ui_widgets) { + Dimension::Absolute(y) => y + 6.0, + _ => 0.0, }; - Rectangle::fill(dims) + Rectangle::fill([470.0, y]) .rgba(0.0, 0.0, 0.0, 0.8) - .x_position(text_edit.get_x_position(ui_widgets)) - .y_position(text_edit.get_y_position(ui_widgets)) + .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) + .w(470.0) .set(self.ids.input_bg, ui_widgets); - if let Some(str) = text_edit.set(self.ids.input, ui_widgets) { + if let Some(str) = text_edit + .top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0) + .set(self.ids.input, ui_widgets) + { self.input = str.to_string(); self.input.retain(|c| c != '\n'); } // Message box - Rectangle::fill([470.0, 167.0]) + Rectangle::fill([470.0, 174.0]) .rgba(0.0, 0.0, 0.0, 0.4) - .up_from(self.ids.input, 0.0) + .up_from(self.ids.input_bg, 0.0) .set(self.ids.message_box_bg, ui_widgets); - let (mut items, scrollbar) = List::flow_down(self.messages.len()) - .top_left_with_margins_on(self.ids.message_box_bg, 0.0, 5.0) - .w_h(460.0, 160.0) - .scrollbar_next_to() - .scrollbar_thickness(18.0) - .scrollbar_color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) + let (mut items, _) = List::flow_down(self.messages.len() + 1) + .top_left_of(self.ids.message_box_bg) + .w_h(470.0, 174.0) + .scroll_kids_vertically() .set(self.ids.message_box, ui_widgets); while let Some(item) = items.next(ui_widgets) { - item.set( - Text::new(&self.messages[item.i]) + // This would be easier if conrod used the v-metrics from rusttype + let widget = if item.i < self.messages.len() { + let text = Text::new(&self.messages[item.i]) .font_size(15) .font_id(font) - .rgba(1.0, 1.0, 1.0, 1.0), - ui_widgets, - ) + .w(470.0) + .rgba(1.0, 1.0, 1.0, 1.0) + .line_spacing(2.0); + // Add space between messages + let y = match text.get_y_dimension(ui_widgets) { + Dimension::Absolute(y) => y + 2.0, + _ => 0.0, + }; + text.h(y) + } else { + // Spacer at bottom of the last message so that it is not cut off + // Needs to be larger than the space above + Text::new("").font_size(6).font_id(font).w(470.0) + }; + item.set(widget, ui_widgets); } // Chat Arrow From 214777466570cb253868f191114759339a636ea0 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 10:40:48 -0400 Subject: [PATCH 43/72] Stop sending empty messages Former-commit-id: 0f2ed6d0adbbf07566ae1cee1cb0c0498c0c15d8 --- voxygen/src/hud/chat.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index d9f770b4f8..8a6f511631 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -154,13 +154,13 @@ impl Chat { } } - // If enter is pressed send the current message + // If enter is pressed and the input box is not empty send the current message if ui_widgets .widget_input(self.ids.input) .presses() .key() .any(|key_press| match key_press.key { - Key::Return => true, + Key::Return if !self.input.is_empty() => true, _ => false, }) { From 83ed5200b0c569ee1be0a8da61d805388edf1c8a Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 11:17:29 -0400 Subject: [PATCH 44/72] hide entire hud when toggling interface Former-commit-id: 969564ecfd85df0477db4216cd8974adf2df1921 --- voxygen/src/hud/mod.rs | 723 ++++++++++++++++++++-------------------- voxygen/src/settings.rs | 4 +- voxygen/src/window.rs | 4 +- 3 files changed, 368 insertions(+), 363 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 83ab013899..670c6620cc 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -487,378 +487,382 @@ impl Hud { const MANA_COLOR: Color = Color::Rgba(0.42, 0.41, 0.66, 1.0); const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0); - if self.show_ui { - // Add Bag-Space Button - if self.inventorytest_button { - if Button::image(self.imgs.mmap_button) - .w_h(100.0, 100.0) - .middle_of(ui_widgets.window) - .label("1 Up!") - .label_font_size(20) - .hover_image(self.imgs.mmap_button_hover) - .press_image(self.imgs.mmap_button_press) - .set(self.ids.bag_space_add, ui_widgets) - .was_clicked() - { - self.inventory_space = self.inventory_space + 1; - }; - } - // Chat box - if let Some(msg) = self - .chat - .update_layout(ui_widgets, self.font_opensans, &self.imgs) - { - events.push(Event::SendMessage(msg)); - } - // Alpha Version - Text::new(version) - .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) - .font_size(14) - .color(TEXT_COLOR) - .set(self.ids.v_logo, ui_widgets); - // Help Text - if self.show_help { - Image::new(self.imgs.window_frame_2) - .top_left_with_margins_on(ui_widgets.window, 3.0, 3.0) - .w_h(300.0, 350.0) - .set(self.ids.help_bg, ui_widgets); - - Text::new( - "Tab = Free Cursor \n\ - Esc = Open/Close Menus \n\ - \n\ - F1 = Toggle this Window \n\ - F2 = Toggle Interface \n\ - \n\ - Enter = Open Chat \n\ - Mouse Wheel = Scroll Chat\n\ - \n\ - M = Map \n\ - B = Bag \n\ - L = Quest-Log \n\ - C = Character Window \n\ - O = Social \n\ - P = Spellbook \n\ - N = Settings", - ) - .color(TEXT_COLOR) - .top_left_with_margins_on(self.ids.help_bg, 20.0, 20.0) - .font_id(self.font_opensans) - .font_size(18) - .set(self.ids.help, ui_widgets); - // X-button - if Button::image(self.imgs.close_button) - .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) - .hover_image(self.imgs.close_button_hover) - .press_image(self.imgs.close_button_press) - .top_right_with_margins_on(self.ids.help_bg, 8.0, 3.0) - .set(self.ids.button_help2, ui_widgets) - .was_clicked() - { - self.show_help = false; - }; - } - - // Minimap frame and bg - Image::new(self.imgs.mmap_frame_bg) - .w_h(1750.0 / 8.0, 1650.0 / 8.0) - .top_right_with_margins_on(ui_widgets.window, 5.0, 30.0) - .set(self.ids.mmap_frame_bg, ui_widgets); - - Image::new(self.imgs.mmap_frame) - .w_h(1750.0 / 8.0, 1650.0 / 8.0) - .top_right_with_margins_on(ui_widgets.window, 5.0, 30.0) - .set(self.ids.mmap_frame, ui_widgets); - - Image::new(self.imgs.mmap_icons) - .w_h(448.0 / 14.93, 2688.0 / 14.93) - .right_from(self.ids.mmap_frame, 0.0) - .align_bottom_of(self.ids.mmap_frame) - .set(self.ids.mmap_icons, ui_widgets); - // Title - // Make it display the actual location - Text::new("Uncanny Valley") - .mid_top_with_margin_on(self.ids.mmap_frame, 5.0) - .font_size(14) - .color(TEXT_COLOR) - .set(self.ids.mmap_location, ui_widgets); - - // Minimap Buttons - - //0 Settings + // Don't show anything if the ui is toggled off + if !self.show_ui { + return events; + } + + // Add Bag-Space Button + if self.inventorytest_button { if Button::image(self.imgs.mmap_button) - .w_h(448.0 / 15.0, 448.0 / 15.0) - .top_right_with_margins_on(self.ids.mmap_icons, 0.0, 0.0) + .w_h(100.0, 100.0) + .middle_of(ui_widgets.window) + .label("1 Up!") + .label_font_size(20) .hover_image(self.imgs.mmap_button_hover) .press_image(self.imgs.mmap_button_press) - .set(self.ids.mmap_button_0, ui_widgets) + .set(self.ids.bag_space_add, ui_widgets) + .was_clicked() + { + self.inventory_space = self.inventory_space + 1; + }; + } + // Chat box + if let Some(msg) = self + .chat + .update_layout(ui_widgets, self.font_opensans, &self.imgs) + { + events.push(Event::SendMessage(msg)); + } + // Alpha Version + Text::new(version) + .top_left_with_margins_on(ui_widgets.window, 5.0, 5.0) + .font_size(14) + .color(TEXT_COLOR) + .set(self.ids.v_logo, ui_widgets); + // Help Text + if self.show_help { + Image::new(self.imgs.window_frame_2) + .top_left_with_margins_on(ui_widgets.window, 3.0, 3.0) + .w_h(300.0, 350.0) + .set(self.ids.help_bg, ui_widgets); + + Text::new( + "Tab = Free Cursor \n\ + Esc = Open/Close Menus \n\ + \n\ + F1 = Toggle this Window \n\ + F2 = Toggle Interface \n\ + \n\ + Enter = Open Chat \n\ + Mouse Wheel = Scroll Chat\n\ + \n\ + M = Map \n\ + B = Bag \n\ + L = Quest-Log \n\ + C = Character Window \n\ + O = Social \n\ + P = Spellbook \n\ + N = Settings", + ) + .color(TEXT_COLOR) + .top_left_with_margins_on(self.ids.help_bg, 20.0, 20.0) + .font_id(self.font_opensans) + .font_size(18) + .set(self.ids.help, ui_widgets); + // X-button + if Button::image(self.imgs.close_button) + .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(self.ids.help_bg, 8.0, 3.0) + .set(self.ids.button_help2, ui_widgets) + .was_clicked() + { + self.show_help = false; + }; + } + + // Minimap frame and bg + Image::new(self.imgs.mmap_frame_bg) + .w_h(1750.0 / 8.0, 1650.0 / 8.0) + .top_right_with_margins_on(ui_widgets.window, 5.0, 30.0) + .set(self.ids.mmap_frame_bg, ui_widgets); + + Image::new(self.imgs.mmap_frame) + .w_h(1750.0 / 8.0, 1650.0 / 8.0) + .top_right_with_margins_on(ui_widgets.window, 5.0, 30.0) + .set(self.ids.mmap_frame, ui_widgets); + + Image::new(self.imgs.mmap_icons) + .w_h(448.0 / 14.93, 2688.0 / 14.93) + .right_from(self.ids.mmap_frame, 0.0) + .align_bottom_of(self.ids.mmap_frame) + .set(self.ids.mmap_icons, ui_widgets); + // Title + // Make it display the actual location + Text::new("Uncanny Valley") + .mid_top_with_margin_on(self.ids.mmap_frame, 5.0) + .font_size(14) + .color(TEXT_COLOR) + .set(self.ids.mmap_location, ui_widgets); + + // Minimap Buttons + + //0 Settings + if Button::image(self.imgs.mmap_button) + .w_h(448.0 / 15.0, 448.0 / 15.0) + .top_right_with_margins_on(self.ids.mmap_icons, 0.0, 0.0) + .hover_image(self.imgs.mmap_button_hover) + .press_image(self.imgs.mmap_button_press) + .set(self.ids.mmap_button_0, ui_widgets) + .was_clicked() + { + self.open_windows = match self.open_windows { + Windows::Settings => Windows::None, + _ => Windows::Settings, + }; + self.bag_open = false; + }; + // 2 Map + if Button::image(self.imgs.mmap_button) + .w_h(448.0 / 15.0, 448.0 / 15.0) + .down_from(self.ids.mmap_button_1, 0.0) + .hover_image(self.imgs.mmap_button_hover) + .press_image(self.imgs.mmap_button_press) + .set(self.ids.mmap_button_2, ui_widgets) + .was_clicked() + { + self.map_open = !self.map_open; + self.bag_open = false; + }; + + // Other Windows can only be accessed, when Settings are closed. Opening Settings will close all other Windows including the Bag. + // Opening the Map won't close the windows displayed before. + + if match self.open_windows { + Windows::Settings => false, + _ => true, + } && self.map_open == false + { + //1 Social + if Button::image(self.imgs.mmap_button) + .w_h(448.0 / 15.0, 448.0 / 15.0) + .down_from(self.ids.mmap_button_0, 0.0) + .hover_image(self.imgs.mmap_button_hover) + .press_image(self.imgs.mmap_button_press) + .set(self.ids.mmap_button_1, ui_widgets) .was_clicked() { self.open_windows = match self.open_windows { - Windows::Settings => Windows::None, - _ => Windows::Settings, + Windows::Small(Small::Social) => Windows::None, + Windows::None | Windows::Small(_) => Windows::Small(Small::Social), + Windows::CharacterAnd(small) => match small { + Some(Small::Social) => Windows::CharacterAnd(None), + _ => Windows::CharacterAnd(Some(Small::Social)), + }, + Windows::Settings => Windows::Settings, }; - self.bag_open = false; - }; - // 2 Map + } + + //3 Spellbook if Button::image(self.imgs.mmap_button) .w_h(448.0 / 15.0, 448.0 / 15.0) - .down_from(self.ids.mmap_button_1, 0.0) + .down_from(self.ids.mmap_button_2, 0.0) .hover_image(self.imgs.mmap_button_hover) .press_image(self.imgs.mmap_button_press) - .set(self.ids.mmap_button_2, ui_widgets) + .set(self.ids.mmap_button_3, ui_widgets) .was_clicked() { - self.map_open = !self.map_open; - self.bag_open = false; - }; - - // Other Windows can only be accessed, when Settings are closed. Opening Settings will close all other Windows including the Bag. - // Opening the Map won't close the windows displayed before. - - if match self.open_windows { - Windows::Settings => false, - _ => true, - } && self.map_open == false + self.open_windows = match self.open_windows { + Windows::Small(Small::Spellbook) => Windows::None, + Windows::None | Windows::Small(_) => Windows::Small(Small::Spellbook), + Windows::CharacterAnd(small) => match small { + Some(Small::Spellbook) => Windows::CharacterAnd(None), + _ => Windows::CharacterAnd(Some(Small::Spellbook)), + }, + Windows::Settings => Windows::Settings, + }; + } + //4 Char-Window + if Button::image(self.imgs.mmap_button) + .w_h(448.0 / 15.0, 448.0 / 15.0) + .down_from(self.ids.mmap_button_3, 0.0) + .hover_image(self.imgs.mmap_button_hover) + .press_image(self.imgs.mmap_button_press) + .set(self.ids.mmap_button_4, ui_widgets) + .was_clicked() { - //1 Social - if Button::image(self.imgs.mmap_button) - .w_h(448.0 / 15.0, 448.0 / 15.0) - .down_from(self.ids.mmap_button_0, 0.0) - .hover_image(self.imgs.mmap_button_hover) - .press_image(self.imgs.mmap_button_press) - .set(self.ids.mmap_button_1, ui_widgets) - .was_clicked() - { - self.open_windows = match self.open_windows { - Windows::Small(Small::Social) => Windows::None, - Windows::None | Windows::Small(_) => Windows::Small(Small::Social), - Windows::CharacterAnd(small) => match small { - Some(Small::Social) => Windows::CharacterAnd(None), - _ => Windows::CharacterAnd(Some(Small::Social)), - }, - Windows::Settings => Windows::Settings, - }; - } - - //3 Spellbook - if Button::image(self.imgs.mmap_button) - .w_h(448.0 / 15.0, 448.0 / 15.0) - .down_from(self.ids.mmap_button_2, 0.0) - .hover_image(self.imgs.mmap_button_hover) - .press_image(self.imgs.mmap_button_press) - .set(self.ids.mmap_button_3, ui_widgets) - .was_clicked() - { - self.open_windows = match self.open_windows { - Windows::Small(Small::Spellbook) => Windows::None, - Windows::None | Windows::Small(_) => Windows::Small(Small::Spellbook), - Windows::CharacterAnd(small) => match small { - Some(Small::Spellbook) => Windows::CharacterAnd(None), - _ => Windows::CharacterAnd(Some(Small::Spellbook)), - }, - Windows::Settings => Windows::Settings, - }; - } - //4 Char-Window - if Button::image(self.imgs.mmap_button) - .w_h(448.0 / 15.0, 448.0 / 15.0) - .down_from(self.ids.mmap_button_3, 0.0) - .hover_image(self.imgs.mmap_button_hover) - .press_image(self.imgs.mmap_button_press) - .set(self.ids.mmap_button_4, ui_widgets) - .was_clicked() - { - self.open_windows = match self.open_windows { - Windows::CharacterAnd(small) => match small { - Some(small) => Windows::Small(small), - None => Windows::None, - }, - Windows::Small(small) => Windows::CharacterAnd(Some(small)), - Windows::None => Windows::CharacterAnd(None), - Windows::Settings => Windows::Settings, - } - } - //5 Quest-Log - if Button::image(self.imgs.mmap_button) - .w_h(448.0 / 15.0, 448.0 / 15.0) - .down_from(self.ids.mmap_button_4, 0.0) - .hover_image(self.imgs.mmap_button_hover) - .press_image(self.imgs.mmap_button_press) - .set(self.ids.mmap_button_5, ui_widgets) - .was_clicked() - { - self.open_windows = match self.open_windows { - Windows::Small(Small::Questlog) => Windows::None, - Windows::None | Windows::Small(_) => Windows::Small(Small::Questlog), - Windows::CharacterAnd(small) => match small { - Some(Small::Questlog) => Windows::CharacterAnd(None), - _ => Windows::CharacterAnd(Some(Small::Questlog)), - }, - Windows::Settings => Windows::Settings, - }; + self.open_windows = match self.open_windows { + Windows::CharacterAnd(small) => match small { + Some(small) => Windows::Small(small), + None => Windows::None, + }, + Windows::Small(small) => Windows::CharacterAnd(Some(small)), + Windows::None => Windows::CharacterAnd(None), + Windows::Settings => Windows::Settings, } } - - // Skillbar Module - - // Experience-Bar - Image::new(self.imgs.xp_bar) - .w_h(2688.0 / 6.0, 116.0 / 6.0) - .mid_bottom_of(ui_widgets.window) - .set(self.ids.xp_bar, ui_widgets); - - Rectangle::fill_with([406.0 * (self.xp_percentage), 5.0], XP_COLOR) // "W=406*[Exp. %]" - .top_left_with_margins_on(self.ids.xp_bar, 5.0, 21.0) - .set(self.ids.xp_bar_progress, ui_widgets); - - // Left Grid - Image::new(self.imgs.sb_grid) - .w_h(2240.0 / 12.0, 448.0 / 12.0) - .up_from(self.ids.xp_bar, 0.0) - .align_left_of(self.ids.xp_bar) - .set(self.ids.sb_grid_l, ui_widgets); - - Image::new(self.imgs.sb_grid_bg) - .w_h(2240.0 / 12.0, 448.0 / 12.0) - .middle_of(self.ids.sb_grid_l) - .set(self.ids.sb_grid_bg_l, ui_widgets); - - // Right Grid - Image::new(self.imgs.sb_grid) - .w_h(2240.0 / 12.0, 448.0 / 12.0) - .up_from(self.ids.xp_bar, 0.0) - .align_right_of(self.ids.xp_bar) - .set(self.ids.sb_grid_r, ui_widgets); - - Image::new(self.imgs.sb_grid_bg) - .w_h(2240.0 / 12.0, 448.0 / 12.0) - .middle_of(self.ids.sb_grid_r) - .set(self.ids.sb_grid_bg_r, ui_widgets); - - // Right and Left Click - Image::new(self.imgs.l_click) - .w_h(224.0 / 6.0, 320.0 / 6.0) - .right_from(self.ids.sb_grid_bg_l, 0.0) - .align_bottom_of(self.ids.sb_grid_bg_l) - .set(self.ids.l_click, ui_widgets); - - Image::new(self.imgs.r_click) - .w_h(224.0 / 6.0, 320.0 / 6.0) - .left_from(self.ids.sb_grid_bg_r, 0.0) - .align_bottom_of(self.ids.sb_grid_bg_r) - .set(self.ids.r_click, ui_widgets); - - // Health Bar - Image::new(self.imgs.health_bar) - .w_h(1120.0 / 6.0, 96.0 / 6.0) - .left_from(self.ids.l_click, 0.0) - .align_top_of(self.ids.l_click) - .set(self.ids.health_bar, ui_widgets); - - // Filling - Rectangle::fill_with([182.0 * (self.hp_percentage), 6.0], HP_COLOR) // "W=182.0 * [Health. %]" - .top_right_with_margins_on(self.ids.health_bar, 5.0, 0.0) - .set(self.ids.health_bar_color, ui_widgets); - - // Mana Bar - Image::new(self.imgs.mana_bar) - .w_h(1120.0 / 6.0, 96.0 / 6.0) - .right_from(self.ids.r_click, 0.0) - .align_top_of(self.ids.r_click) - .set(self.ids.mana_bar, ui_widgets); - - // Filling - Rectangle::fill_with([182.0 * (self.mana_percentage), 6.0], MANA_COLOR) // "W=182.0 * [Mana. %]" - .top_left_with_margins_on(self.ids.mana_bar, 5.0, 0.0) - .set(self.ids.mana_bar_color, ui_widgets); - - // Buffs/Debuffs - - // Buffs - - // Debuffs - - // Level Display - - // Insert actual Level here - Text::new("1") - .left_from(self.ids.xp_bar, -15.0) - .font_size(10) - .color(TEXT_COLOR) - .set(self.ids.level_text, ui_widgets); - - // Insert next Level here - Text::new("2") - .right_from(self.ids.xp_bar, -15.0) - .font_size(10) - .color(TEXT_COLOR) - .set(self.ids.next_level_text, ui_widgets); - - // Bag contents - if self.bag_open { - // Contents - Image::new(self.imgs.bag_contents) - .w_h(307.0, 545.0) - .bottom_right_with_margins_on(ui_widgets.window, 90.0, 5.0) - .set(self.ids.bag_contents, ui_widgets); - - // Alignment for Grid - Rectangle::fill_with([246.0, 465.0], color::TRANSPARENT) - .top_left_with_margins_on(self.ids.bag_contents, 27.0, 23.0) - .scroll_kids() - .scroll_kids_vertically() - .set(self.ids.inv_alignment, ui_widgets); - // Grid - Image::new(self.imgs.inv_grid) - .w_h(232.0, 1104.0) - .mid_top_with_margin_on(self.ids.inv_alignment, 0.0) - .set(self.ids.inv_grid, ui_widgets); - Scrollbar::y_axis(self.ids.inv_alignment) - .thickness(5.0) - .rgba(0.86, 0.86, 0.86, 0.1) - .set(self.ids.inv_scrollbar, ui_widgets); - - // X-button - if Button::image(self.imgs.close_button) - .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) - .hover_image(self.imgs.close_button_hover) - .press_image(self.imgs.close_button_press) - .top_right_with_margins_on(self.ids.bag_contents, 5.0, 17.0) - .set(self.ids.bag_close, ui_widgets) - .was_clicked() - { - self.bag_open = false; - } - - if self.inventory_space > 0 { - // First Slot - Button::image(self.imgs.inv_slot) - .top_left_with_margins_on(self.ids.inv_grid, 5.0, 5.0) - .w_h(40.0, 40.0) - .set(self.ids.inv_slot_0, ui_widgets); - } - // if self.ids.inv_slot.len() < self.inventory_space { - // self.ids.inv_slot.resize(self.inventory_space, &mut ui_widgets.widget_id_generator()); - //} - - //let num = self.ids.inv_slot.len(); - //println!("self.ids.inv_slot.len(): {:?}", num); - //if num > 0 { - //Button::image(self.imgs.inv_slot) - //.top_left_with_margins_on(self.ids.inv_grid, 5.0, 5.0) - //.w_h(40.0, 40.0) - //.set(self.ids.inv_slot[0], ui_widgets); - //} - //for i in 1..5 { - //Button::image(self.imgs.inv_slot) - //.right(10.0) - //.label(&format!("{}", i + 1)) - //.label_color(TEXT_COLOR) - //.label_font_size(5) - //.set(self.ids.inv_slot[i], ui_widgets);} + //5 Quest-Log + if Button::image(self.imgs.mmap_button) + .w_h(448.0 / 15.0, 448.0 / 15.0) + .down_from(self.ids.mmap_button_4, 0.0) + .hover_image(self.imgs.mmap_button_hover) + .press_image(self.imgs.mmap_button_press) + .set(self.ids.mmap_button_5, ui_widgets) + .was_clicked() + { + self.open_windows = match self.open_windows { + Windows::Small(Small::Questlog) => Windows::None, + Windows::None | Windows::Small(_) => Windows::Small(Small::Questlog), + Windows::CharacterAnd(small) => match small { + Some(Small::Questlog) => Windows::CharacterAnd(None), + _ => Windows::CharacterAnd(Some(Small::Questlog)), + }, + Windows::Settings => Windows::Settings, + }; } } + + // Skillbar Module + + // Experience-Bar + Image::new(self.imgs.xp_bar) + .w_h(2688.0 / 6.0, 116.0 / 6.0) + .mid_bottom_of(ui_widgets.window) + .set(self.ids.xp_bar, ui_widgets); + + Rectangle::fill_with([406.0 * (self.xp_percentage), 5.0], XP_COLOR) // "W=406*[Exp. %]" + .top_left_with_margins_on(self.ids.xp_bar, 5.0, 21.0) + .set(self.ids.xp_bar_progress, ui_widgets); + + // Left Grid + Image::new(self.imgs.sb_grid) + .w_h(2240.0 / 12.0, 448.0 / 12.0) + .up_from(self.ids.xp_bar, 0.0) + .align_left_of(self.ids.xp_bar) + .set(self.ids.sb_grid_l, ui_widgets); + + Image::new(self.imgs.sb_grid_bg) + .w_h(2240.0 / 12.0, 448.0 / 12.0) + .middle_of(self.ids.sb_grid_l) + .set(self.ids.sb_grid_bg_l, ui_widgets); + + // Right Grid + Image::new(self.imgs.sb_grid) + .w_h(2240.0 / 12.0, 448.0 / 12.0) + .up_from(self.ids.xp_bar, 0.0) + .align_right_of(self.ids.xp_bar) + .set(self.ids.sb_grid_r, ui_widgets); + + Image::new(self.imgs.sb_grid_bg) + .w_h(2240.0 / 12.0, 448.0 / 12.0) + .middle_of(self.ids.sb_grid_r) + .set(self.ids.sb_grid_bg_r, ui_widgets); + + // Right and Left Click + Image::new(self.imgs.l_click) + .w_h(224.0 / 6.0, 320.0 / 6.0) + .right_from(self.ids.sb_grid_bg_l, 0.0) + .align_bottom_of(self.ids.sb_grid_bg_l) + .set(self.ids.l_click, ui_widgets); + + Image::new(self.imgs.r_click) + .w_h(224.0 / 6.0, 320.0 / 6.0) + .left_from(self.ids.sb_grid_bg_r, 0.0) + .align_bottom_of(self.ids.sb_grid_bg_r) + .set(self.ids.r_click, ui_widgets); + + // Health Bar + Image::new(self.imgs.health_bar) + .w_h(1120.0 / 6.0, 96.0 / 6.0) + .left_from(self.ids.l_click, 0.0) + .align_top_of(self.ids.l_click) + .set(self.ids.health_bar, ui_widgets); + + // Filling + Rectangle::fill_with([182.0 * (self.hp_percentage), 6.0], HP_COLOR) // "W=182.0 * [Health. %]" + .top_right_with_margins_on(self.ids.health_bar, 5.0, 0.0) + .set(self.ids.health_bar_color, ui_widgets); + + // Mana Bar + Image::new(self.imgs.mana_bar) + .w_h(1120.0 / 6.0, 96.0 / 6.0) + .right_from(self.ids.r_click, 0.0) + .align_top_of(self.ids.r_click) + .set(self.ids.mana_bar, ui_widgets); + + // Filling + Rectangle::fill_with([182.0 * (self.mana_percentage), 6.0], MANA_COLOR) // "W=182.0 * [Mana. %]" + .top_left_with_margins_on(self.ids.mana_bar, 5.0, 0.0) + .set(self.ids.mana_bar_color, ui_widgets); + + // Buffs/Debuffs + + // Buffs + + // Debuffs + + // Level Display + + // Insert actual Level here + Text::new("1") + .left_from(self.ids.xp_bar, -15.0) + .font_size(10) + .color(TEXT_COLOR) + .set(self.ids.level_text, ui_widgets); + + // Insert next Level here + Text::new("2") + .right_from(self.ids.xp_bar, -15.0) + .font_size(10) + .color(TEXT_COLOR) + .set(self.ids.next_level_text, ui_widgets); + + // Bag contents + if self.bag_open { + // Contents + Image::new(self.imgs.bag_contents) + .w_h(307.0, 545.0) + .bottom_right_with_margins_on(ui_widgets.window, 90.0, 5.0) + .set(self.ids.bag_contents, ui_widgets); + + // Alignment for Grid + Rectangle::fill_with([246.0, 465.0], color::TRANSPARENT) + .top_left_with_margins_on(self.ids.bag_contents, 27.0, 23.0) + .scroll_kids() + .scroll_kids_vertically() + .set(self.ids.inv_alignment, ui_widgets); + // Grid + Image::new(self.imgs.inv_grid) + .w_h(232.0, 1104.0) + .mid_top_with_margin_on(self.ids.inv_alignment, 0.0) + .set(self.ids.inv_grid, ui_widgets); + Scrollbar::y_axis(self.ids.inv_alignment) + .thickness(5.0) + .rgba(0.86, 0.86, 0.86, 0.1) + .set(self.ids.inv_scrollbar, ui_widgets); + + // X-button + if Button::image(self.imgs.close_button) + .w_h(244.0 * 0.22 / 3.0, 244.0 * 0.22 / 3.0) + .hover_image(self.imgs.close_button_hover) + .press_image(self.imgs.close_button_press) + .top_right_with_margins_on(self.ids.bag_contents, 5.0, 17.0) + .set(self.ids.bag_close, ui_widgets) + .was_clicked() + { + self.bag_open = false; + } + + if self.inventory_space > 0 { + // First Slot + Button::image(self.imgs.inv_slot) + .top_left_with_margins_on(self.ids.inv_grid, 5.0, 5.0) + .w_h(40.0, 40.0) + .set(self.ids.inv_slot_0, ui_widgets); + } + // if self.ids.inv_slot.len() < self.inventory_space { + // self.ids.inv_slot.resize(self.inventory_space, &mut ui_widgets.widget_id_generator()); + //} + + //let num = self.ids.inv_slot.len(); + //println!("self.ids.inv_slot.len(): {:?}", num); + //if num > 0 { + //Button::image(self.imgs.inv_slot) + //.top_left_with_margins_on(self.ids.inv_grid, 5.0, 5.0) + //.w_h(40.0, 40.0) + //.set(self.ids.inv_slot[0], ui_widgets); + //} + //for i in 1..5 { + //Button::image(self.imgs.inv_slot) + //.right(10.0) + //.label(&format!("{}", i + 1)) + //.label_color(TEXT_COLOR) + //.label_font_size(5) + //.set(self.ids.inv_slot[i], ui_widgets);} + } + // Bag if !self.map_open { self.bag_open = ToggleButton::new(self.bag_open, self.imgs.bag, self.imgs.bag_open) @@ -1538,13 +1542,18 @@ impl Hud { pub fn handle_event(&mut self, event: WinEvent) -> bool { match event { WinEvent::Ui(event) => { - if (self.typing() && event.is_keyboard()) + if (self.typing() && event.is_keyboard() && self.show_ui) || !(self.cursor_grabbed && event.is_keyboard_or_mouse()) { self.ui.handle_event(event); } true } + WinEvent::KeyDown(Key::ToggleInterface) => { + self.toggle_ui(); + true + } + _ if !self.show_ui => false, WinEvent::Zoom(_) => !self.cursor_grabbed && !self.ui.no_widget_capturing_mouse(), WinEvent::KeyDown(Key::Enter) => { self.ui.focus_widget(if self.typing() { @@ -1596,10 +1605,6 @@ impl Hud { self.toggle_help(); true } - Key::Interface => { - self.toggle_ui(); - true - } _ => false, }, WinEvent::KeyDown(key) | WinEvent::KeyUp(key) => match key { diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs index 52f772af2e..86d90cb446 100644 --- a/voxygen/src/settings.rs +++ b/voxygen/src/settings.rs @@ -34,7 +34,7 @@ pub struct ControlSettings { pub spellbook: VirtualKeyCode, pub settings: VirtualKeyCode, pub help: VirtualKeyCode, - pub interface: VirtualKeyCode, + pub toggle_interface: VirtualKeyCode, } impl Default for Settings { @@ -56,7 +56,7 @@ impl Default for Settings { spellbook: VirtualKeyCode::P, settings: VirtualKeyCode::N, help: VirtualKeyCode::F1, - interface: VirtualKeyCode::F2, + toggle_interface: VirtualKeyCode::F2, }, } } diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs index 59913c0069..f13a515455 100644 --- a/voxygen/src/window.rs +++ b/voxygen/src/window.rs @@ -51,7 +51,7 @@ impl Window { key_map.insert(settings.controls.spellbook, Key::Spellbook); key_map.insert(settings.controls.settings, Key::Settings); key_map.insert(settings.controls.help, Key::Help); - key_map.insert(settings.controls.interface, Key::Interface); + key_map.insert(settings.controls.toggle_interface, Key::ToggleInterface); let tmp = Ok(Self { events_loop, @@ -180,7 +180,7 @@ pub enum Key { Social, Spellbook, Settings, - Interface, + ToggleInterface, Help, } From 85dda5e50598decf3269dec9e21831902b32e071 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 11:24:28 -0400 Subject: [PATCH 45/72] go back to main menu when logging out Former-commit-id: 95956f916adb0afb47e489defa197f2b8e99b775 --- voxygen/src/menu/char_selection/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 04504bb6c6..051e2e155e 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -67,7 +67,7 @@ impl PlayState for CharSelectionState { global_state.singleplayer = None; return PlayStateResult::Pop; }, - ui::Event::Play => return PlayStateResult::Push( + ui::Event::Play => return PlayStateResult::Switch( Box::new(SessionState::new(&mut global_state.window, self.client.clone())) ), } From 67584a49ce929d2d6d0fd9f49da6a82702abc359 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 11:43:38 -0400 Subject: [PATCH 46/72] hide chat input when not typing Former-commit-id: a1982ef2edf991c94cea359a2892cbf13ef8e980 --- voxygen/src/hud/chat.rs | 52 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index 8a6f511631..91fb29d4ed 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -83,34 +83,42 @@ impl Chat { self.new_messages = false; } + // Only show if it has the keyboard captured // Chat input with rectangle as background - let text_edit = TextEdit::new(&self.input) - .w(460.0) - .restrict_to_height(false) - .line_spacing(2.0) - .font_size(15) - .font_id(font); - let y = match text_edit.get_y_dimension(ui_widgets) { - Dimension::Absolute(y) => y + 6.0, - _ => 0.0, - }; - Rectangle::fill([470.0, y]) - .rgba(0.0, 0.0, 0.0, 0.8) - .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) - .w(470.0) - .set(self.ids.input_bg, ui_widgets); - if let Some(str) = text_edit - .top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0) - .set(self.ids.input, ui_widgets) - { - self.input = str.to_string(); - self.input.retain(|c| c != '\n'); + let keyboard_captured = ui_widgets.global_input().current.widget_capturing_keyboard.map_or(false, |id| id == self.ids.input); + if keyboard_captured { + let text_edit = TextEdit::new(&self.input) + .w(460.0) + .restrict_to_height(false) + .line_spacing(2.0) + .font_size(15) + .font_id(font); + let y = match text_edit.get_y_dimension(ui_widgets) { + Dimension::Absolute(y) => y + 6.0, + _ => 0.0, + }; + Rectangle::fill([470.0, y]) + .rgba(0.0, 0.0, 0.0, 0.8) + .bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) + .w(470.0) + .set(self.ids.input_bg, ui_widgets); + if let Some(str) = text_edit + .top_left_with_margins_on(self.ids.input_bg, 1.0, 1.0) + .set(self.ids.input, ui_widgets) + { + self.input = str.to_string(); + self.input.retain(|c| c != '\n'); + } } // Message box Rectangle::fill([470.0, 174.0]) .rgba(0.0, 0.0, 0.0, 0.4) - .up_from(self.ids.input_bg, 0.0) + .and(|r| if keyboard_captured { + r.up_from(self.ids.input_bg, 0.0) + } else { + r.bottom_left_with_margins_on(ui_widgets.window, 10.0, 10.0) + }) .set(self.ids.message_box_bg, ui_widgets); let (mut items, _) = List::flow_down(self.messages.len() + 1) .top_left_of(self.ids.message_box_bg) From d6d4155fc41ac9150fb4cfce554ef2a5fcccd71e Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 14:08:39 -0400 Subject: [PATCH 47/72] rearrange hud event handling slighlty Former-commit-id: 8043d6c6197112123c371258407ea886a5ae3595 --- voxygen/src/hud/mod.rs | 71 ++++++++++++++++++++---------------------- voxygen/src/session.rs | 6 ++-- 2 files changed, 36 insertions(+), 41 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 670c6620cc..bbbbffc1fb 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -4,6 +4,7 @@ use crate::{ render::Renderer, ui::{self, ScaleMode, ToggleButton, Ui}, window::{Event as WinEvent, Key, Window}, + GlobalState, }; use common::assets; use conrod_core::{ @@ -406,7 +407,6 @@ pub struct Hud { ids: Ids, imgs: Imgs, chat: chat::Chat, - cursor_grabbed: bool, font_metamorph: FontId, font_opensans: FontId, show_help: bool, @@ -459,7 +459,6 @@ impl Hud { imgs, ids, chat, - cursor_grabbed: true, settings_tab: SettingsTab::Interface, show_help: true, bag_open: false, @@ -1460,13 +1459,17 @@ impl Hud { self.chat.new_message(msg); } - pub fn toggle_menu(&mut self) { + fn toggle_menu(&mut self) { self.menu_open = !self.menu_open; } - pub fn toggle_bag(&mut self) { + fn toggle_bag(&mut self) { self.bag_open = !self.bag_open } - pub fn toggle_questlog(&mut self) { + fn toggle_map(&mut self) { + self.map_open = !self.map_open; + self.bag_open = false; + } + fn toggle_questlog(&mut self) { self.open_windows = match self.open_windows { Windows::Small(Small::Questlog) => Windows::None, Windows::None | Windows::Small(_) => Windows::Small(Small::Questlog), @@ -1477,11 +1480,7 @@ impl Hud { Windows::Settings => Windows::Settings, }; } - pub fn toggle_map(&mut self) { - self.map_open = !self.map_open; - self.bag_open = false; - } - pub fn toggle_charwindow(&mut self) { + fn toggle_charwindow(&mut self) { self.open_windows = match self.open_windows { Windows::CharacterAnd(small) => match small { Some(small) => Windows::Small(small), @@ -1492,7 +1491,7 @@ impl Hud { Windows::Settings => Windows::Settings, } } - pub fn toggle_social(&mut self) { + fn toggle_social(&mut self) { self.open_windows = match self.open_windows { Windows::Small(Small::Social) => Windows::None, Windows::None | Windows::Small(_) => Windows::Small(Small::Social), @@ -1503,7 +1502,7 @@ impl Hud { Windows::Settings => Windows::Settings, }; } - pub fn toggle_spellbook(&mut self) { + fn toggle_spellbook(&mut self) { self.open_windows = match self.open_windows { Windows::Small(Small::Spellbook) => Windows::None, Windows::None | Windows::Small(_) => Windows::Small(Small::Spellbook), @@ -1514,22 +1513,36 @@ impl Hud { Windows::Settings => Windows::Settings, }; } - pub fn toggle_settings(&mut self) { + fn toggle_settings(&mut self) { self.open_windows = match self.open_windows { Windows::Settings => Windows::None, _ => Windows::Settings, }; self.bag_open = false; } - pub fn toggle_help(&mut self) { + fn toggle_help(&mut self) { self.show_help = !self.show_help } - pub fn toggle_ui(&mut self) { + fn toggle_ui(&mut self) { self.show_ui = !self.show_ui; } - pub fn update_grab(&mut self, cursor_grabbed: bool) { - self.cursor_grabbed = cursor_grabbed; + fn toggle_windows(&mut self) { + if self.bag_open + || self.menu_open + || self.map_open + || match self.open_windows { + Windows::None => false, + _ => true, + } + { + self.bag_open = false; + self.menu_open = false; + self.map_open = false; + self.open_windows = Windows::None; + } else { + self.menu_open = true; + } } fn typing(&self) -> bool { @@ -1539,11 +1552,12 @@ impl Hud { } } - pub fn handle_event(&mut self, event: WinEvent) -> bool { + pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool { + let cursor_grabbed = global_state.window.is_cursor_grabbed(); match event { WinEvent::Ui(event) => { if (self.typing() && event.is_keyboard() && self.show_ui) - || !(self.cursor_grabbed && event.is_keyboard_or_mouse()) + || !(cursor_grabbed && event.is_keyboard_or_mouse()) { self.ui.handle_event(event); } @@ -1554,7 +1568,7 @@ impl Hud { true } _ if !self.show_ui => false, - WinEvent::Zoom(_) => !self.cursor_grabbed && !self.ui.no_widget_capturing_mouse(), + WinEvent::Zoom(_) => !cursor_grabbed && !self.ui.no_widget_capturing_mouse(), WinEvent::KeyDown(Key::Enter) => { self.ui.focus_widget(if self.typing() { None @@ -1625,21 +1639,4 @@ impl Hud { pub fn render(&self, renderer: &mut Renderer) { self.ui.render(renderer); } - pub fn toggle_windows(&mut self) { - if self.bag_open - || self.menu_open - || self.map_open - || match self.open_windows { - Windows::None => false, - _ => true, - } - { - self.bag_open = false; - self.menu_open = false; - self.map_open = false; - self.open_windows = Windows::None; - } else { - self.menu_open = true; - } - } } diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 46003c7278..df0e014bf8 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -120,8 +120,8 @@ impl PlayState for SessionState { // Handle window events for event in global_state.window.fetch_events() { - // Pass all events to the ui first - if self.hud.handle_event(event.clone()) { + // Pass all events to the ui first + if self.hud.handle_event(event.clone(), global_state) { continue; } let _handled = match event { @@ -134,8 +134,6 @@ impl PlayState for SessionState { global_state .window .grab_cursor(!global_state.window.is_cursor_grabbed()); - self.hud - .update_grab(global_state.window.is_cursor_grabbed()); } // Movement Key Pressed Event::KeyDown(Key::MoveForward) => self.key_state.up = true, From 2800c9e9f55aa8ed2136fb131bef80a189320d3c Mon Sep 17 00:00:00 2001 From: Piotr Date: Sat, 20 Apr 2019 20:35:45 +0200 Subject: [PATCH 48/72] make 11.0 a const Former-commit-id: 4602f3147b434e93256d48938b813325e74ad551 --- voxygen/src/anim/character/idle.rs | 17 +++++++++-------- voxygen/src/anim/character/mod.rs | 2 ++ voxygen/src/anim/character/run.rs | 17 +++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index 55a0f8f425..9bada97c00 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -8,6 +8,7 @@ use vek::*; use super::{ CharacterSkeleton, super::Animation, + SCALE, }; pub struct IdleAnimation; @@ -22,24 +23,24 @@ impl Animation for IdleAnimation { time: f64, ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - next.head.offset = Vec3::unit_z() * 13.0 / 11.0; + next.head.offset = Vec3::unit_z() * 13.0 / SCALE; next.head.ori = Quaternion::rotation_z(0.0); - next.chest.offset = Vec3::unit_z() * 9.0 / 11.0; + next.chest.offset = Vec3::unit_z() * 9.0 / SCALE; next.chest.ori = Quaternion::rotation_z(0.0); - next.belt.offset = Vec3::unit_z() * 7.0 / 11.0; + next.belt.offset = Vec3::unit_z() * 7.0 / SCALE; next.belt.ori = Quaternion::rotation_z(0.0); - next.shorts.offset = Vec3::unit_z() * 4.0 / 11.0; + next.shorts.offset = Vec3::unit_z() * 4.0 / SCALE; next.shorts.ori = Quaternion::rotation_z(0.0); - next.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / 11.0; - next.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / 11.0; + next.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / SCALE; + next.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / SCALE; - next.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / 11.0; + next.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / SCALE; next.l_foot.ori = Quaternion::rotation_x(0.0); - next.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / 11.0; + next.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / SCALE; next.r_foot.ori = Quaternion::rotation_x(0.0); next.back.offset = Vec3::new(-9.0, 5.0, 18.0); diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index f84cc18e09..3d6e3e1dfc 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -14,6 +14,8 @@ use super::{ Bone, }; +const SCALE: f32 = 11.0; + #[derive(Clone)] pub struct CharacterSkeleton { head: Bone, diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index abab662168..27da889f95 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -8,6 +8,7 @@ use vek::*; use super::{ CharacterSkeleton, super::Animation, + SCALE }; pub struct RunAnimation; @@ -26,24 +27,24 @@ impl Animation for RunAnimation { let wave_slow = (time as f32 * 6.0 + PI).sin(); let wave_dip = (wave_slow.abs() - 0.5).abs(); - next.head.offset = Vec3::unit_z() * 13.0 / 11.0; + next.head.offset = Vec3::unit_z() * 13.0 / SCALE; next.head.ori = Quaternion::rotation_z(wave * 0.3); - next.chest.offset = Vec3::unit_z() * 9.0 / 11.0; + next.chest.offset = Vec3::unit_z() * 9.0 / SCALE; next.chest.ori = Quaternion::rotation_z(wave * 0.3); - next.belt.offset = Vec3::unit_z() * 7.0 / 11.0; + next.belt.offset = Vec3::unit_z() * 7.0 / SCALE; next.belt.ori = Quaternion::rotation_z(wave * 0.2); - next.shorts.offset = Vec3::unit_z() * 4.0 / 11.0; + next.shorts.offset = Vec3::unit_z() * 4.0 / SCALE; next.shorts.ori = Quaternion::rotation_z(wave * 0.1); - next.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0) / 11.0; - next.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0) / 11.0; + next.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0) / SCALE; + next.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0) / SCALE; - next.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0) / 11.0; + next.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0) / SCALE; next.l_foot.ori = Quaternion::rotation_x(-wave + 1.0); - next.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0) / 11.0; + next.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0) / SCALE; next.r_foot.ori = Quaternion::rotation_x(wave + 1.0); next.back.offset = Vec3::new(-9.0, 5.0, 18.0); From d4002262e9547fbf2de74432f5ec3c8ae8d7e47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Bro=C5=84ski?= Date: Sat, 20 Apr 2019 20:48:35 +0000 Subject: [PATCH 49/72] Fix fonts Issue Former-commit-id: ce4e6d4d0d42a48489585f208a9267b7b6aa88e6 --- .gitlab-ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 71691d120f..80479e9a52 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -74,7 +74,6 @@ nightly-linux-debug: - cp target/debug/veloren-voxygen nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - - cp -r voxygen/fonts nightly/ - rm -f nightly-linux-debug.tar.bz2 - tar -cvjSf nightly-linux-debug.tar.bz2 nightly when: always @@ -97,7 +96,6 @@ nightly-windows-debug: - cp target/x86_64-pc-windows-gnu/debug/veloren-voxygen.exe nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - - cp -r voxygen/fonts nightly/ - rm -f nightly-windows-debug.zip - zip -r nightly-windows-debug.zip nightly artifacts: @@ -119,7 +117,6 @@ nightly-linux-optimized: - cp target/release/veloren-voxygen nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - - cp -r voxygen/fonts nightly/ - rm -f nightly-linux-optimized.tar.bz2 - tar -cvjSf nightly-linux-optimized.tar.bz2 nightly when: manual @@ -142,7 +139,6 @@ nightly-windows-optimized: - cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe nightly - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - - cp -r voxygen/fonts nightly/ - rm -f nightly-windows-optimized.zip - zip -r nightly-windows-optimized.zip nightly when: manual @@ -165,7 +161,6 @@ stable-linux-optimized: - cp target/release/veloren-voxygen stable - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - - cp -r voxygen/fonts nightly/ - rm -f stable-linux-optimized.tar.bz2 - tar -cvjSf stable-linux-optimized.tar.bz2 stable artifacts: @@ -187,7 +182,6 @@ stable-windows-optimized: - cp target/x86_64-pc-windows-gnu/release/veloren-voxygen.exe stable - cp -r assets nightly/ - cp -r voxygen/shaders nightly/ - - cp -r voxygen/fonts nightly/ - rm -f stable-windows-optimized.zip - zip -r stable-windows-optimized.zip stable artifacts: From 60fa9a7e204b52de3f879ee150e5862cf6f8aaf9 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 17:33:51 -0400 Subject: [PATCH 50/72] animattion tweaks Former-commit-id: 0baf418a09bfa8ffad7a0bfe4b9f5256053454fb --- assets/voxygen | 2 +- voxygen/src/scene/figure.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/voxygen b/assets/voxygen index e3083ec8e8..0a176c4089 160000 --- a/assets/voxygen +++ b/assets/voxygen @@ -1 +1 @@ -Subproject commit e3083ec8e8e634af8c9daed00ea82435da195979 +Subproject commit 0a176c408946f081850132623a6730d9d2b1e7ed diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index f75d768e89..d8e54ecbe4 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -47,7 +47,7 @@ impl Figures { } let bone_meshes = [ - Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.5, -7.0, -6.0))), + Some(load_segment("head.vox").generate_mesh(Vec3::new(-3.5, -7.0, -6.0))), Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))), Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), Some(load_segment("pants.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), From 7fa37e0c2a8c0c97e5cb7a54ebbe4c1c32a97115 Mon Sep 17 00:00:00 2001 From: Imbris Date: Sat, 20 Apr 2019 18:02:48 -0400 Subject: [PATCH 51/72] update asset loading to not use env Former-commit-id: 1858f3e06a26502c8bb6a3237e216d551377f6c6 --- voxygen/src/hud/mod.rs | 26 +++++++++++-------------- voxygen/src/menu/char_selection/ui.rs | 24 ++++++++++------------- voxygen/src/menu/main/ui.rs | 28 ++++++++++++--------------- voxygen/src/scene/figure.rs | 10 ++++++++-- 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index bbbbffc1fb..05c9fe128a 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -250,7 +250,7 @@ pub(self) struct Imgs { } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { - let mut load = |filename, ui: &mut Ui| { + let load = |filename, ui: &mut Ui| { let fullpath: String = ["/voxygen/", filename].concat(); let image = image::load_from_memory( assets::load(fullpath.as_str()) @@ -438,22 +438,18 @@ impl Hud { // Load images let imgs = Imgs::new(&mut ui, window.renderer_mut()); // Load fonts - let font_opensans = ui.new_font( - conrod_core::text::font::from_file(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../assets/voxygen/font/OpenSans-Regular.ttf" - )) - .unwrap(), - ); - let font_metamorph = ui.new_font( - conrod_core::text::font::from_file(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../assets/voxygen/font/Metamorphous-Regular.ttf" - )) - .unwrap(), - ); + let load_font = |filename, ui: &mut Ui| { + let fullpath: String = ["/voxygen/font", filename].concat(); + ui.new_font(conrod_core::text::Font::from_bytes( + assets::load(fullpath.as_str()) + .expect("Error loading file") + ).unwrap()) + }; + let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui); + let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui); // Chat box let chat = chat::Chat::new(&mut ui); + Self { ui, imgs, diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index 1a2be0245e..47c156e452 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -377,20 +377,16 @@ impl CharSelectionUi { // Load images let imgs = Imgs::new(&mut ui, window.renderer_mut()); // Load fonts - let font_opensans = ui.new_font( - conrod_core::text::font::from_file(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../assets/voxygen/font/OpenSans-Regular.ttf" - )) - .unwrap(), - ); - let font_metamorph = ui.new_font( - conrod_core::text::font::from_file(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../assets/voxygen/font/Metamorphous-Regular.ttf" - )) - .unwrap(), - ); + let load_font = |filename, ui: &mut Ui| { + let fullpath: String = ["/voxygen/font", filename].concat(); + ui.new_font(conrod_core::text::Font::from_bytes( + assets::load(fullpath.as_str()) + .expect("Error loading file") + ).unwrap()) + }; + let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui); + let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui); + Self { ui, imgs, diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 1ab24d8c63..d14e75686e 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -68,7 +68,7 @@ struct Imgs { } impl Imgs { fn new(ui: &mut Ui, renderer: &mut Renderer) -> Imgs { - let mut load_img = |filename, ui: &mut Ui| { + let load_img = |filename, ui: &mut Ui| { let fullpath: String = ["/voxygen/", filename].concat(); let image = image::load_from_memory( assets::load(fullpath.as_str()) @@ -78,7 +78,7 @@ impl Imgs { .unwrap(); ui.new_graphic(ui::Graphic::Image(image)) }; - let mut load_vox = |filename, ui: &mut Ui| { + let load_vox = |filename, ui: &mut Ui| { let fullpath: String = ["/voxygen/", filename].concat(); let dot_vox = dot_vox::load_bytes( assets::load(fullpath.as_str()) @@ -146,20 +146,16 @@ impl MainMenuUi { // Load images let imgs = Imgs::new(&mut ui, window.renderer_mut()); // Load fonts - let font_opensans = ui.new_font( - conrod_core::text::font::from_file(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../assets/voxygen/font/OpenSans-Regular.ttf" - )) - .unwrap(), - ); - let font_metamorph = ui.new_font( - conrod_core::text::font::from_file(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../assets/voxygen/font/Metamorphous-Regular.ttf" - )) - .unwrap(), - ); + let load_font = |filename, ui: &mut Ui| { + let fullpath: String = ["/voxygen/font", filename].concat(); + ui.new_font(conrod_core::text::Font::from_bytes( + assets::load(fullpath.as_str()) + .expect("Error loading file") + ).unwrap()) + }; + let font_opensans = load_font("/OpenSans-Regular.ttf", &mut ui); + let font_metamorph = load_font("/Metamorphous-Regular.ttf", &mut ui); + Self { ui, imgs, diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 66f1a65b27..849e865686 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -8,7 +8,8 @@ use client::Client; use common::{ comp, figure::Segment, - msg + msg, + assets, }; use crate::{ Error, @@ -43,7 +44,12 @@ impl Figures { pub fn new(renderer: &mut Renderer) -> Self { // TODO: Make a proper asset loading system fn load_segment(filename: &'static str) -> Segment { - Segment::from(dot_vox::load(&(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/voxygen/voxel/").to_string() + filename)).unwrap()) + let fullpath: String = ["/voxygen/voxel/", filename].concat(); + Segment::from(dot_vox::load_bytes( + assets::load(fullpath.as_str()) + .expect("Error loading file") + .as_slice(), + ).unwrap()) } let bone_meshes = [ From 46f571f99a508310343d6ce51d8a6e03b23aca18 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:08:56 -0400 Subject: [PATCH 52/72] animation minor fixes Former-commit-id: 4326db41103a0d3f87c7ad638fb38cd2f3eec71c --- voxygen/src/anim/character/run.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 08b7838d7a..8db66c439d 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -30,26 +30,26 @@ impl Animation for RunAnimation { let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); - next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *0.4)/ 11.0; + next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ 11.0; //next.head.ori = Quaternion::rotation_z(); - next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.3) / 11.0; - next.chest.ori = Quaternion::rotation_z(wave * 0.2); + next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / 11.0; + next.chest.ori = Quaternion::rotation_z(wave * 0.3); - next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.3)/ 11.0; - next.belt.ori = Quaternion::rotation_z(wave * 0.2); + next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.8)/ 11.0; + next.belt.ori = Quaternion::rotation_z(wave * 0.3); - next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.3) / 11.0; - next.shorts.ori = Quaternion::rotation_z(wave * 0.1); + next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.8) / 11.0; + next.shorts.ori = Quaternion::rotation_z(wave * 0.2); next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / 11.0; next.l_hand.ori = Quaternion::rotation_y(wave * -1.8); next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / 11.0; next.r_hand.ori = Quaternion::rotation_y(wave * 1.8); - next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.5) / 11.0; + next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.9) / 11.0; next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); - next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.5) / 11.0; + next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.9) / 11.0; next.r_foot.ori = Quaternion::rotation_y(wave * 1.0); next.back.offset = Vec3::new(-6.0, 16.0, 15.0); From 3d318a85e46b1992d4f467b4382746975e13c247 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:12:45 -0400 Subject: [PATCH 53/72] tidying up code Former-commit-id: df86599ae47b71bb744f5589da4511fa71603541 --- voxygen/src/anim/character/idle.rs | 4 +--- voxygen/src/anim/character/run.rs | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index b61ac2135c..9138ed56ef 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -26,11 +26,9 @@ impl Animation for IdleAnimation { let wave = (time as f32 * 12.0).sin(); let wavecos = (time as f32 * 12.0).cos(); let wave_slow = (time as f32 * 6.0 + PI).sin(); - let wave_slower = (time as f32 * 2.0 + PI).sin(); - let wavecos_slower = (time as f32 * 2.0 + PI).cos(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let waveultra_slow = (time as f32 * 1.0 + PI).sin(); let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); - let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / 11.0; diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 8db66c439d..90bd0d91d7 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -26,12 +26,10 @@ impl Animation for RunAnimation { let fuzzwave = (time as f32 * 12.0).sin(); let wavecos = (time as f32 * 14.0).cos(); let wave_slow = (time as f32 * 8.0 + PI).sin(); - let waveultra_slow = (time as f32 * 0.5 + PI).sin(); let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ 11.0; - //next.head.ori = Quaternion::rotation_z(); next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / 11.0; next.chest.ori = Quaternion::rotation_z(wave * 0.3); From ee4a261a28fe0051d03205a5e86804c076d87182 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:37:09 -0400 Subject: [PATCH 54/72] rebasing Former-commit-id: 38e7f49fb503caa9ca2377ac48f8fb3a1b22301e --- assets/voxygen | 2 +- voxygen/src/anim/character/mod.rs | 18 +++++++++--------- voxygen/src/anim/character/run.rs | 4 ++++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/assets/voxygen b/assets/voxygen index e3083ec8e8..0a176c4089 160000 --- a/assets/voxygen +++ b/assets/voxygen @@ -1 +1 @@ -Subproject commit e3083ec8e8e634af8c9daed00ea82435da195979 +Subproject commit 0a176c408946f081850132623a6730d9d2b1e7ed diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 3d6e3e1dfc..4d442d416e 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -20,10 +20,10 @@ const SCALE: f32 = 11.0; pub struct CharacterSkeleton { head: Bone, chest: Bone, - belt: Bone, - shorts: Bone, - l_hand: Bone, + bl_foot: Bone, + br_foot: Bone, r_hand: Bone, + l_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -34,10 +34,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - belt: Bone::default(), - shorts: Bone::default(), - l_hand: Bone::default(), + br_foot: Bone::default(), + bl_foot: Bone::default(), r_hand: Bone::default(), + l_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -52,10 +52,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.belt.compute_base_matrix()), - FigureBoneData::new(self.shorts.compute_base_matrix()), - FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.bl_foot.compute_base_matrix()), + FigureBoneData::new(self.br_foot.compute_base_matrix()), FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.l_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 27da889f95..a94788c0cf 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -24,9 +24,12 @@ impl Animation for RunAnimation { let mut next = (*skeleton).clone(); let wave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 12.0).cos(); let wave_slow = (time as f32 * 6.0 + PI).sin(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); +<<<<<<< HEAD next.head.offset = Vec3::unit_z() * 13.0 / SCALE; next.head.ori = Quaternion::rotation_z(wave * 0.3); @@ -52,5 +55,6 @@ impl Animation for RunAnimation { next.back.scale = Vec3::one(); next + } } From 164b9ee203dff4e8cb6a40e3ca58288bb9b6e60e Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 2 Mar 2019 18:05:21 -0500 Subject: [PATCH 55/72] adding test assets Former-commit-id: 9731a05a8b4bed89898513599f8689be5600bb0b --- voxygen/test_assets/body.vox | Bin 0 -> 6984 bytes voxygen/test_assets/dragon_body.vox | Bin 0 -> 9540 bytes voxygen/test_assets/dragon_lfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_rfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_tail.vox | Bin 0 -> 2080 bytes voxygen/test_assets/dragon_wingL_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingL_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragon_wingR_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingR_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragonhead.vox | Bin 0 -> 3040 bytes voxygen/test_assets/foot_BL.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_BR.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_FL.vox | Bin 0 -> 1192 bytes voxygen/test_assets/foot_FR.vox | Bin 0 -> 1192 bytes voxygen/test_assets/lionhead.vox | Bin 0 -> 5164 bytes voxygen/test_assets/sabremale.vox | Bin 0 -> 7436 bytes 16 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 voxygen/test_assets/body.vox create mode 100644 voxygen/test_assets/dragon_body.vox create mode 100644 voxygen/test_assets/dragon_lfoot.vox create mode 100644 voxygen/test_assets/dragon_rfoot.vox create mode 100644 voxygen/test_assets/dragon_tail.vox create mode 100644 voxygen/test_assets/dragon_wingL_in.vox create mode 100644 voxygen/test_assets/dragon_wingL_out.vox create mode 100644 voxygen/test_assets/dragon_wingR_in.vox create mode 100644 voxygen/test_assets/dragon_wingR_out.vox create mode 100644 voxygen/test_assets/dragonhead.vox create mode 100644 voxygen/test_assets/foot_BL.vox create mode 100644 voxygen/test_assets/foot_BR.vox create mode 100644 voxygen/test_assets/foot_FL.vox create mode 100644 voxygen/test_assets/foot_FR.vox create mode 100644 voxygen/test_assets/lionhead.vox create mode 100644 voxygen/test_assets/sabremale.vox diff --git a/voxygen/test_assets/body.vox b/voxygen/test_assets/body.vox new file mode 100644 index 0000000000000000000000000000000000000000..d6c7aa48dcc2c87e2cddbfa2b1ccb66f309a022f GIT binary patch literal 6984 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 IXVT@r0oGHx%>V!Z literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_lfoot.vox b/voxygen/test_assets/dragon_lfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..80828a713720e4be9d073de8f5282fa58a8c93bb GIT binary patch literal 1408 zcmchWZA@Eb6vxkV@9m4j7Z|0iFrjuZTA1Ud45%n`wkqoPZ3d|&EL&JZyJbt{XyU3((qzSoBqid*I2H`C7mUU^jlF7ABATA#{TlZ$iHs^SC=pfTdPYc0yq8hT zj7f>0smDtktem}y9PjD`fqB)w7NJ{q3`$0o`g+`FfZ z>-E*t)P#6Ejt7&3eOFeo&GH9+vsjSL1|Zipe;VCgH8_5>8S&vRq{sY7Paa2ldJv82 z2y(qv*pAs@f2#_vSr5o(0EIV!<~D;?t;h`!3QrTZP7ronCz!*8ClZ8w_SUO}`aljk zPv;^ynvV<1PopDF=t&Y@T_l`c^j}D(6d4d#eJ4{e-en z?mb0lSs~C%Jb%OtNWdKaIWW@W#MH?;#1A!M>Qp_oJ~gT6{DLiNQM z-&>BcpBgv;f^uFbo# zf8P=)F@l0<0hXs9zC-zrN=i!bc6kyt)q^;3@jSK+6yokz>--aI~3L9^3eOb_HCch)uY69m34AS^}IH!>yDW< SP({jXB)_ literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_rfoot.vox b/voxygen/test_assets/dragon_rfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..1e2bcfe32d72e45c57b712337b993ed77f354f69 GIT binary patch literal 1408 zcmc(eZA?>F7{{M`?(NHDFCeAZ;!0OR+T!G;2y`GTLZ=0bLuRKP65TYj>r6={M4M&{ zb~9s+jj;wKQ4tMci;*d5NtbeNq+f1 z|K~jCIp>~xZ)o2^`y>$s+XFo;^sbJmFA(-Wtr{L|X~W-o@K89=Dydl_wOHtsoX{&d zk|`%K;wd^Mj10#zqo{eoc}8YPVb2IgW)#)y*fX+`i6cvtzU?h$i zK{P~atVlT_OWd1Pkzx|7%qnwEVuXQndR9HFj#bBV>}6JAluikQU==ypAaat5BDfEG z6`hF52JXWMMdq{0IYq~Ly@)A#!79i9dbkD2;cjF{1ISJsMRsZs zP1zUz8Z3=&FD5;l($w%sHcql9NtgktvQ>x712 z0lH2WB0N%zkC&cDXOhsHCcL>oIJ3%Yd#$iV9H>aT(U|d}EN+5h%nJ8hIqL3Ip|qb+ zF~Yqk39ZWndX4u_7(wZ0L5n7gRuy5swgeA$mH}NaAWeiN<_G2%CViT)@C6}1Pq=%F zy^k>KC*<}M*54+C*`E#(#*cA+n9$)O3^WslI|&y!-`ikC#P2|&*NMsF^++CQ!sLk# z8uyWNgD zmjjL4x8kLG7sfx>jD;%>{CL-m_50Ph$a`ky2=~4v{QNy35pm)|%7c{~9r*31KE%%# zV(cpuZmn9dj`IKg`8^&FK5v>qP2DV7M$f{Mvf$2D!h<&m*PTwdTrTX`xD$K#EP_%A zl*CK0H1+r$?o|}nY&N`KnMQ5RAda0shfM>exc_w}mckZH@LfH5|7|T3TCYQW_Ygk; zoSB+O>RJY$F5brUcWc-&IEuEjGw8m&jJ}&|@cDdrL;x8X`~i85@bH_*=X=QC*MH6P zPl#&kE~wfj4Qd*!ifH$Ij`kOV literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_tail.vox b/voxygen/test_assets/dragon_tail.vox new file mode 100644 index 0000000000000000000000000000000000000000..050f21c65a3468e0a49993190171cc26cc9904a9 GIT binary patch literal 2080 zcmc(eYiO2r7{>qaY3}eIpVQp5x#npHQ|EMtrZx{tr%h9H=~B^Bat(2e5FNwNm9)$< z8&g4B7P3M#l}+C0gAEZ8L}W<>B_a`h?L$c4u71xW^}#QF?178>zW?`i-S_qU-{);x zyQy^07}L6>Wevf^bB)>1(%u~R3!Wkn136&R=Ju9fA|yPIL18$OEewZ2C|elvK_22P zLLMQHkcXo5K?H;hIfwuQ$G|agqU2HXXe2u^9LqZN9e56WkC+bfC@~B|*$j1tJsI|8 z*qdQ~hFuwUX4vha_s}~2IUY0UGUzNkSkxA^MQyXsVwTNr8xJ;KY&_X`vzcN0y})yf zI!X$2O$pUXav z+zVnjn+rD|B+(_&B$=5{KNm#c$A~!~N}dBR0xuTu`8~+fXwuXUz8(BKyoVQn9n=;a z3$GR&%fEB@mVXXE8q8uI-lHG_a_|+wcND||u!orDJ<|SN`oAOhV{tzg=N5Nl(X)7W zi@wDS%l~%hd;a~w^*HnB=fKPL!H#?%tIQJ9xeSQfO1?QtXJsEAYWt0sI2A1@QAZ z%L@?7=21uK<-y4#=5jv42lWK%3G^qR%i$~rlH|!CMzRU=1bG5p0xt=;3A`lmlE6!X z840{3@DhWwe#O!yCK~+BO?`d6dV72I=!DVAvo|%>`AdH~j>g7XI0FRHX;2R58>b(;SoO%$GT5$=vjmZZ#_0V>J1= z(X7ixxt&IdJ|mmjyI?fGwLq)(q}6`N)(6*~(ehrSbpuAPUotvy5AC{Qm2{M8T5qLl zN18OL+fmuEVpX1>qUu{SRk+1y+975S8ZEqTWL{x^Pp-^BQs%0o{+SsK&vkWw(Ijcr zvl=i)*T9e9H!!f@=+dV~W5Y(buTVD`oohDAt~Yw{rcpcf{x+lIJ2~HHw5-BtTfNb~ zhzxYierr zN!^g!Oii!#?uomg1l~-l@dgOMyx_0u(Z+NhnZ>OY0 z?@S-i+&Nv^dGv@TZY$K?Z>H;7dy!6XS5M#n;>Huftj!zlsC&0`;N-CSz8uj)LR6Tun_)dSoP%3-nl#aifRdKJoXE@9V$%{0mi8yi|T%9O?>U z>&%WIJ{M|KW@C4dPw)6Jh;1`Y2eBdC8$@5{KYna@<4_Q1oxUeKRiv6w$G^RQI8R0M EH>B;$0{{R3 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_in.vox b/voxygen/test_assets/dragon_wingL_in.vox new file mode 100644 index 0000000000000000000000000000000000000000..aa0a7eedb2afbf963d7ede5a3235f2f9b7bdf915 GIT binary patch literal 2884 zcmc)LTZ~m#9mnziz|5S>zMs9%KDW6s+-9JbYqw3=qN1qrvV`jUzj_)CCrDwKpd}4?1F8GY1i7q_x7SF)M<=D9PKCZY3H^0q`s_sX+X?Br z6VQLhXAF+VIGi$LaY~HGDKaLfz_^@V#^&@eKBt>8I`bK)Gmo(%?zVQ^!(2PP)($Z* zw{}-#{3MCJ=8BCQ|7*c3<;`;k+UulStCQTP6njU z`#u@C`6OE?qYoAC^^++%!1EsKF-Z1OH{|MB;|ek)s3Jzrx<{xXM8Nw2S#fJcHsPTK zpYz(sI|12GhU5VC1q>o(?^KW>K@}c*At!w@r0tMBR(0P&X4Ls)6CPS9^K2hV=tmI) zNE6ydh6Gi2%{=5}NJg$r+N-$lL4!T)bFT>xEtIM2BTHmIStL{Tc?B5~R1qU}ZMvkb zgmRs7L^jAWbxqPk%Uz=nB@~fzW-7=yHwjrKV=_mC8bZ_&pn;hAZjupgx5zR|D58Lr z^H)K}8B9<`j2sba2vJ9X27EN(p^OrW$T+_#s;D4G!nv-IF z-C*A}*dGnbb=I>^xlUb;^{w&yRpUA*D?FdDM-sQ5u1uRT<(Rf&>SLad9QI($J0a^B zavhL9^Y6i@98g!L{St~UIa@^(9L{ww9((wqt=4_-zi`8b4Vs>w)@P?okGyqD3$uUe zA6cfGH+Rc@-Wk8DJ-b%wnWr{s`p7O_JwC3hr=HQ(vu&-v`l8~oT#cuPH1x`Hjh^2q z+tDLCRF+++$Zq9|cbjT2nEFnd?t9l%JY))HOexp-+orX3Fs!d#nI4{Fz!M)chN^*XfEH1m|{{9)6LADh+sh%bp z8XD57(P6E-e~G@hdQ>OB*Qd)rAJ(5fT&BApFV~xV=j=t(N53=u-nl<{#`tw?`>Vh^Me^rf{hCcX(>634m-X0mz z=;){(s642zJaR=gb5zx-s;-^Aw}!7Y**gOR`tIV>TDhXFXJ3C!^@BBi{F}wPHqp>2 z=IZnFzh%>@xwf9%_mQTamtH=5Ni)BkRp-k4I`{iKdZ2w=TV6e{T|c{_eed4U*w~mp zGs%k3KQ;f3>C@ld>))sBum5$QQ>f+5hvafgS9>mZFP)srFLZ5E^7zzTdGX|r=5qg% nb91?I-t=6$_uR+j#%~>)%lppVRvI<5rfc%Q_x|(D=hFTSe|IGn literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_out.vox b/voxygen/test_assets/dragon_wingL_out.vox new file mode 100644 index 0000000000000000000000000000000000000000..879372f6d8d7af3fb5897159e1512c98499fe431 GIT binary patch literal 3544 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 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragonhead.vox b/voxygen/test_assets/dragonhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..0de9789f15d4495178dca869b50b40272cc46005 GIT binary patch literal 3040 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 S)HH5pGxbliZ6tnry!;FE;3mre literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_BR.vox b/voxygen/test_assets/foot_BR.vox new file mode 100644 index 0000000000000000000000000000000000000000..073a55c9e009ef5d5b79538af901e1f6f04bd83f GIT binary patch literal 1236 zcma)*e@L8l9LGP;^V~wR*)7lW$F1`^b-O!b?$q>5TW5N?d;GDSY1?fR7aMtqZ5$!n zaV)kg$%bW@=!BM8h{Tv}qEhsSlOba;#;_4V$QTj*+aD4A_v-t&KZmOiy!kwzpYQMI z^L)QO2M&2AM5Mhj+M$%(u!(d^&CU|Q%`A3D)^Q!lR(6A!Nn~Fb~g^cGQ3l2th?_h3k9`|2y zf%yXCA}lNXtnjk9bLT`j|LbNvgY+iT);5KYEKlX5*BXIBBRXru9`HCwpocFopCnVfsB` zh-NckutuUsYAbXSLH*1ZSupxj`wC!I& z(n<0Xc`Q#p`iJL=)ZKBrdB1F&ef1emTpXsLH=n!Tm9ZQvB;)Zswtp+n>UFs54vBs^ zJ2^-Cn?*iZxXILwbzV9>!oCaBw0^ll*R^%R;V=&cBujz6G1i3#KRi0$19iXtE3Tg4 W<~!R;Tfwbjmj6ky&Bjlzmwy2+<0jnz literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_FL.vox b/voxygen/test_assets/foot_FL.vox new file mode 100644 index 0000000000000000000000000000000000000000..23eab56821aed022d1485f7849650580a8a36cc5 GIT binary patch literal 1192 zcma)*Z%kWd6vofJWeE|7OiH0;mRewIiy12*6v0^pWWD^E48g722s13wG`OWPWNVt4 ztxCiNWwn7VaUvQ*%re|aOEi8!vXEuTvMjh56GN887{B_#7{C2|FZ0{N^d!%H?s?8V z=Y7w)?>lhdkZW2*x?4g$iX@#Q(iaN1KW#e7EdOGg;zNhSp0R-&NkIbG^us5e9O z90iMlZfLrML=!_aQ&+5OhNf8zUF5Q^bj^f_p=(-5Ghybdn5O9=O;^5dvZd=_$Ez)( z_G4Ng5Fn9A@GvFpzp_TT^>6;PT3KD~#%ow=oX4cg`HEv3)h9*sIWaL6e{0#RjBLE!x$|f ze6Em>mY<_7A@rt&w-$vn_f&4L182ldMZ!mYCP-<_ihI(5Z@vuwt=$wK6)MiD+S5Yw ziXd;O_2aonIv-iGGO>FH3ww*W|8gl9&yyBmS>Y#z-xSiPg~d;W)dk`94dn-gxpv{( zgTlt!LZm}DJs?a)Y>W>H(-C1XAdIyMmz3UH=OEJVCf@5|`a}(h{syK;T3P+@O@5z` zP*rZDxu%THS3H~;Xdr3`$z#IoyTZyRLcP;L$XCJ9`aQ(j8X54}h}4xb*-=Smu$uN} zKL=iGB>Z{{(V-sVC&NsA5GAuP&ic(Oq~39pI8sVpULGZdJE$%#!0&Zazh@UO)p(hD zeRwh(|nJO4hP=t(8B1=_7WbfXT0|+_-0FgEGQu z9-I9StGSE`t=_HsAMM)pSpUwFXYjd;@RjA$ z{ic%Tu$`34_1OH)@61|<`|c1Mfip7;B)`h=@zPB$|FF)BrzY5UewNP9SLnOGPB0kc rp@8Hn@E4YK;lX#0_V+-Yum6gxE4X>jwqi55Rm{|%6x%HP(yWrpBd!jLwE zjy9Xj6*rrO*upyJhR7&&tt7Is2PZ{Jp_Jmv7z`<8jJ@t*jJ^GKWA|3f7zz=p~KPQSUkr{1g^}{#$ zeLg}>rJ2^c3c6l#abmEEXh=vN6K3BPRz49L?N)-GDvmbpA=c5%pvO$4!Nyc)HQAwB z0o7nhRttX*s8k6-$UT`)5BwTT<|ENoCg zSj}Uz{}DBpaiQJ4b^l}CyB_P`Uj7UoXDObFVp`nA4EVM);Qjyo*Vor`v1yiC?;I_Y z=dmO$-1<_ue?++Ia^ZHn8Lb?rd;b!Wj8hsbWqIb&KRjzycgJq$z3MdkT2hQ$n4o;9 zjJw}dvmCaNayTBFe|}xQ*5Up;#75!F%mT@;vV6RBlgmG>^Wv#V_MM-l>+==*udn0x t`*|oJg$n+{ur56K?$P-ksQdL_arFc@-`Q3=AKWUI_dhANS@_BM@()`hBKH6Q literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/lionhead.vox b/voxygen/test_assets/lionhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..7d6727d68553a8bfa9c0b56db5003eab21bb2042 GIT binary patch literal 5164 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 E1MV8k_W%F@ literal 0 HcmV?d00001 From c655790c8ad69ee5ef7f4cdf985d6a3ee9927692 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 19 Apr 2019 19:42:12 -0400 Subject: [PATCH 56/72] merge fix Former-commit-id: a344856978c40e12d37dba5aaa0e0abac1dba9f4 --- voxygen/src/anim/character/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 4d442d416e..3d6e3e1dfc 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -20,10 +20,10 @@ const SCALE: f32 = 11.0; pub struct CharacterSkeleton { head: Bone, chest: Bone, - bl_foot: Bone, - br_foot: Bone, - r_hand: Bone, + belt: Bone, + shorts: Bone, l_hand: Bone, + r_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -34,10 +34,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - br_foot: Bone::default(), - bl_foot: Bone::default(), - r_hand: Bone::default(), + belt: Bone::default(), + shorts: Bone::default(), l_hand: Bone::default(), + r_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -52,10 +52,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.bl_foot.compute_base_matrix()), - FigureBoneData::new(self.br_foot.compute_base_matrix()), - FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.belt.compute_base_matrix()), + FigureBoneData::new(self.shorts.compute_base_matrix()), FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.r_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), From 7717d12c7a759ddbb30e642c755cbd3752df022e Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:47:15 -0400 Subject: [PATCH 57/72] more rebasing Former-commit-id: c38dde30d5ced7cefad40e3f4ae4208f412bdd23 --- voxygen/src/anim/character/idle.rs | 45 +++++++++++++++++++----------- voxygen/src/anim/character/run.rs | 41 ++++++++++++++------------- voxygen/src/scene/figure.rs | 20 ++++++------- 3 files changed, 61 insertions(+), 45 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index 9bada97c00..b4bbe69b0f 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -23,28 +23,41 @@ impl Animation for IdleAnimation { time: f64, ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - next.head.offset = Vec3::unit_z() * 13.0 / SCALE; - next.head.ori = Quaternion::rotation_z(0.0); - next.chest.offset = Vec3::unit_z() * 9.0 / SCALE; - next.chest.ori = Quaternion::rotation_z(0.0); + let wave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 12.0).cos(); + let wave_slow = (time as f32 * 6.0 + PI).sin(); + let wave_slower = (time as f32 * 2.0 + PI).sin(); + let wavecos_slower = (time as f32 * 2.0 + PI).cos(); + let waveultra_slow = (time as f32 * 1.0 + PI).sin(); + let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); + let wave_dip = (wave_slow.abs() - 0.5).abs(); - next.belt.offset = Vec3::unit_z() * 7.0 / SCALE; - next.belt.ori = Quaternion::rotation_z(0.0); + next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE; + next.head.ori = Quaternion::rotation_y(waveultra_slow * 0.05); - next.shorts.offset = Vec3::unit_z() * 4.0 / SCALE; - next.shorts.ori = Quaternion::rotation_z(0.0); + next.chest.offset = Vec3::new(0.0, 0.0, 8.0 + waveultra_slow * 0.4) / SCALE; + next.chest.ori = Quaternion::rotation_y(0.0); - next.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / SCALE; - next.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / SCALE; + next.belt.offset = Vec3::new(0.0, 0.0, 6.0 + waveultra_slow * 0.4) / SCALE; + next.belt.ori = Quaternion::rotation_y(0.0); - next.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / SCALE; - next.l_foot.ori = Quaternion::rotation_x(0.0); - next.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / SCALE; - next.r_foot.ori = Quaternion::rotation_x(0.0); + next.shorts.offset = Vec3::new(0.0, 0.0, 3.0 + waveultra_slow * 0.4) / SCALE; + next.shorts.ori = Quaternion::rotation_y(0.0); - next.back.offset = Vec3::new(-9.0, 5.0, 18.0); - next.back.ori = Quaternion::rotation_y(2.5); + next.l_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3, 7.5, 11.0 + waveultra_slow * 1.1) / SCALE; + next.l_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); + next.r_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3 , - 7.5, 11.0 + waveultra_slow * 1.1) / SCALE; + next.r_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); + + next.l_foot.offset = Vec3::new(2.5, 3.4, 6.0) / SCALE; + next.l_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04); + next.r_foot.offset = Vec3::new(2.5, -3.4, 6.0) / SCALE; + next.r_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04); + + next.back.offset = Vec3::new(-6.5, 16.0, 15.0); + next.back.ori = Quaternion::rotation_x(2.5); next.back.scale = Vec3::one(); next diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index a94788c0cf..3b82fc6eb8 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -23,35 +23,38 @@ impl Animation for RunAnimation { ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - let wave = (time as f32 * 12.0).sin(); - let wavecos = (time as f32 * 12.0).cos(); - let wave_slow = (time as f32 * 6.0 + PI).sin(); - let wavecos_slow = (time as f32 * 6.0 + PI).cos(); + let wave = (time as f32 * 14.0).sin(); + let fuzzwave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 14.0).cos(); + let wave_slow = (time as f32 * 8.0 + PI).sin(); + let waveultra_slow = (time as f32 * 0.5 + PI).sin(); + let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); -<<<<<<< HEAD - next.head.offset = Vec3::unit_z() * 13.0 / SCALE; - next.head.ori = Quaternion::rotation_z(wave * 0.3); + next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *0.4)/ SCALE; + //next.head.ori = Quaternion::rotation_z(); - next.chest.offset = Vec3::unit_z() * 9.0 / SCALE; - next.chest.ori = Quaternion::rotation_z(wave * 0.3); + next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.3) / SCALE; + next.chest.ori = Quaternion::rotation_z(wave * 0.2); - next.belt.offset = Vec3::unit_z() * 7.0 / SCALE; + next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.3)/ SCALE; next.belt.ori = Quaternion::rotation_z(wave * 0.2); - next.shorts.offset = Vec3::unit_z() * 4.0 / SCALE; + next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.3) / SCALE; next.shorts.ori = Quaternion::rotation_z(wave * 0.1); - next.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0) / SCALE; - next.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0) / SCALE; + next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / SCALE; + next.l_hand.ori = Quaternion::rotation_y(wave * -1.8); + next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE; + next.r_hand.ori = Quaternion::rotation_y(wave * 1.8); - next.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0) / SCALE; - next.l_foot.ori = Quaternion::rotation_x(-wave + 1.0); - next.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0) / SCALE; - next.r_foot.ori = Quaternion::rotation_x(wave + 1.0); + next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.5) / SCALE; + next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); + next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.5) / SCALE; + next.r_foot.ori = Quaternion::rotation_y(wave * 1.0); - next.back.offset = Vec3::new(-9.0, 5.0, 18.0); - next.back.ori = Quaternion::rotation_y(2.5); + next.back.offset = Vec3::new(-6.0, 16.0, 15.0); + next.back.ori = Quaternion::rotation_x(2.5); next.back.scale = Vec3::one(); next diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 66f1a65b27..f75d768e89 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -47,15 +47,15 @@ impl Figures { } let bone_meshes = [ - Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -6.5, -6.0))), - Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))), - Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))), + Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.5, -7.0, -6.0))), + Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))), + Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), + Some(load_segment("pants.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), + Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))), + Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))), + Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))), + Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))), + Some(load_segment("sword.vox").generate_mesh(Vec3::new(0.0, -0.0, 0.0))), None, None, None, @@ -138,7 +138,7 @@ impl FigureState { let mat = Mat4::::identity() * Mat4::translation_3d(pos) * - Mat4::rotation_z(dir.y.atan2(dir.x) + f32::consts::PI / 2.0); + Mat4::rotation_z(dir.y.atan2(dir.x));// + f32//::consts)::PI / 2.0); let locals = FigureLocals::new(mat); renderer.update_consts(&mut self.locals, &[locals]).unwrap(); From 30e80bdfc39c08ca928439e21d7f3f0b7c8730d1 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 17:33:51 -0400 Subject: [PATCH 58/72] animattion tweaks Former-commit-id: 8e1b89a929761fee2a46aab4689a3dee72573eff --- voxygen/src/scene/figure.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index f75d768e89..d8e54ecbe4 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -47,7 +47,7 @@ impl Figures { } let bone_meshes = [ - Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.5, -7.0, -6.0))), + Some(load_segment("head.vox").generate_mesh(Vec3::new(-3.5, -7.0, -6.0))), Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))), Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), Some(load_segment("pants.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), From 83f8759746762dc57124cadc27cd5699ac563541 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:12:45 -0400 Subject: [PATCH 59/72] tidying up code Former-commit-id: 062930589922dc903be9e959eb06fd203945c101 --- voxygen/src/anim/character/idle.rs | 4 +--- voxygen/src/anim/character/run.rs | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index b4bbe69b0f..d6d48a5550 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -27,11 +27,9 @@ impl Animation for IdleAnimation { let wave = (time as f32 * 12.0).sin(); let wavecos = (time as f32 * 12.0).cos(); let wave_slow = (time as f32 * 6.0 + PI).sin(); - let wave_slower = (time as f32 * 2.0 + PI).sin(); - let wavecos_slower = (time as f32 * 2.0 + PI).cos(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let waveultra_slow = (time as f32 * 1.0 + PI).sin(); let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); - let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE; diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 3b82fc6eb8..49aa331cc7 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -27,12 +27,11 @@ impl Animation for RunAnimation { let fuzzwave = (time as f32 * 12.0).sin(); let wavecos = (time as f32 * 14.0).cos(); let wave_slow = (time as f32 * 8.0 + PI).sin(); - let waveultra_slow = (time as f32 * 0.5 + PI).sin(); let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); + next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *0.4)/ SCALE; - //next.head.ori = Quaternion::rotation_z(); next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.3) / SCALE; next.chest.ori = Quaternion::rotation_z(wave * 0.2); From a04ddf67f6b2886f89b05ea1b07b5a92421d2343 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 2 Mar 2019 17:41:34 -0500 Subject: [PATCH 60/72] quadruped testing Former-commit-id: 07f4fb4484f26dae0e8503ddec32a17f2fa312b5 --- assets/voxygen | 2 +- voxygen/src/anim/character/mod.rs | 18 +++++++++--------- voxygen/src/anim/character/run.rs | 3 +++ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/assets/voxygen b/assets/voxygen index e3083ec8e8..0a176c4089 160000 --- a/assets/voxygen +++ b/assets/voxygen @@ -1 +1 @@ -Subproject commit e3083ec8e8e634af8c9daed00ea82435da195979 +Subproject commit 0a176c408946f081850132623a6730d9d2b1e7ed diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 3d6e3e1dfc..4d442d416e 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -20,10 +20,10 @@ const SCALE: f32 = 11.0; pub struct CharacterSkeleton { head: Bone, chest: Bone, - belt: Bone, - shorts: Bone, - l_hand: Bone, + bl_foot: Bone, + br_foot: Bone, r_hand: Bone, + l_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -34,10 +34,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - belt: Bone::default(), - shorts: Bone::default(), - l_hand: Bone::default(), + br_foot: Bone::default(), + bl_foot: Bone::default(), r_hand: Bone::default(), + l_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -52,10 +52,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.belt.compute_base_matrix()), - FigureBoneData::new(self.shorts.compute_base_matrix()), - FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.bl_foot.compute_base_matrix()), + FigureBoneData::new(self.br_foot.compute_base_matrix()), FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.l_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 27da889f95..258b610205 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -24,7 +24,9 @@ impl Animation for RunAnimation { let mut next = (*skeleton).clone(); let wave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 12.0).cos(); let wave_slow = (time as f32 * 6.0 + PI).sin(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); next.head.offset = Vec3::unit_z() * 13.0 / SCALE; @@ -52,5 +54,6 @@ impl Animation for RunAnimation { next.back.scale = Vec3::one(); next + } } From ab17221dad762a34538b5cd5642b44217aa712d9 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 2 Mar 2019 18:05:21 -0500 Subject: [PATCH 61/72] adding test assets Former-commit-id: 7d8f9b19d8ec1b31a67d3d650a9e64aa23fc741c --- voxygen/test_assets/body.vox | Bin 0 -> 6984 bytes voxygen/test_assets/dragon_body.vox | Bin 0 -> 9540 bytes voxygen/test_assets/dragon_lfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_rfoot.vox | Bin 0 -> 1408 bytes voxygen/test_assets/dragon_tail.vox | Bin 0 -> 2080 bytes voxygen/test_assets/dragon_wingL_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingL_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragon_wingR_in.vox | Bin 0 -> 2884 bytes voxygen/test_assets/dragon_wingR_out.vox | Bin 0 -> 3544 bytes voxygen/test_assets/dragonhead.vox | Bin 0 -> 3040 bytes voxygen/test_assets/foot_BL.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_BR.vox | Bin 0 -> 1236 bytes voxygen/test_assets/foot_FL.vox | Bin 0 -> 1192 bytes voxygen/test_assets/foot_FR.vox | Bin 0 -> 1192 bytes voxygen/test_assets/lionhead.vox | Bin 0 -> 5164 bytes voxygen/test_assets/sabremale.vox | Bin 0 -> 7436 bytes 16 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 voxygen/test_assets/body.vox create mode 100644 voxygen/test_assets/dragon_body.vox create mode 100644 voxygen/test_assets/dragon_lfoot.vox create mode 100644 voxygen/test_assets/dragon_rfoot.vox create mode 100644 voxygen/test_assets/dragon_tail.vox create mode 100644 voxygen/test_assets/dragon_wingL_in.vox create mode 100644 voxygen/test_assets/dragon_wingL_out.vox create mode 100644 voxygen/test_assets/dragon_wingR_in.vox create mode 100644 voxygen/test_assets/dragon_wingR_out.vox create mode 100644 voxygen/test_assets/dragonhead.vox create mode 100644 voxygen/test_assets/foot_BL.vox create mode 100644 voxygen/test_assets/foot_BR.vox create mode 100644 voxygen/test_assets/foot_FL.vox create mode 100644 voxygen/test_assets/foot_FR.vox create mode 100644 voxygen/test_assets/lionhead.vox create mode 100644 voxygen/test_assets/sabremale.vox diff --git a/voxygen/test_assets/body.vox b/voxygen/test_assets/body.vox new file mode 100644 index 0000000000000000000000000000000000000000..d6c7aa48dcc2c87e2cddbfa2b1ccb66f309a022f GIT binary patch literal 6984 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 IXVT@r0oGHx%>V!Z literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_lfoot.vox b/voxygen/test_assets/dragon_lfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..80828a713720e4be9d073de8f5282fa58a8c93bb GIT binary patch literal 1408 zcmchWZA@Eb6vxkV@9m4j7Z|0iFrjuZTA1Ud45%n`wkqoPZ3d|&EL&JZyJbt{XyU3((qzSoBqid*I2H`C7mUU^jlF7ABATA#{TlZ$iHs^SC=pfTdPYc0yq8hT zj7f>0smDtktem}y9PjD`fqB)w7NJ{q3`$0o`g+`FfZ z>-E*t)P#6Ejt7&3eOFeo&GH9+vsjSL1|Zipe;VCgH8_5>8S&vRq{sY7Paa2ldJv82 z2y(qv*pAs@f2#_vSr5o(0EIV!<~D;?t;h`!3QrTZP7ronCz!*8ClZ8w_SUO}`aljk zPv;^ynvV<1PopDF=t&Y@T_l`c^j}D(6d4d#eJ4{e-en z?mb0lSs~C%Jb%OtNWdKaIWW@W#MH?;#1A!M>Qp_oJ~gT6{DLiNQM z-&>BcpBgv;f^uFbo# zf8P=)F@l0<0hXs9zC-zrN=i!bc6kyt)q^;3@jSK+6yokz>--aI~3L9^3eOb_HCch)uY69m34AS^}IH!>yDW< SP({jXB)_ literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_rfoot.vox b/voxygen/test_assets/dragon_rfoot.vox new file mode 100644 index 0000000000000000000000000000000000000000..1e2bcfe32d72e45c57b712337b993ed77f354f69 GIT binary patch literal 1408 zcmc(eZA?>F7{{M`?(NHDFCeAZ;!0OR+T!G;2y`GTLZ=0bLuRKP65TYj>r6={M4M&{ zb~9s+jj;wKQ4tMci;*d5NtbeNq+f1 z|K~jCIp>~xZ)o2^`y>$s+XFo;^sbJmFA(-Wtr{L|X~W-o@K89=Dydl_wOHtsoX{&d zk|`%K;wd^Mj10#zqo{eoc}8YPVb2IgW)#)y*fX+`i6cvtzU?h$i zK{P~atVlT_OWd1Pkzx|7%qnwEVuXQndR9HFj#bBV>}6JAluikQU==ypAaat5BDfEG z6`hF52JXWMMdq{0IYq~Ly@)A#!79i9dbkD2;cjF{1ISJsMRsZs zP1zUz8Z3=&FD5;l($w%sHcql9NtgktvQ>x712 z0lH2WB0N%zkC&cDXOhsHCcL>oIJ3%Yd#$iV9H>aT(U|d}EN+5h%nJ8hIqL3Ip|qb+ zF~Yqk39ZWndX4u_7(wZ0L5n7gRuy5swgeA$mH}NaAWeiN<_G2%CViT)@C6}1Pq=%F zy^k>KC*<}M*54+C*`E#(#*cA+n9$)O3^WslI|&y!-`ikC#P2|&*NMsF^++CQ!sLk# z8uyWNgD zmjjL4x8kLG7sfx>jD;%>{CL-m_50Ph$a`ky2=~4v{QNy35pm)|%7c{~9r*31KE%%# zV(cpuZmn9dj`IKg`8^&FK5v>qP2DV7M$f{Mvf$2D!h<&m*PTwdTrTX`xD$K#EP_%A zl*CK0H1+r$?o|}nY&N`KnMQ5RAda0shfM>exc_w}mckZH@LfH5|7|T3TCYQW_Ygk; zoSB+O>RJY$F5brUcWc-&IEuEjGw8m&jJ}&|@cDdrL;x8X`~i85@bH_*=X=QC*MH6P zPl#&kE~wfj4Qd*!ifH$Ij`kOV literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_tail.vox b/voxygen/test_assets/dragon_tail.vox new file mode 100644 index 0000000000000000000000000000000000000000..050f21c65a3468e0a49993190171cc26cc9904a9 GIT binary patch literal 2080 zcmc(eYiO2r7{>qaY3}eIpVQp5x#npHQ|EMtrZx{tr%h9H=~B^Bat(2e5FNwNm9)$< z8&g4B7P3M#l}+C0gAEZ8L}W<>B_a`h?L$c4u71xW^}#QF?178>zW?`i-S_qU-{);x zyQy^07}L6>Wevf^bB)>1(%u~R3!Wkn136&R=Ju9fA|yPIL18$OEewZ2C|elvK_22P zLLMQHkcXo5K?H;hIfwuQ$G|agqU2HXXe2u^9LqZN9e56WkC+bfC@~B|*$j1tJsI|8 z*qdQ~hFuwUX4vha_s}~2IUY0UGUzNkSkxA^MQyXsVwTNr8xJ;KY&_X`vzcN0y})yf zI!X$2O$pUXav z+zVnjn+rD|B+(_&B$=5{KNm#c$A~!~N}dBR0xuTu`8~+fXwuXUz8(BKyoVQn9n=;a z3$GR&%fEB@mVXXE8q8uI-lHG_a_|+wcND||u!orDJ<|SN`oAOhV{tzg=N5Nl(X)7W zi@wDS%l~%hd;a~w^*HnB=fKPL!H#?%tIQJ9xeSQfO1?QtXJsEAYWt0sI2A1@QAZ z%L@?7=21uK<-y4#=5jv42lWK%3G^qR%i$~rlH|!CMzRU=1bG5p0xt=;3A`lmlE6!X z840{3@DhWwe#O!yCK~+BO?`d6dV72I=!DVAvo|%>`AdH~j>g7XI0FRHX;2R58>b(;SoO%$GT5$=vjmZZ#_0V>J1= z(X7ixxt&IdJ|mmjyI?fGwLq)(q}6`N)(6*~(ehrSbpuAPUotvy5AC{Qm2{M8T5qLl zN18OL+fmuEVpX1>qUu{SRk+1y+975S8ZEqTWL{x^Pp-^BQs%0o{+SsK&vkWw(Ijcr zvl=i)*T9e9H!!f@=+dV~W5Y(buTVD`oohDAt~Yw{rcpcf{x+lIJ2~HHw5-BtTfNb~ zhzxYierr zN!^g!Oii!#?uomg1l~-l@dgOMyx_0u(Z+NhnZ>OY0 z?@S-i+&Nv^dGv@TZY$K?Z>H;7dy!6XS5M#n;>Huftj!zlsC&0`;N-CSz8uj)LR6Tun_)dSoP%3-nl#aifRdKJoXE@9V$%{0mi8yi|T%9O?>U z>&%WIJ{M|KW@C4dPw)6Jh;1`Y2eBdC8$@5{KYna@<4_Q1oxUeKRiv6w$G^RQI8R0M EH>B;$0{{R3 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_in.vox b/voxygen/test_assets/dragon_wingL_in.vox new file mode 100644 index 0000000000000000000000000000000000000000..aa0a7eedb2afbf963d7ede5a3235f2f9b7bdf915 GIT binary patch literal 2884 zcmc)LTZ~m#9mnziz|5S>zMs9%KDW6s+-9JbYqw3=qN1qrvV`jUzj_)CCrDwKpd}4?1F8GY1i7q_x7SF)M<=D9PKCZY3H^0q`s_sX+X?Br z6VQLhXAF+VIGi$LaY~HGDKaLfz_^@V#^&@eKBt>8I`bK)Gmo(%?zVQ^!(2PP)($Z* zw{}-#{3MCJ=8BCQ|7*c3<;`;k+UulStCQTP6njU z`#u@C`6OE?qYoAC^^++%!1EsKF-Z1OH{|MB;|ek)s3Jzrx<{xXM8Nw2S#fJcHsPTK zpYz(sI|12GhU5VC1q>o(?^KW>K@}c*At!w@r0tMBR(0P&X4Ls)6CPS9^K2hV=tmI) zNE6ydh6Gi2%{=5}NJg$r+N-$lL4!T)bFT>xEtIM2BTHmIStL{Tc?B5~R1qU}ZMvkb zgmRs7L^jAWbxqPk%Uz=nB@~fzW-7=yHwjrKV=_mC8bZ_&pn;hAZjupgx5zR|D58Lr z^H)K}8B9<`j2sba2vJ9X27EN(p^OrW$T+_#s;D4G!nv-IF z-C*A}*dGnbb=I>^xlUb;^{w&yRpUA*D?FdDM-sQ5u1uRT<(Rf&>SLad9QI($J0a^B zavhL9^Y6i@98g!L{St~UIa@^(9L{ww9((wqt=4_-zi`8b4Vs>w)@P?okGyqD3$uUe zA6cfGH+Rc@-Wk8DJ-b%wnWr{s`p7O_JwC3hr=HQ(vu&-v`l8~oT#cuPH1x`Hjh^2q z+tDLCRF+++$Zq9|cbjT2nEFnd?t9l%JY))HOexp-+orX3Fs!d#nI4{Fz!M)chN^*XfEH1m|{{9)6LADh+sh%bp z8XD57(P6E-e~G@hdQ>OB*Qd)rAJ(5fT&BApFV~xV=j=t(N53=u-nl<{#`tw?`>Vh^Me^rf{hCcX(>634m-X0mz z=;){(s642zJaR=gb5zx-s;-^Aw}!7Y**gOR`tIV>TDhXFXJ3C!^@BBi{F}wPHqp>2 z=IZnFzh%>@xwf9%_mQTamtH=5Ni)BkRp-k4I`{iKdZ2w=TV6e{T|c{_eed4U*w~mp zGs%k3KQ;f3>C@ld>))sBum5$QQ>f+5hvafgS9>mZFP)srFLZ5E^7zzTdGX|r=5qg% nb91?I-t=6$_uR+j#%~>)%lppVRvI<5rfc%Q_x|(D=hFTSe|IGn literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragon_wingL_out.vox b/voxygen/test_assets/dragon_wingL_out.vox new file mode 100644 index 0000000000000000000000000000000000000000..879372f6d8d7af3fb5897159e1512c98499fe431 GIT binary patch literal 3544 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 literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/dragonhead.vox b/voxygen/test_assets/dragonhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..0de9789f15d4495178dca869b50b40272cc46005 GIT binary patch literal 3040 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 S)HH5pGxbliZ6tnry!;FE;3mre literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_BR.vox b/voxygen/test_assets/foot_BR.vox new file mode 100644 index 0000000000000000000000000000000000000000..073a55c9e009ef5d5b79538af901e1f6f04bd83f GIT binary patch literal 1236 zcma)*e@L8l9LGP;^V~wR*)7lW$F1`^b-O!b?$q>5TW5N?d;GDSY1?fR7aMtqZ5$!n zaV)kg$%bW@=!BM8h{Tv}qEhsSlOba;#;_4V$QTj*+aD4A_v-t&KZmOiy!kwzpYQMI z^L)QO2M&2AM5Mhj+M$%(u!(d^&CU|Q%`A3D)^Q!lR(6A!Nn~Fb~g^cGQ3l2th?_h3k9`|2y zf%yXCA}lNXtnjk9bLT`j|LbNvgY+iT);5KYEKlX5*BXIBBRXru9`HCwpocFopCnVfsB` zh-NckutuUsYAbXSLH*1ZSupxj`wC!I& z(n<0Xc`Q#p`iJL=)ZKBrdB1F&ef1emTpXsLH=n!Tm9ZQvB;)Zswtp+n>UFs54vBs^ zJ2^-Cn?*iZxXILwbzV9>!oCaBw0^ll*R^%R;V=&cBujz6G1i3#KRi0$19iXtE3Tg4 W<~!R;Tfwbjmj6ky&Bjlzmwy2+<0jnz literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/foot_FL.vox b/voxygen/test_assets/foot_FL.vox new file mode 100644 index 0000000000000000000000000000000000000000..23eab56821aed022d1485f7849650580a8a36cc5 GIT binary patch literal 1192 zcma)*Z%kWd6vofJWeE|7OiH0;mRewIiy12*6v0^pWWD^E48g722s13wG`OWPWNVt4 ztxCiNWwn7VaUvQ*%re|aOEi8!vXEuTvMjh56GN887{B_#7{C2|FZ0{N^d!%H?s?8V z=Y7w)?>lhdkZW2*x?4g$iX@#Q(iaN1KW#e7EdOGg;zNhSp0R-&NkIbG^us5e9O z90iMlZfLrML=!_aQ&+5OhNf8zUF5Q^bj^f_p=(-5Ghybdn5O9=O;^5dvZd=_$Ez)( z_G4Ng5Fn9A@GvFpzp_TT^>6;PT3KD~#%ow=oX4cg`HEv3)h9*sIWaL6e{0#RjBLE!x$|f ze6Em>mY<_7A@rt&w-$vn_f&4L182ldMZ!mYCP-<_ihI(5Z@vuwt=$wK6)MiD+S5Yw ziXd;O_2aonIv-iGGO>FH3ww*W|8gl9&yyBmS>Y#z-xSiPg~d;W)dk`94dn-gxpv{( zgTlt!LZm}DJs?a)Y>W>H(-C1XAdIyMmz3UH=OEJVCf@5|`a}(h{syK;T3P+@O@5z` zP*rZDxu%THS3H~;Xdr3`$z#IoyTZyRLcP;L$XCJ9`aQ(j8X54}h}4xb*-=Smu$uN} zKL=iGB>Z{{(V-sVC&NsA5GAuP&ic(Oq~39pI8sVpULGZdJE$%#!0&Zazh@UO)p(hD zeRwh(|nJO4hP=t(8B1=_7WbfXT0|+_-0FgEGQu z9-I9StGSE`t=_HsAMM)pSpUwFXYjd;@RjA$ z{ic%Tu$`34_1OH)@61|<`|c1Mfip7;B)`h=@zPB$|FF)BrzY5UewNP9SLnOGPB0kc rp@8Hn@E4YK;lX#0_V+-Yum6gxE4X>jwqi55Rm{|%6x%HP(yWrpBd!jLwE zjy9Xj6*rrO*upyJhR7&&tt7Is2PZ{Jp_Jmv7z`<8jJ@t*jJ^GKWA|3f7zz=p~KPQSUkr{1g^}{#$ zeLg}>rJ2^c3c6l#abmEEXh=vN6K3BPRz49L?N)-GDvmbpA=c5%pvO$4!Nyc)HQAwB z0o7nhRttX*s8k6-$UT`)5BwTT<|ENoCg zSj}Uz{}DBpaiQJ4b^l}CyB_P`Uj7UoXDObFVp`nA4EVM);Qjyo*Vor`v1yiC?;I_Y z=dmO$-1<_ue?++Ia^ZHn8Lb?rd;b!Wj8hsbWqIb&KRjzycgJq$z3MdkT2hQ$n4o;9 zjJw}dvmCaNayTBFe|}xQ*5Up;#75!F%mT@;vV6RBlgmG>^Wv#V_MM-l>+==*udn0x t`*|oJg$n+{ur56K?$P-ksQdL_arFc@-`Q3=AKWUI_dhANS@_BM@()`hBKH6Q literal 0 HcmV?d00001 diff --git a/voxygen/test_assets/lionhead.vox b/voxygen/test_assets/lionhead.vox new file mode 100644 index 0000000000000000000000000000000000000000..7d6727d68553a8bfa9c0b56db5003eab21bb2042 GIT binary patch literal 5164 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 E1MV8k_W%F@ literal 0 HcmV?d00001 From 33411a6004e38f73cd31f37083db030c29723d83 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 19 Apr 2019 19:42:12 -0400 Subject: [PATCH 62/72] merge fix Former-commit-id: 15da549d36774bb3713297d2b9f3799b1d7eb5f4 --- voxygen/src/anim/character/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 4d442d416e..3d6e3e1dfc 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -20,10 +20,10 @@ const SCALE: f32 = 11.0; pub struct CharacterSkeleton { head: Bone, chest: Bone, - bl_foot: Bone, - br_foot: Bone, - r_hand: Bone, + belt: Bone, + shorts: Bone, l_hand: Bone, + r_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -34,10 +34,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - br_foot: Bone::default(), - bl_foot: Bone::default(), - r_hand: Bone::default(), + belt: Bone::default(), + shorts: Bone::default(), l_hand: Bone::default(), + r_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -52,10 +52,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.bl_foot.compute_base_matrix()), - FigureBoneData::new(self.br_foot.compute_base_matrix()), - FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.belt.compute_base_matrix()), + FigureBoneData::new(self.shorts.compute_base_matrix()), FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.r_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), From 78d7cfd89dd3e1beb8ea3319054e6dd985bfe980 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 19 Apr 2019 20:20:01 -0400 Subject: [PATCH 63/72] animation adjustments Former-commit-id: d396ddadf4293212f9f6f7142de0d8a519e127d6 --- voxygen/src/anim/character/idle.rs | 45 +++++++++++++++++++----------- voxygen/src/anim/character/run.rs | 39 ++++++++++++++------------ voxygen/src/scene/figure.rs | 20 ++++++------- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index 9bada97c00..b4bbe69b0f 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -23,28 +23,41 @@ impl Animation for IdleAnimation { time: f64, ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - next.head.offset = Vec3::unit_z() * 13.0 / SCALE; - next.head.ori = Quaternion::rotation_z(0.0); - next.chest.offset = Vec3::unit_z() * 9.0 / SCALE; - next.chest.ori = Quaternion::rotation_z(0.0); + let wave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 12.0).cos(); + let wave_slow = (time as f32 * 6.0 + PI).sin(); + let wave_slower = (time as f32 * 2.0 + PI).sin(); + let wavecos_slower = (time as f32 * 2.0 + PI).cos(); + let waveultra_slow = (time as f32 * 1.0 + PI).sin(); + let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); + let wave_dip = (wave_slow.abs() - 0.5).abs(); - next.belt.offset = Vec3::unit_z() * 7.0 / SCALE; - next.belt.ori = Quaternion::rotation_z(0.0); + next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE; + next.head.ori = Quaternion::rotation_y(waveultra_slow * 0.05); - next.shorts.offset = Vec3::unit_z() * 4.0 / SCALE; - next.shorts.ori = Quaternion::rotation_z(0.0); + next.chest.offset = Vec3::new(0.0, 0.0, 8.0 + waveultra_slow * 0.4) / SCALE; + next.chest.ori = Quaternion::rotation_y(0.0); - next.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / SCALE; - next.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / SCALE; + next.belt.offset = Vec3::new(0.0, 0.0, 6.0 + waveultra_slow * 0.4) / SCALE; + next.belt.ori = Quaternion::rotation_y(0.0); - next.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / SCALE; - next.l_foot.ori = Quaternion::rotation_x(0.0); - next.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / SCALE; - next.r_foot.ori = Quaternion::rotation_x(0.0); + next.shorts.offset = Vec3::new(0.0, 0.0, 3.0 + waveultra_slow * 0.4) / SCALE; + next.shorts.ori = Quaternion::rotation_y(0.0); - next.back.offset = Vec3::new(-9.0, 5.0, 18.0); - next.back.ori = Quaternion::rotation_y(2.5); + next.l_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3, 7.5, 11.0 + waveultra_slow * 1.1) / SCALE; + next.l_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); + next.r_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3 , - 7.5, 11.0 + waveultra_slow * 1.1) / SCALE; + next.r_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06); + + next.l_foot.offset = Vec3::new(2.5, 3.4, 6.0) / SCALE; + next.l_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04); + next.r_foot.offset = Vec3::new(2.5, -3.4, 6.0) / SCALE; + next.r_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04); + + next.back.offset = Vec3::new(-6.5, 16.0, 15.0); + next.back.ori = Quaternion::rotation_x(2.5); next.back.scale = Vec3::one(); next diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 258b610205..5b06e64d1a 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -23,34 +23,37 @@ impl Animation for RunAnimation { ) -> Self::Skeleton { let mut next = (*skeleton).clone(); - let wave = (time as f32 * 12.0).sin(); - let wavecos = (time as f32 * 12.0).cos(); - let wave_slow = (time as f32 * 6.0 + PI).sin(); - let wavecos_slow = (time as f32 * 6.0 + PI).cos(); + let wave = (time as f32 * 14.0).sin(); + let fuzzwave = (time as f32 * 12.0).sin(); + let wavecos = (time as f32 * 14.0).cos(); + let wave_slow = (time as f32 * 8.0 + PI).sin(); + let waveultra_slow = (time as f32 * 0.5 + PI).sin(); + let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); - next.head.offset = Vec3::unit_z() * 13.0 / SCALE; - next.head.ori = Quaternion::rotation_z(wave * 0.3); + next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *0.4)/ SCALE; - next.chest.offset = Vec3::unit_z() * 9.0 / SCALE; - next.chest.ori = Quaternion::rotation_z(wave * 0.3); + next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.3) / SCALE; + next.chest.ori = Quaternion::rotation_z(wave * 0.2); - next.belt.offset = Vec3::unit_z() * 7.0 / SCALE; + next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.3)/ SCALE; next.belt.ori = Quaternion::rotation_z(wave * 0.2); - next.shorts.offset = Vec3::unit_z() * 4.0 / SCALE; + next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.3) / SCALE; next.shorts.ori = Quaternion::rotation_z(wave * 0.1); - next.l_hand.offset = Vec3::new(-6.0 - wave_dip * 6.0, wave * 5.0, 11.0 - wave_dip * 6.0) / SCALE; - next.r_hand.offset = Vec3::new(6.0 + wave_dip * 6.0, -wave * 5.0, 11.0 - wave_dip * 6.0) / SCALE; + next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / SCALE; + next.l_hand.ori = Quaternion::rotation_y(wave * -1.8); + next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE; + next.r_hand.ori = Quaternion::rotation_y(wave * 1.8); - next.l_foot.offset = Vec3::new(-3.5, 1.0 - wave * 8.0, 3.5 - wave_dip * 4.0) / SCALE; - next.l_foot.ori = Quaternion::rotation_x(-wave + 1.0); - next.r_foot.offset = Vec3::new(3.5, 1.0 + wave * 8.0, 3.5 - wave_dip * 4.0) / SCALE; - next.r_foot.ori = Quaternion::rotation_x(wave + 1.0); + next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.5) / SCALE; + next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); + next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.5) / SCALE; + next.r_foot.ori = Quaternion::rotation_y(wave * 1.0); - next.back.offset = Vec3::new(-9.0, 5.0, 18.0); - next.back.ori = Quaternion::rotation_y(2.5); + next.back.offset = Vec3::new(-6.0, 16.0, 15.0); + next.back.ori = Quaternion::rotation_x(2.5); next.back.scale = Vec3::one(); next diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 849e865686..3a0c0a726e 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -53,15 +53,15 @@ impl Figures { } let bone_meshes = [ - Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.0, -6.5, -6.0))), - Some(load_segment("chest.vox").generate_mesh(Vec3::new(-6.0, -3.0, 0.0))), - Some(load_segment("belt.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("pants.vox").generate_mesh(Vec3::new(-5.0, -3.0, 0.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("hand.vox").generate_mesh(Vec3::new(-2.0, -2.0, -1.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("foot.vox").generate_mesh(Vec3::new(-2.5, -3.0, -2.0))), - Some(load_segment("sword.vox").generate_mesh(Vec3::new(-6.5, -1.0, 0.0))), + Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.5, -7.0, -6.0))), + Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))), + Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), + Some(load_segment("pants.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), + Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))), + Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -6.0))), + Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))), + Some(load_segment("foot.vox").generate_mesh(Vec3::new(-4.0, -2.5, -6.0))), + Some(load_segment("sword.vox").generate_mesh(Vec3::new(0.0, -0.0, 0.0))), None, None, None, @@ -144,7 +144,7 @@ impl FigureState { let mat = Mat4::::identity() * Mat4::translation_3d(pos) * - Mat4::rotation_z(dir.y.atan2(dir.x) + f32::consts::PI / 2.0); + Mat4::rotation_z(dir.y.atan2(dir.x));// + f32//::consts)::PI / 2.0); let locals = FigureLocals::new(mat); renderer.update_consts(&mut self.locals, &[locals]).unwrap(); From 0137a83dd838ff070053d7c3512ec34286361c83 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 17:33:51 -0400 Subject: [PATCH 64/72] animattion tweaks Former-commit-id: ea560ba0f06432d2d4f9d4f1906f77451a7f5ef7 --- voxygen/src/scene/figure.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 3a0c0a726e..3898ed4b4e 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -53,7 +53,7 @@ impl Figures { } let bone_meshes = [ - Some(load_segment("head.vox").generate_mesh(Vec3::new(-7.5, -7.0, -6.0))), + Some(load_segment("head.vox").generate_mesh(Vec3::new(-3.5, -7.0, -6.0))), Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))), Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), Some(load_segment("pants.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), From 6fd783e6eb603b1403b18b3dc7e2eb1975d1f5fd Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:08:56 -0400 Subject: [PATCH 65/72] animation minor fixes Former-commit-id: 38d2da587d647b7f0c08994bc9fe41cc2d7ab675 --- voxygen/src/anim/character/run.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 5b06e64d1a..c3e3ec7404 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -31,6 +31,7 @@ impl Animation for RunAnimation { let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); +<<<<<<< HEAD next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *0.4)/ SCALE; next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.3) / SCALE; @@ -41,15 +42,34 @@ impl Animation for RunAnimation { next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.3) / SCALE; next.shorts.ori = Quaternion::rotation_z(wave * 0.1); +======= + next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ 11.0; + //next.head.ori = Quaternion::rotation_z(); + + next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / 11.0; + next.chest.ori = Quaternion::rotation_z(wave * 0.3); + + next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.8)/ 11.0; + next.belt.ori = Quaternion::rotation_z(wave * 0.3); + + next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.8) / 11.0; + next.shorts.ori = Quaternion::rotation_z(wave * 0.2); +>>>>>>> animation minor fixes next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / SCALE; next.l_hand.ori = Quaternion::rotation_y(wave * -1.8); next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE; next.r_hand.ori = Quaternion::rotation_y(wave * 1.8); +<<<<<<< HEAD next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.5) / SCALE; next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.5) / SCALE; +======= + next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.9) / 11.0; + next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); + next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.9) / 11.0; +>>>>>>> animation minor fixes next.r_foot.ori = Quaternion::rotation_y(wave * 1.0); next.back.offset = Vec3::new(-6.0, 16.0, 15.0); From 9d2040d50958b5e3b2909c218a0a0c84085ff3b9 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:12:45 -0400 Subject: [PATCH 66/72] tidying up code Former-commit-id: 43981525316728a182d41ecc107f31e2eb2583f9 --- voxygen/src/anim/character/idle.rs | 4 +--- voxygen/src/anim/character/run.rs | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index b4bbe69b0f..d6d48a5550 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -27,11 +27,9 @@ impl Animation for IdleAnimation { let wave = (time as f32 * 12.0).sin(); let wavecos = (time as f32 * 12.0).cos(); let wave_slow = (time as f32 * 6.0 + PI).sin(); - let wave_slower = (time as f32 * 2.0 + PI).sin(); - let wavecos_slower = (time as f32 * 2.0 + PI).cos(); + let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let waveultra_slow = (time as f32 * 1.0 + PI).sin(); let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); - let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE; diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index c3e3ec7404..e9ee7158f6 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -27,7 +27,6 @@ impl Animation for RunAnimation { let fuzzwave = (time as f32 * 12.0).sin(); let wavecos = (time as f32 * 14.0).cos(); let wave_slow = (time as f32 * 8.0 + PI).sin(); - let waveultra_slow = (time as f32 * 0.5 + PI).sin(); let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); @@ -44,7 +43,6 @@ impl Animation for RunAnimation { next.shorts.ori = Quaternion::rotation_z(wave * 0.1); ======= next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ 11.0; - //next.head.ori = Quaternion::rotation_z(); next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / 11.0; next.chest.ori = Quaternion::rotation_z(wave * 0.3); From a7f300feee96c6aa82e8c537d07b309bad9dc3cc Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:37:09 -0400 Subject: [PATCH 67/72] rebasing Former-commit-id: 1ef4423a8f839f5c72c650dd0ba4affddc0215fa --- voxygen/src/anim/character/mod.rs | 18 ++++++++--------- voxygen/src/anim/character/run.rs | 32 +++++++------------------------ 2 files changed, 16 insertions(+), 34 deletions(-) diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 3d6e3e1dfc..4d442d416e 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -20,10 +20,10 @@ const SCALE: f32 = 11.0; pub struct CharacterSkeleton { head: Bone, chest: Bone, - belt: Bone, - shorts: Bone, - l_hand: Bone, + bl_foot: Bone, + br_foot: Bone, r_hand: Bone, + l_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -34,10 +34,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - belt: Bone::default(), - shorts: Bone::default(), - l_hand: Bone::default(), + br_foot: Bone::default(), + bl_foot: Bone::default(), r_hand: Bone::default(), + l_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -52,10 +52,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.belt.compute_base_matrix()), - FigureBoneData::new(self.shorts.compute_base_matrix()), - FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.bl_foot.compute_base_matrix()), + FigureBoneData::new(self.br_foot.compute_base_matrix()), FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.l_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index e9ee7158f6..340b72deb3 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -30,44 +30,26 @@ impl Animation for RunAnimation { let wavecos_slow = (time as f32 * 8.0 + PI).cos(); let wave_dip = (wave_slow.abs() - 0.5).abs(); -<<<<<<< HEAD - next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *0.4)/ SCALE; + next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ SCALE; - next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.3) / SCALE; - next.chest.ori = Quaternion::rotation_z(wave * 0.2); - - next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.3)/ SCALE; - next.belt.ori = Quaternion::rotation_z(wave * 0.2); - - next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.3) / SCALE; - next.shorts.ori = Quaternion::rotation_z(wave * 0.1); -======= - next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ 11.0; - - next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / 11.0; + next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / SCALE; next.chest.ori = Quaternion::rotation_z(wave * 0.3); - next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.8)/ 11.0; + next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.8) / SCALE; next.belt.ori = Quaternion::rotation_z(wave * 0.3); - next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.8) / 11.0; + next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.8) / SCALE; next.shorts.ori = Quaternion::rotation_z(wave * 0.2); ->>>>>>> animation minor fixes next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / SCALE; next.l_hand.ori = Quaternion::rotation_y(wave * -1.8); next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE; next.r_hand.ori = Quaternion::rotation_y(wave * 1.8); -<<<<<<< HEAD - next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.5) / SCALE; + + next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.9) / SCALE; next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); - next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.5) / SCALE; -======= - next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.9) / 11.0; - next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); - next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.9) / 11.0; ->>>>>>> animation minor fixes + next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.9) / SCALE; next.r_foot.ori = Quaternion::rotation_y(wave * 1.0); next.back.offset = Vec3::new(-6.0, 16.0, 15.0); From 0e71756643af219ebc6119fadadd0cc50846bada Mon Sep 17 00:00:00 2001 From: jshipsey Date: Fri, 19 Apr 2019 19:42:12 -0400 Subject: [PATCH 68/72] merge fix Former-commit-id: 38fa38de2b2985062e3260170b4f6f06d17515a1 --- voxygen/src/anim/character/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 4d442d416e..3d6e3e1dfc 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -20,10 +20,10 @@ const SCALE: f32 = 11.0; pub struct CharacterSkeleton { head: Bone, chest: Bone, - bl_foot: Bone, - br_foot: Bone, - r_hand: Bone, + belt: Bone, + shorts: Bone, l_hand: Bone, + r_hand: Bone, l_foot: Bone, r_foot: Bone, back: Bone, @@ -34,10 +34,10 @@ impl CharacterSkeleton { Self { head: Bone::default(), chest: Bone::default(), - br_foot: Bone::default(), - bl_foot: Bone::default(), - r_hand: Bone::default(), + belt: Bone::default(), + shorts: Bone::default(), l_hand: Bone::default(), + r_hand: Bone::default(), l_foot: Bone::default(), r_foot: Bone::default(), back: Bone::default(), @@ -52,10 +52,10 @@ impl Skeleton for CharacterSkeleton { [ FigureBoneData::new(self.head.compute_base_matrix()), FigureBoneData::new(chest_mat), - FigureBoneData::new(self.bl_foot.compute_base_matrix()), - FigureBoneData::new(self.br_foot.compute_base_matrix()), - FigureBoneData::new(self.r_hand.compute_base_matrix()), + FigureBoneData::new(self.belt.compute_base_matrix()), + FigureBoneData::new(self.shorts.compute_base_matrix()), FigureBoneData::new(self.l_hand.compute_base_matrix()), + FigureBoneData::new(self.r_hand.compute_base_matrix()), FigureBoneData::new(self.l_foot.compute_base_matrix()), FigureBoneData::new(self.r_foot.compute_base_matrix()), FigureBoneData::new(chest_mat * self.back.compute_base_matrix()), From 7778546b69ca95dc1a0c142d8e5296fe31ef512a Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:47:15 -0400 Subject: [PATCH 69/72] more rebasing Former-commit-id: f8671bbddd1c8aae132f1888bb76262aa5f81bcf --- voxygen/src/anim/character/idle.rs | 1 + voxygen/src/anim/character/run.rs | 1 - voxygen/src/scene/figure.rs | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index d6d48a5550..d04aeb6855 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -30,6 +30,7 @@ impl Animation for IdleAnimation { let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let waveultra_slow = (time as f32 * 1.0 + PI).sin(); let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); + let wave_dip = (wave_slow.abs() - 0.5).abs(); next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE; diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 340b72deb3..a0bd50d7b2 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -46,7 +46,6 @@ impl Animation for RunAnimation { next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE; next.r_hand.ori = Quaternion::rotation_y(wave * 1.8); - next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.9) / SCALE; next.l_foot.ori = Quaternion::rotation_y(wave * -1.0); next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.9) / SCALE; diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 3898ed4b4e..86a51be0eb 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -53,6 +53,7 @@ impl Figures { } let bone_meshes = [ + Some(load_segment("head.vox").generate_mesh(Vec3::new(-3.5, -7.0, -6.0))), Some(load_segment("chest.vox").generate_mesh(Vec3::new(-3.0, -6.0, 0.0))), Some(load_segment("belt.vox").generate_mesh(Vec3::new(-3.0, -5.0, 0.0))), From c492e72a99e825e6690474757214ee59bfed5a98 Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sat, 20 Apr 2019 18:12:45 -0400 Subject: [PATCH 70/72] tidying up code Former-commit-id: 0f77e7baf0c628969bc31e4d5fc4b42e18ab57d2 --- voxygen/src/anim/character/idle.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index d04aeb6855..d6d48a5550 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -30,7 +30,6 @@ impl Animation for IdleAnimation { let wavecos_slow = (time as f32 * 6.0 + PI).cos(); let waveultra_slow = (time as f32 * 1.0 + PI).sin(); let waveultracos_slow = (time as f32 * 1.0 + PI).cos(); - let wave_dip = (wave_slow.abs() - 0.5).abs(); next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE; From 91057edfac8ced520408e8aac4b5e7cf2579e306 Mon Sep 17 00:00:00 2001 From: timokoesters Date: Mon, 22 Apr 2019 10:20:25 +0200 Subject: [PATCH 71/72] Remove .internal and .internal_mut Former-commit-id: 261b656ec400f6780f2be2f5a4c331cc3b2a64a2 --- common/src/state.rs | 44 ++++++++++++++++++------------------- server/src/cmd.rs | 2 +- server/src/lib.rs | 38 +++++++++++++++----------------- voxygen/src/scene/figure.rs | 2 +- voxygen/src/scene/mod.rs | 1 - 5 files changed, 41 insertions(+), 46 deletions(-) diff --git a/common/src/state.rs b/common/src/state.rs index 6a12cc6d7d..e8b4601d94 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -97,41 +97,41 @@ impl State { ecs.register_synced::(); // Register unsynched (or synced by other means) components - ecs.internal_mut().register::(); - ecs.internal_mut().register::(); - ecs.internal_mut().register::(); - ecs.internal_mut().register::(); - ecs.internal_mut().register::(); - ecs.internal_mut().register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); + ecs.register::(); // Register resources used by the ECS - ecs.internal_mut().add_resource(TimeOfDay(0.0)); - ecs.internal_mut().add_resource(Time(0.0)); - ecs.internal_mut().add_resource(DeltaTime(0.0)); - ecs.internal_mut().add_resource(TerrainMap::new()); + ecs.add_resource(TimeOfDay(0.0)); + ecs.add_resource(Time(0.0)); + ecs.add_resource(DeltaTime(0.0)); + ecs.add_resource(TerrainMap::new()); } /// Register a component with the state's ECS pub fn with_component(mut self) -> Self where ::Storage: Default { - self.ecs.internal_mut().register::(); + self.ecs.register::(); self } /// Write a component attributed to a particular entity pub fn write_component(&mut self, entity: EcsEntity, comp: C) { - let _ = self.ecs.internal_mut().write_storage().insert(entity, comp); + let _ = self.ecs.write_storage().insert(entity, comp); } /// Read a component attributed to a particular entity pub fn read_component_cloned(&self, entity: EcsEntity) -> Option { - self.ecs.internal().read_storage().get(entity).cloned() + self.ecs.read_storage().get(entity).cloned() } /// Get a read-only reference to the storage of a particular component type pub fn read_storage(&self) -> EcsStorage>> { - self.ecs.internal().read_storage::() + self.ecs.read_storage::() } /// Get a reference to the internal ECS world @@ -154,27 +154,25 @@ impl State { /// /// Note that this should not be used for physics, animations or other such localised timings. pub fn get_time_of_day(&self) -> f64 { - self.ecs.internal().read_resource::().0 + self.ecs.read_resource::().0 } /// Get the current in-game time. /// /// Note that this does not correspond to the time of day. pub fn get_time(&self) -> f64 { - self.ecs.internal().read_resource::