From 9bab55cba55a2f3afb0e7474adb3d7d86bc4e43d Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:49:37 +0530 Subject: [PATCH] more MP ui --- data/ui/mp/lb_chkbx_d.png | Bin 0 -> 1393 bytes data/ui/mp/lb_chkbx_di_h.png | Bin 0 -> 1095 bytes data/ui/mp/lb_chkbx_di_i.png | Bin 0 -> 1095 bytes data/ui/mp/lb_chkbx_di_n.png | Bin 0 -> 1095 bytes data/ui/mp/lb_chkbx_h.png | Bin 0 -> 751 bytes data/ui/mp/lb_chkbx_i.png | Bin 0 -> 674 bytes data/ui/mp/lb_chkbx_n.png | Bin 0 -> 782 bytes data/ui/mp/play/nextcat_d.png | Bin 0 -> 4626 bytes data/ui/mp/play/nextcat_h.png | Bin 0 -> 4576 bytes data/ui/mp/play/nextcat_i.png | Bin 0 -> 4180 bytes data/ui/mp/play/nextcat_n.png | Bin 0 -> 4621 bytes data/ui/mp/play/prev_n.png | Bin 3823 -> 2720 bytes data/ui/mp/play/prevcat_d.png | Bin 0 -> 4635 bytes data/ui/mp/play/prevcat_h.png | Bin 0 -> 4592 bytes data/ui/mp/play/prevcat_i.png | Bin 0 -> 4133 bytes data/ui/mp/play/prevcat_n.png | Bin 0 -> 4616 bytes data/ui/mp/settings/inputbg.png | Bin 0 -> 1838 bytes src/MarbleGame.hx | 61 +++++--- src/gui/JoinServerGui.hx | 3 + src/gui/MPExitGameDlg.hx | 127 +++++++++++++++ src/gui/MPMarbleSelectGui.hx | 214 ++++++++++++++++++++++++++ src/gui/MPPlayMissionGui.hx | 37 ++++- src/gui/MPSearchGui.hx | 264 ++++++++++++++++++++++++++++++++ src/gui/MPServerDlg.hx | 203 ++++++++++++++++++++++++ 24 files changed, 879 insertions(+), 30 deletions(-) create mode 100644 data/ui/mp/lb_chkbx_d.png create mode 100644 data/ui/mp/lb_chkbx_di_h.png create mode 100644 data/ui/mp/lb_chkbx_di_i.png create mode 100644 data/ui/mp/lb_chkbx_di_n.png create mode 100644 data/ui/mp/lb_chkbx_h.png create mode 100644 data/ui/mp/lb_chkbx_i.png create mode 100644 data/ui/mp/lb_chkbx_n.png create mode 100644 data/ui/mp/play/nextcat_d.png create mode 100644 data/ui/mp/play/nextcat_h.png create mode 100644 data/ui/mp/play/nextcat_i.png create mode 100644 data/ui/mp/play/nextcat_n.png create mode 100644 data/ui/mp/play/prevcat_d.png create mode 100644 data/ui/mp/play/prevcat_h.png create mode 100644 data/ui/mp/play/prevcat_i.png create mode 100644 data/ui/mp/play/prevcat_n.png create mode 100644 data/ui/mp/settings/inputbg.png create mode 100644 src/gui/MPExitGameDlg.hx create mode 100644 src/gui/MPMarbleSelectGui.hx create mode 100644 src/gui/MPSearchGui.hx create mode 100644 src/gui/MPServerDlg.hx diff --git a/data/ui/mp/lb_chkbx_d.png b/data/ui/mp/lb_chkbx_d.png new file mode 100644 index 0000000000000000000000000000000000000000..51ed12d3752d7d584a530e94ffe233b1cfd3f049 GIT binary patch literal 1393 zcmV-%1&;cOP)003>600482008&k004u*003^p0082J001#$000aLoeTkpf`~#O!KZ*E;4Wy$n=Da#+3Ze&3A;0soy+#6 zs(k3$+1c!FlF>O(Om|OJednAybxxIxq6mO`y*>%lTnhk?@ktDHfJZDk z03n`hW^4C%R2uhbH6L>7^hXnJS*0`9O6TI#HGoc<#Hd0M-}e!SXF@G@mjXg~q)DHR zc9VN64*=$#7~Ye6O)7-IT8$72-}jw!c7v@2V|4y&Eyfsx5O}^vn#OcHE$%fQ&}?`1 zRDMsmRD~R142jNmS+xb$T9aleI@4rXhPC-hNu|h=9xJQ&X|_5@sh%IM)OKf`YLd9W z<9}mq4o*_yBq5Fy(llc^XfR*9!Gcy9DtGv~ev6~cSu$<0!pD~qDJ7ogjR2R0A@^FOG30y)HX5x{;y9z%i@6#6#*O+s z2nf<5#tJ;)BRq-ktI^=T%s(4r@r(hH0l5MOL7HijG^4+n5ZM)O9G@S=WLNg^Jc%zA zQYxex5iV7LF$Rl9ThInFZ82JtX-ynwbbB$axWl){f6RBSlYgq~s9u0J7NrVEIT~E} zQi0Z_+Mu;1Ni*Ukp`Z4#iDfg6>2!NsIrtM)wg*;PMb04xeDT*syiLKM-ruYoelQqw^wD8HZk}a&W{NPJKx<1Oc$_Dyk>I|< z7!V?1!T!#r@S8!;tJQ0~^XP4^p1eL-=VNO}`DEimreMyZc=qu$7kcNZ9jGxiRij#|QYsaBywOD!f_=eHffuk= zPz;K^ReF;XYbW^1UScu43leUf{59{m37>U8Wp?%ewOWlZtWqqMP*PGT6!*<+&)DY* z5EyHzq#4sm%EjgdF0WtVm+70iyA6D~@i{L{AE7o?V>*8%H=YJLSYbKzAy3q101Q;t`-za zRH`9o<8vI-$2e7fmr|)nxm>1PE)xX7j>z_9VUVmwf_t7nsL8EXo5jUN(ljN@GPKsb zYEH21Eu&Oka;3~&J)BI8F=UzEQKX&=zNLMm(O`alo|ToAL7q3p3@Pd1dETJ^aAcQC zB_<~)3Bzz-1@`sJ>gp;B3kx(FjU9V+*t%iZlUu6a-!8*p814&?f$q?8YHew0iQBht zv%0#v=fwK~pOh^HI-L&W=eK^oPe=ey0zF{OeOQm8$OGP(o0~hr_@n^5NPcVS11&&E z_n?6|ilPeJx0Z2=a0*P4--b4TOuBRQ)_MI9F!8il_#a})i*M$Zxhvg^%UO7?!?kzXmxcpthd$FVw6t)|9$ zy{@i-9P<%w5JS0Xn*EcjG-U+{pVh=E5X*g#r_*V=yu75jxjD+^a+J+x6|vLS^(40^ zl!O-sasVo?uCD0#_?RM*NGtpx2Cxl%lS_Do%=#N6RF}(TIz2t5^YinzxgZ4kCYL=D zGE5dy7(xsn+z$^Abar;u3N505B!v?|-{dGWYqCjl;TlLqaj{sW-QC@`#gW-EUmWO% z+<>)T^g&K>Y zrls80*4AirbW{-|+?a#;Aa?3(Vjd@QsK-K3f`wOBRw$83v^AUc^>rE>8>476+9LP+ z{fb!1Oz>9aO?!rd2#JG)f;0R3`!qW{OOun66b^?KX&?}2OE8R1FQuMgw*!hmytueX zu~>{|W@gkikOEL^&1_NLH@Va<7D72)TwJJHM}t8LjgOC0DwR?MAOs0UYt2hTvcD&K zl8g7q?1O^?y1l)9)#t7KTb{RW6{3Qd47S9{0mrx?vr)@%z*?(TbyhNaNue=`NyqC% zj+b@Ga-7N}lSw){I#LdFTG)y3)nQ#bfST9mx3WGV<238R?DzVHI$QIp64JggVlJLu z<%C?+4xlgJnED3}VihKSXZdPz(+urEM1Kw8++H`C(5u58&=ClC%Z2~2rdD6q+gvjB zA4BhjN6yqP6W4WaA>=<9DSW|*!kYHxRzKj^VRHME=}~_+0rXdZ0RSrBB(W|a93}t& N002ovPDHLkV1jAM|D*r_ literal 0 HcmV?d00001 diff --git a/data/ui/mp/lb_chkbx_di_i.png b/data/ui/mp/lb_chkbx_di_i.png new file mode 100644 index 0000000000000000000000000000000000000000..3613cef9b252644e6fe7e831f63b6546706ed287 GIT binary patch literal 1095 zcmV-N1i1T&P)kzXmxcpthd$FVw6t)|9$ zy{@i-9P<%w5JS0Xn*EcjG-U+{pVh=E5X*g#r_*V=yu75jxjD+^a+J+x6|vLS^(40^ zl!O-sasVo?uCD0#_?RM*NGtpx2Cxl%lS_Do%=#N6RF}(TIz2t5^YinzxgZ4kCYL=D zGE5dy7(xsn+z$^Abar;u3N505B!v?|-{dGWYqCjl;TlLqaj{sW-QC@`#gW-EUmWO% z+<>)T^g&K>Y zrls80*4AirbW{-|+?a#;Aa?3(Vjd@QsK-K3f`wOBRw$83v^AUc^>rE>8>476+9LP+ z{fb!1Oz>9aO?!rd2#JG)f;0R3`!qW{OOun66b^?KX&?}2OE8R1FQuMgw*!hmytueX zu~>{|W@gkikOEL^&1_NLH@Va<7D72)TwJJHM}t8LjgOC0DwR?MAOs0UYt2hTvcD&K zl8g7q?1O^?y1l)9)#t7KTb{RW6{3Qd47S9{0mrx?vr)@%z*?(TbyhNaNue=`NyqC% zj+b@Ga-7N}lSw){I#LdFTG)y3)nQ#bfST9mx3WGV<238R?DzVHI$QIp64JggVlJLu z<%C?+4xlgJnED3}VihKSXZdPz(+urEM1Kw8++H`C(5u58&=ClC%Z2~2rdD6q+gvjB zA4BhjN6yqP6W4WaA>=<9DSW|*!kYHxRzKj^VRHME=}~_+0rXdZ0RSrBB(W|a93}t& N002ovPDHLkV1jAM|D*r_ literal 0 HcmV?d00001 diff --git a/data/ui/mp/lb_chkbx_di_n.png b/data/ui/mp/lb_chkbx_di_n.png new file mode 100644 index 0000000000000000000000000000000000000000..3613cef9b252644e6fe7e831f63b6546706ed287 GIT binary patch literal 1095 zcmV-N1i1T&P)kzXmxcpthd$FVw6t)|9$ zy{@i-9P<%w5JS0Xn*EcjG-U+{pVh=E5X*g#r_*V=yu75jxjD+^a+J+x6|vLS^(40^ zl!O-sasVo?uCD0#_?RM*NGtpx2Cxl%lS_Do%=#N6RF}(TIz2t5^YinzxgZ4kCYL=D zGE5dy7(xsn+z$^Abar;u3N505B!v?|-{dGWYqCjl;TlLqaj{sW-QC@`#gW-EUmWO% z+<>)T^g&K>Y zrls80*4AirbW{-|+?a#;Aa?3(Vjd@QsK-K3f`wOBRw$83v^AUc^>rE>8>476+9LP+ z{fb!1Oz>9aO?!rd2#JG)f;0R3`!qW{OOun66b^?KX&?}2OE8R1FQuMgw*!hmytueX zu~>{|W@gkikOEL^&1_NLH@Va<7D72)TwJJHM}t8LjgOC0DwR?MAOs0UYt2hTvcD&K zl8g7q?1O^?y1l)9)#t7KTb{RW6{3Qd47S9{0mrx?vr)@%z*?(TbyhNaNue=`NyqC% zj+b@Ga-7N}lSw){I#LdFTG)y3)nQ#bfST9mx3WGV<238R?DzVHI$QIp64JggVlJLu z<%C?+4xlgJnED3}VihKSXZdPz(+urEM1Kw8++H`C(5u58&=ClC%Z2~2rdD6q+gvjB zA4BhjN6yqP6W4WaA>=<9DSW|*!kYHxRzKj^VRHME=}~_+0rXdZ0RSrBB(W|a93}t& N002ovPDHLkV1jAM|D*r_ literal 0 HcmV?d00001 diff --git a/data/ui/mp/lb_chkbx_h.png b/data/ui/mp/lb_chkbx_h.png new file mode 100644 index 0000000000000000000000000000000000000000..ac43e81ac4694da73cea5e5d01a2ddb4df544c55 GIT binary patch literal 751 zcmV003>600482008&k004u*003^p0082J001#$000l%Q5zuyC% z$>;z9?ZpyEf!{#toGSoSUDx#c{nx-d;H|(d?M4Qi0Ykt6Q|DZ+;yCUB1K0= zYTJrj;A0VR3Y-T(1iSzq0~Me|04>9(zzL8z=jK3ZfDq8Y3|NVXvSs)ga0DDV=QQxj zIhPr6S^$ZR&et!WKPja^sk>XgIA@Zauz&FJsVu7zv$c^FuVetEt9*$KAEC8I;V&Rx zW~8$T!|%uJ9}r*p`P^JLNhw8Lmndb?T1#>og7XU&iz&k&$0XDA+GnnX8yf;pR~30# zu-*$A)z)IhaCA&EnPZII9d7OA!{w?ZUuKQrzfMj`lG%;mTby?`7s1Q9v7LVzYz8;m zlYHRTglKI&;2UXIp5OpbZs?JA?FGM0%*Zuk)@bsQauom})Ec3$17bR;Etb6K~!G*kA8SoSM229mPi)6(8OQ0)h hYWvDGmuu4$;4gbw+79Fr>jMA)002ovPDHLkV1n?QODX^W literal 0 HcmV?d00001 diff --git a/data/ui/mp/lb_chkbx_i.png b/data/ui/mp/lb_chkbx_i.png new file mode 100644 index 0000000000000000000000000000000000000000..9f8342ca65b3b6712f9531b3272f24a005e46976 GIT binary patch literal 674 zcmV;T0$u%yP)r)e$S6<O3^+^fOxT3 z&}1^f?bV0Z&uZPDKv)z-)wWtKv$eHaQ5?rKolYr=qP4$SOWtn3uQVi(=Q-)Uph+Z2 zQYi+p?ynI!0_0H9G-k6I&FAxK=r+Ypa)gO;%$ZG!znmO>Y*YOya?{z4KK54bx~@?I zda3>waw}yAIq+>|uV;)+2FvZ+lw-W=Gu>pDv$E8%%bAwlNO@f;h)vcx`q)*mo#dvQ z3{)GD*UN4~tjUeaUSHQ?7}97oYD})bh}$OJR&sn22ZMn&1C657>5%XH)a`bgeNy)& zuDo)Z{<}s3o5=C8PHJ}Q?|3|>;c#e7{4oJI8u4$bIApk47xg`n7kCix1arm1Us`mp z+9Ai1z#In%B^R*DD<=L?JGIyhM-uSmGz8zCEAi3VucHD-+vdU^QHuIphB;Ak003>600482008&k004u*003^p0082J001#$000)l~{ogJ5Iuu zQ*g1KfE%!>ka~eGhzNm-0&$W$b>rB6EHWidNlHEOlb&R2X8iw{55Eyr1wcglz(b!M zz|dYSfE4%%q^eo~h^itY&w$s!3lARAZe+k17y_SxsjBAAD}DvM0S*BLa?iG{us*v$ z4_JsuW&F!y;66|R;t8}FIWPszfkag=fYJf6XEg(soMD~|_b;%?-=k2@q2YyF7pLZd=G0aLO6kZk&(_O48NWM zyu8tT>9!3L5mZY=BCNIEoQA;p74!L&;kPrAX}Yz~R&W=^0BBW_mj%~nL8HAjpD`Sr zkxVXdF1kB-6sd8a-JLCRg!`RiaaaJM-q1Uzyv)S_RaH?G<;G9yj^L|9Wi%Rbe05s6>{ncOn{;D4<)cr)d#F^Ep3K)0)1Aup$njJzK*`G*AIb%+t$J!prYZka&t?VkGN4{WCQaO9x+K>z>% M07*qoM6N<$f+!A7c>n+a literal 0 HcmV?d00001 diff --git a/data/ui/mp/play/nextcat_d.png b/data/ui/mp/play/nextcat_d.png new file mode 100644 index 0000000000000000000000000000000000000000..05a0710a295c0c3bee584dc8f007fa9f4c33d4ef GIT binary patch literal 4626 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 IM6N<$g1|$^^8f$< literal 0 HcmV?d00001 diff --git a/data/ui/mp/play/nextcat_h.png b/data/ui/mp/play/nextcat_h.png new file mode 100644 index 0000000000000000000000000000000000000000..87883e7ab3b0e11de51845392238d7d5e3a3fce2 GIT binary patch literal 4576 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 KMNUMnLSTZs^~tmV literal 0 HcmV?d00001 diff --git a/data/ui/mp/play/nextcat_i.png b/data/ui/mp/play/nextcat_i.png new file mode 100644 index 0000000000000000000000000000000000000000..c4d121ffbb0099e271957c6170b4d61db5669ae6 GIT binary patch literal 4180 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 DMKJ_l literal 0 HcmV?d00001 diff --git a/data/ui/mp/play/prev_n.png b/data/ui/mp/play/prev_n.png index c44adb23ef54da5b3097620a5ad318658b44cf3a..3654e286be60b577dc23342feab727066b788184 100644 GIT binary patch literal 2720 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 literal 0 HcmV?d00001 diff --git a/data/ui/mp/play/prevcat_n.png b/data/ui/mp/play/prevcat_n.png new file mode 100644 index 0000000000000000000000000000000000000000..2e8583e6d79e621f7d3900a087132ddc80d738d3 GIT binary patch literal 4616 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 cA)BcG2aj>3OOyQv@Bjb+07*qoM6N<$f { - canvas.popDialog(exitGameDlg); - var w = getWorld(); - if (w.isRecording) { - MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> { - quitMission(); - })); - } else { + if (world.isMultiplayer) { + exitGameDlg = new MPExitGameDlg(() -> { + canvas.popDialog(exitGameDlg); + paused = !paused; + var w = getWorld(); + w.setCursorLock(true); + }, () -> { + canvas.popDialog(exitGameDlg); quitMission(Net.isClient); if (Net.isMP && Net.isClient) { Net.disconnect(); } - } - }, (sender) -> { - canvas.popDialog(exitGameDlg); - paused = !paused; - var w = getWorld(); - w.setCursorLock(true); - }, (sender) -> { - canvas.popDialog(exitGameDlg); - var w = getWorld(); - w.restart(w.marble, true); - // world.setCursorLock(true); - paused = !paused; - }); + }); + } else { + exitGameDlg = new ExitGameDlg((sender) -> { + canvas.popDialog(exitGameDlg); + var w = getWorld(); + if (w.isRecording) { + MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> { + quitMission(); + })); + } else { + quitMission(Net.isClient); + if (Net.isMP && Net.isClient) { + Net.disconnect(); + } + } + }, (sender) -> { + canvas.popDialog(exitGameDlg); + paused = !paused; + var w = getWorld(); + w.setCursorLock(true); + }, (sender) -> { + canvas.popDialog(exitGameDlg); + var w = getWorld(); + w.restart(w.marble, true); + // world.setCursorLock(true); + paused = !paused; + }); + } canvas.pushDialog(exitGameDlg); } else { if (world._ready) { diff --git a/src/gui/JoinServerGui.hx b/src/gui/JoinServerGui.hx index 407adb0c..1b6ecb48 100644 --- a/src/gui/JoinServerGui.hx +++ b/src/gui/JoinServerGui.hx @@ -150,6 +150,9 @@ class JoinServerGui extends GuiImage { var serverSettingsBtn = new GuiButton(loadButtonImages("data/ui/mp/play/settings")); serverSettingsBtn.position = new Vector(171, 379); serverSettingsBtn.extent = new Vector(45, 45); + serverSettingsBtn.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new MPServerDlg()); + } window.addChild(serverSettingsBtn); var exitBtn = new GuiButton(loadButtonImages("data/ui/mp/join/leave")); diff --git a/src/gui/MPExitGameDlg.hx b/src/gui/MPExitGameDlg.hx new file mode 100644 index 00000000..9f6a1964 --- /dev/null +++ b/src/gui/MPExitGameDlg.hx @@ -0,0 +1,127 @@ +package gui; + +import h2d.filter.DropShadow; +import net.Net; +import src.MarbleGame; +import hxd.res.BitmapFont; +import h3d.Vector; +import src.ResourceLoader; +import src.Settings; + +class MPExitGameDlg extends GuiControl { + public function new(resumeFunc:() -> Void, exitFunc:() -> Void) { + super(); + + this.horizSizing = Width; + this.vertSizing = Height; + this.position = new Vector(); + this.extent = new Vector(640, 480); + + function loadButtonImages(path:String) { + var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile(); + var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile(); + var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile(); + var disabled = ResourceLoader.getResource('${path}_i.png', ResourceLoader.getImage, this.imageResources).toTile(); + return [normal, hover, pressed, disabled]; + } + + var dialogImg = new GuiImage(ResourceLoader.getResource("data/ui/mp/team/teamjoin.png", ResourceLoader.getImage, this.imageResources).toTile()); + dialogImg.horizSizing = Center; + dialogImg.vertSizing = Center; + dialogImg.position = new Vector(146, 115); + dialogImg.extent = new Vector(347, 250); + this.addChild(dialogImg); + + var partialRestart = new GuiButton(loadButtonImages("data/ui/mp/exit/partial")); + partialRestart.position = new Vector(133, 80); + partialRestart.extent = new Vector(94, 45); + partialRestart.vertSizing = Top; + dialogImg.addChild(partialRestart); + if (!Net.isHost) { + partialRestart.disabled = true; + } + + var disconnectBtn = new GuiButton(Net.isHost ? loadButtonImages("data/ui/mp/exit/levelselect") : loadButtonImages("data/ui/mp/exit/disconnect")); + disconnectBtn.position = new Vector(22, 132); + disconnectBtn.extent = new Vector(114, 45); + disconnectBtn.vertSizing = Top; + disconnectBtn.pressedAction = (e) -> exitFunc(); + dialogImg.addChild(disconnectBtn); + + var resumeBtn = new GuiButton(loadButtonImages("data/ui/mp/exit/resume")); + resumeBtn.position = new Vector(133, 132); + resumeBtn.extent = new Vector(94, 45); + resumeBtn.vertSizing = Top; + resumeBtn.pressedAction = (e) -> resumeFunc(); + dialogImg.addChild(resumeBtn); + + var serverSettingsBtn = new GuiButton(loadButtonImages("data/ui/mp/play/settings")); + serverSettingsBtn.position = new Vector(195, 184); + serverSettingsBtn.extent = new Vector(45, 45); + serverSettingsBtn.vertSizing = Top; + serverSettingsBtn.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new MPServerDlg()); + }; + dialogImg.addChild(serverSettingsBtn); + if (!Net.isHost) { + serverSettingsBtn.disabled = true; + } + + var kickBtn = new GuiButton(loadButtonImages("data/ui/mp/play/kick")); + kickBtn.position = new Vector(108, 184); + kickBtn.extent = new Vector(45, 45); + kickBtn.vertSizing = Top; + dialogImg.addChild(kickBtn); + if (!Net.isHost) { + kickBtn.disabled = true; + } + + var quickspawnBtn = new GuiButton(loadButtonImages("data/ui/mp/exit/respawn")); + quickspawnBtn.position = new Vector(224, 132); + quickspawnBtn.extent = new Vector(104, 45); + quickspawnBtn.vertSizing = Top; + dialogImg.addChild(quickspawnBtn); + + var completeRestart = new GuiButton(loadButtonImages("data/ui/mp/exit/complete")); + completeRestart.position = new Vector(224, 80); + completeRestart.extent = new Vector(104, 45); + completeRestart.vertSizing = Top; + dialogImg.addChild(completeRestart); + if (!Net.isHost) { + completeRestart.disabled = true; + } + + var markerFelt32fontdata = ResourceLoader.getFileEntry("data/font/MarkerFelt.fnt"); + var markerFelt32b = new BitmapFont(markerFelt32fontdata.entry); + @:privateAccess markerFelt32b.loader = ResourceLoader.loader; + var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); + var markerFelt38 = markerFelt32b.toSdfFont(cast 31 * Settings.uiScale, MultiChannel); + + var exitTitle = new GuiText(markerFelt38); + exitTitle.position = new Vector(8, 28); + exitTitle.extent = new Vector(331, 30); + exitTitle.justify = Center; + exitTitle.text.text = "Ingame Options"; + exitTitle.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + dialogImg.addChild(exitTitle); + + var restartTitle = new GuiText(markerFelt32); + restartTitle.position = new Vector(20, 88); + restartTitle.extent = new Vector(114, 14); + restartTitle.justify = Center; + restartTitle.text.text = "Restart:"; + restartTitle.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + dialogImg.addChild(restartTitle); + + var jukeboxButton = new GuiButton(loadButtonImages("data/ui/jukebox/jb_pausemenu")); + jukeboxButton.vertSizing = Top; + jukeboxButton.horizSizing = Left; + jukeboxButton.position = new Vector(439, 403); + jukeboxButton.extent = new Vector(187, 65); + jukeboxButton.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new JukeboxDlg()); + } + + this.addChild(jukeboxButton); + } +} diff --git a/src/gui/MPMarbleSelectGui.hx b/src/gui/MPMarbleSelectGui.hx new file mode 100644 index 00000000..11bdd661 --- /dev/null +++ b/src/gui/MPMarbleSelectGui.hx @@ -0,0 +1,214 @@ +package gui; + +import h2d.filter.DropShadow; +import hxd.res.BitmapFont; +import h3d.prim.Polygon; +import h3d.scene.Mesh; +import h3d.shader.AlphaChannel; +import src.MarbleGame; +import h3d.Vector; +import src.ResourceLoader; +import src.DtsObject; +import src.Settings; +import src.ResourceLoaderWorker; + +class MPMarbleSelectGui extends GuiImage { + public function new() { + var img = ResourceLoader.getImage("data/ui/mp/team/teamcreate.png"); + super(img.resource.toTile()); + this.horizSizing = Center; + this.vertSizing = Center; + this.position = new Vector(73, -59); + this.extent = new Vector(493, 361); + + var categoryNames = ["Official Marbles", "MBUltra"]; + + var curSelection:Int = Settings.optionsSettings.marbleIndex; + var curCategorySelection:Int = Settings.optionsSettings.marbleCategoryIndex; + + function loadButtonImages(path:String) { + var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile(); + var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile(); + var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile(); + var disabled = ResourceLoader.getResource('${path}_i.png', ResourceLoader.getImage, this.imageResources).toTile(); + return [normal, hover, pressed, disabled]; + } + + var markerFelt32fontdata = ResourceLoader.getFileEntry("data/font/MarkerFelt.fnt"); + var markerFelt32b = new BitmapFont(markerFelt32fontdata.entry); + @:privateAccess markerFelt32b.loader = ResourceLoader.loader; + var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); + var markerFelt24 = markerFelt32b.toSdfFont(cast 18 * Settings.uiScale, MultiChannel); + var markerFelt28 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); + + var selectBtn = new GuiButton(loadButtonImages("data/ui/mp/play/choose")); + selectBtn.horizSizing = Center; + selectBtn.vertSizing = Top; + selectBtn.position = new Vector(199, 270); + selectBtn.extent = new Vector(95, 45); + selectBtn.pressedAction = (e) -> { + Settings.optionsSettings.marbleIndex = curSelection; + Settings.optionsSettings.marbleCategoryIndex = curCategorySelection; + Settings.optionsSettings.marbleSkin = MarbleSelectGui.marbleData[curCategorySelection][curSelection].skin; + Settings.optionsSettings.marbleModel = MarbleSelectGui.marbleData[curCategorySelection][curSelection].dts; + Settings.optionsSettings.marbleShader = MarbleSelectGui.marbleData[curCategorySelection][curSelection].shader; + Settings.save(); + MarbleGame.canvas.popDialog(this); + } + this.addChild(selectBtn); + + var marbleShow = buildObjectShow(MarbleSelectGui.marbleData[curCategorySelection][curSelection].dts, new Vector(171, 97), new Vector(150, 150), 2.6, + 0, [ + "base.marble" => MarbleSelectGui.marbleData[curCategorySelection][curSelection].skin + ".marble" + ]); + marbleShow.horizSizing = Center; + marbleShow.vertSizing = Bottom; + marbleShow.visible = true; + this.addChild(marbleShow); + + var titleText = new GuiMLText(markerFelt28, null); + titleText.text.textColor = 0xFFFFFF; + titleText.text.filter = new DropShadow(1.414, 0.785, 0, 1, 0x0000007F, 0.4, 1, true); + titleText.horizSizing = Center; + titleText.vertSizing = Bottom; + titleText.position = new Vector(140, 67); + titleText.extent = new Vector(213, 27); + titleText.text.text = '

${categoryNames[curCategorySelection]}

'; + this.addChild(titleText); + + var marbleText = new GuiMLText(markerFelt24, null); + marbleText.text.textColor = 0xFFFFFF; + marbleText.text.filter = new DropShadow(1.414, 0.785, 0, 1, 0x0000007F, 0.4, 1, true); + marbleText.horizSizing = Center; + marbleText.vertSizing = Bottom; + marbleText.position = new Vector(86, 243); + marbleText.extent = new Vector(320, 22); + marbleText.text.text = '

${MarbleSelectGui.marbleData[curCategorySelection][curSelection].name}

'; + this.addChild(marbleText); + + var changeMarbleText = new GuiImage(ResourceLoader.getResource("data/ui/play/change_marble_text.png", ResourceLoader.getImage, this.imageResources) + .toTile()); + changeMarbleText.horizSizing = Center; + changeMarbleText.position = new Vector(96, 26); + changeMarbleText.extent = new Vector(300, 39); + this.addChild(changeMarbleText); + + function setMarbleSelection(idx:Int, categoryIdx:Int) { + if (categoryIdx < 0) + categoryIdx = MarbleSelectGui.marbleData.length + categoryIdx; + if (categoryIdx >= MarbleSelectGui.marbleData.length) + categoryIdx -= MarbleSelectGui.marbleData.length; + + if (idx < 0) + idx = MarbleSelectGui.marbleData[categoryIdx].length + idx; + if (idx >= MarbleSelectGui.marbleData[categoryIdx].length) + idx -= MarbleSelectGui.marbleData[categoryIdx].length; + curSelection = idx; + curCategorySelection = categoryIdx; + var marble = MarbleSelectGui.marbleData[categoryIdx][idx]; + + titleText.text.text = '

${categoryNames[curCategorySelection]}

'; + marbleText.text.text = '

${marble.name}

'; + + var dtsObj = new DtsObject(); + dtsObj.dtsPath = marble.dts; + dtsObj.ambientRotate = true; + dtsObj.ambientSpinFactor /= -2; + dtsObj.showSequences = false; + dtsObj.useInstancing = false; + dtsObj.matNameOverride.set("base.marble", marble.skin + ".marble"); + + ResourceLoader.load(dtsObj.dtsPath).entry.load(() -> { + var dtsFile = ResourceLoader.loadDts(dtsObj.dtsPath); + var directoryPath = haxe.io.Path.directory(dtsObj.dtsPath); + var texToLoad = []; + for (i in 0...dtsFile.resource.matNames.length) { + var matName = dtsObj.matNameOverride.exists(dtsFile.resource.matNames[i]) ? dtsObj.matNameOverride.get(dtsFile.resource.matNames[i]) : dtsFile.resource.matNames[i]; + var fullNames = ResourceLoader.getFullNamesOf(directoryPath + '/' + matName).filter(x -> haxe.io.Path.extension(x) != "dts"); + var fullName = fullNames.length > 0 ? fullNames[0] : null; + if (fullName != null) { + texToLoad.push(fullName); + } + } + + var worker = new ResourceLoaderWorker(() -> { + dtsObj.init(null, () -> {}); // The lambda is not gonna run async anyway + for (mat in dtsObj.materials) { + mat.mainPass.enableLights = false; + mat.mainPass.culling = None; + if (mat.blendMode != Alpha && mat.blendMode != Add) + mat.mainPass.addShader(new AlphaChannel()); + } + marbleShow.changeObject(dtsObj); + }); + + for (texPath in texToLoad) { + worker.loadFile(texPath); + } + worker.run(); + }); + } + + var nextBtn = new GuiButton(loadButtonImages("data/ui/mp/play/next")); + nextBtn.position = new Vector(296, 270); + nextBtn.extent = new Vector(75, 45); + nextBtn.pressedAction = (e) -> { + setMarbleSelection(curSelection + 1, curCategorySelection); + } + this.addChild(nextBtn); + + var prevBtn = new GuiButton(loadButtonImages("data/ui/mp/play/prev")); + prevBtn.position = new Vector(123, 270); + prevBtn.extent = new Vector(75, 45); + prevBtn.pressedAction = (e) -> { + setMarbleSelection(curSelection - 1, curCategorySelection); + } + + var nextCategoryBtn = new GuiButton(loadButtonImages("data/ui/mp/play/nextcat")); + nextCategoryBtn.position = new Vector(371, 270); + nextCategoryBtn.extent = new Vector(85, 45); + nextCategoryBtn.pressedAction = (e) -> { + setMarbleSelection(0, curCategorySelection + 1); + } + this.addChild(nextCategoryBtn); + + var prevCategoryBtn = new GuiButton(loadButtonImages("data/ui/mp/play/prevcat")); + prevCategoryBtn.position = new Vector(37, 270); + prevCategoryBtn.extent = new Vector(85, 45); + prevCategoryBtn.pressedAction = (e) -> { + setMarbleSelection(0, curCategorySelection - 1); + } + this.addChild(prevCategoryBtn); + + setMarbleSelection(curSelection, curCategorySelection); + this.addChild(prevBtn); + } + + function buildObjectShow(dtsPath:String, position:Vector, extent:Vector, dist:Float = 5, pitch:Float = 0, matnameOverride:Map = null) { + var oShow = new GuiObjectShow(); + var dtsObj = new DtsObject(); + dtsObj.dtsPath = dtsPath; + dtsObj.ambientRotate = true; + dtsObj.ambientSpinFactor /= -2; + dtsObj.showSequences = false; + dtsObj.useInstancing = false; + if (matnameOverride != null) { + for (key => value in matnameOverride) { + dtsObj.matNameOverride.set(key, value); + } + } + dtsObj.init(null, () -> {}); // The lambda is not gonna run async anyway + for (mat in dtsObj.materials) { + mat.mainPass.enableLights = false; + mat.mainPass.culling = None; + if (mat.blendMode != Alpha && mat.blendMode != Add) + mat.mainPass.addShader(new AlphaChannel()); + } + oShow.sceneObject = dtsObj; + oShow.position = position; + oShow.extent = extent; + oShow.renderDistance = dist; + oShow.renderPitch = pitch; + return oShow; + } +} diff --git a/src/gui/MPPlayMissionGui.hx b/src/gui/MPPlayMissionGui.hx index be992e0a..e28fd217 100644 --- a/src/gui/MPPlayMissionGui.hx +++ b/src/gui/MPPlayMissionGui.hx @@ -155,6 +155,9 @@ class MPPlayMissionGui extends GuiImage { var searchBtn = new GuiButton(loadButtonImages("data/ui/mp/play/search")); searchBtn.position = new Vector(255, 514); searchBtn.extent = new Vector(44, 44); + searchBtn.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new MPSearchGui(false)); + } window.addChild(searchBtn); var kickBtn = new GuiButton(loadButtonImages("data/ui/mp/play/kick")); @@ -165,11 +168,17 @@ class MPPlayMissionGui extends GuiImage { var serverSettingsBtn = new GuiButton(loadButtonImages("data/ui/mp/play/settings")); serverSettingsBtn.position = new Vector(157, 514); serverSettingsBtn.extent = new Vector(44, 44); + serverSettingsBtn.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new MPServerDlg()); + } window.addChild(serverSettingsBtn); var marbleSelectBtn = new GuiButton(loadButtonImages("data/ui/mp/play/marble")); marbleSelectBtn.position = new Vector(206, 514); marbleSelectBtn.extent = new Vector(44, 44); + marbleSelectBtn.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(new MPMarbleSelectGui()); + } window.addChild(marbleSelectBtn); var temprev = new BitmapData(1, 1); @@ -200,9 +209,10 @@ class MPPlayMissionGui extends GuiImage { var difficultySelector = new GuiButton(loadButtonImages("data/ui/mp/play/difficulty_beginner")); difficultySelector.position = new Vector(161, 47); difficultySelector.extent = new Vector(204, 44); - difficultySelector.pressedAction = (e) -> { - MarbleGame.canvas.pushDialog(difficultyPopover); - }; + if (isHost) + difficultySelector.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(difficultyPopover); + }; window.addChild(difficultySelector); var difficultyCloseButton = new GuiButton(loadButtonImages("data/ui/mp/play/difficultymenu")); @@ -262,18 +272,21 @@ class MPPlayMissionGui extends GuiImage { prevBtn.extent = new Vector(73, 44); prevBtn.gamepadAccelerator = ["dpadLeft"]; prevBtn.pressedAction = (sender) -> { - setSelectedFunc(currentSelection - 1); + NetCommands.setLobbyLevelIndex(currentCategory, currentSelection - 1); } - window.addChild(prevBtn); + if (isHost) + window.addChild(prevBtn); var nextBtn = new GuiButton(loadButtonImagesExt("data/ui/mp/play/next")); nextBtn.position = new Vector(659, 514); nextBtn.extent = new Vector(73, 44); nextBtn.gamepadAccelerator = ["dpadRight"]; + nextBtn.pressedAction = (sender) -> { - setSelectedFunc(currentSelection + 1); + NetCommands.setLobbyLevelIndex(currentCategory, currentSelection + 1); } - window.addChild(nextBtn); + if (isHost) + window.addChild(nextBtn); var playBtn = new GuiButton(loadButtonImages("data/ui/mp/play/play")); playBtn.position = new Vector(565, 514); @@ -422,7 +435,7 @@ class MPPlayMissionGui extends GuiImage { currentCategoryStatic = currentCategory; - setSelectedFunc(currentList.length - 1); + NetCommands.setLobbyLevelIndex(category, currentList.length - 1); // if (doRender) // this.render(cast(this.parent, Canvas).scene2d); } @@ -519,6 +532,14 @@ class MPPlayMissionGui extends GuiImage { // } } + setLevelFn = (cat:String, index:Int) -> { + if (currentCategory != cat) { + currentCategory = cat; + setCategoryFunc(cat); + } + setSelectedFunc(index); + } + currentList = MissionList.missionList["multiplayer"]["beginner"]; setCategoryFunc(currentCategoryStatic, null, false); diff --git a/src/gui/MPSearchGui.hx b/src/gui/MPSearchGui.hx new file mode 100644 index 00000000..dfa3674f --- /dev/null +++ b/src/gui/MPSearchGui.hx @@ -0,0 +1,264 @@ +package gui; + +import src.Marbleland; +import h2d.Tile; +import hxd.BitmapData; +import src.MarbleGame; +import hxd.res.BitmapFont; +import h3d.Vector; +import src.ResourceLoader; +import src.Settings; +import src.MissionList; + +class MPSearchGui extends GuiImage { + public function new(isCustom:Bool) { + var img = ResourceLoader.getImage("data/ui/mp/search/window.png"); + super(img.resource.toTile()); + + this.horizSizing = Center; + this.vertSizing = Center; + this.position = new Vector(76, 8); + this.extent = new Vector(487, 463); + + var missionList = []; + if (!isCustom) { + for (diff in MissionList.missionList["multiplayer"]) { + for (mis in diff) { + missionList.push({ + mis: mis, + name: mis.title, + artist: mis.artist, + path: mis.path + }); + } + } + } else { + var customsList = MissionList.customMissions; + for (mis in customsList) { + missionList.push({ + mis: mis, + name: mis.title, + artist: mis.artist, + path: mis.path + }); + } + } + + var displayList = missionList.map(x -> x.name); + displayList.sort((x, y) -> (x > y) ? 1 : (x == y ? 0 : -1)); + missionList.sort((x, y) -> x.name > y.name ? 1 : (x.name == y.name ? 0 : -1)); + var retrieveMissionList = missionList; + + var searchMissionList:GuiTextListCtrl = null; + var scrollCtrl:GuiScrollCtrl = null; + + var currentSortBy = "title"; + + function sortBy(type:String, txt:String = "") { + if (type == "title") { + retrieveMissionList = missionList.filter(x -> StringTools.contains(x.name.toLowerCase(), txt.toLowerCase())); + displayList = retrieveMissionList.map(x -> x.name); + displayList.sort((x, y) -> (x > y) ? 1 : (x == y ? 0 : -1)); + retrieveMissionList.sort((x, y) -> x.name > y.name ? 1 : (x.name == y.name ? 0 : -1)); + } + if (type == "artist") { + retrieveMissionList = missionList.filter(x -> StringTools.contains(x.artist.toLowerCase(), txt.toLowerCase())); + retrieveMissionList.sort((x, y) -> x.artist > y.artist ? 1 : (x.artist == y.artist ? 0 : -1)); + displayList = retrieveMissionList.map(x -> '${x.name} By ${x.artist}'); + } + if (type == "file") { + retrieveMissionList = missionList.filter(x -> StringTools.contains(x.path.toLowerCase(), txt.toLowerCase())); + retrieveMissionList.sort((x, y) -> x.path > y.path ? 1 : (x.path == y.path ? 0 : -1)); + var idxofslash = 0; + displayList = retrieveMissionList.map(x -> { + var idxofslash = 0; + var slashcount = 0; + for (i in 0...x.path.length) { + if (x.path.charCodeAt(x.path.length - i - 1) == '/'.code) { + slashcount++; + if (slashcount == 2) { + idxofslash = x.path.length - i - 1; + break; + } + } + } + return '${x.path.substr(idxofslash + 1)}'; + }); + } + searchMissionList.setTexts(displayList); + scrollCtrl.setScrollMax(searchMissionList.calculateFullHeight()); + } + + function loadButtonImages(path:String) { + var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile(); + var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile(); + var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile(); + var disabledObj = ResourceLoader.getResource('${path}_i.png', ResourceLoader.getImage, this.imageResources); + var disabled = disabledObj != null ? disabledObj.toTile() : null; + return [normal, hover, pressed, disabled]; + } + + var markerFelt32fontdata = ResourceLoader.getFileEntry("data/font/MarkerFelt.fnt"); + var markerFelt32b = new BitmapFont(markerFelt32fontdata.entry); + @:privateAccess markerFelt32b.loader = ResourceLoader.loader; + var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); + var markerFelt24 = markerFelt32b.toSdfFont(cast 18 * Settings.uiScale, MultiChannel); + var markerFelt18 = markerFelt32b.toSdfFont(cast 14 * Settings.uiScale, MultiChannel); + + var domcasual32fontdata = ResourceLoader.getFileEntry("data/font/DomCasualD.fnt"); + var domcasual32b = new BitmapFont(domcasual32fontdata.entry); + @:privateAccess domcasual32b.loader = ResourceLoader.loader; + var domcasual32 = domcasual32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); + var domcasual64 = domcasual32b.toSdfFont(cast 58 * Settings.uiScale, MultiChannel); + var domcasual24 = domcasual32b.toSdfFont(cast 20 * Settings.uiScale, MultiChannel); + + var searchCancel = new GuiButton(loadButtonImages("data/ui/mp/search/cancel")); + searchCancel.vertSizing = Top; + searchCancel.position = new Vector(21, 395); + searchCancel.extent = new Vector(94, 45); + searchCancel.pressedAction = (e) -> { + MarbleGame.canvas.popDialog(this); + } + this.addChild(searchCancel); + + var selectedIdx:Int = -1; + + var searchPlay = new GuiButton(loadButtonImages("data/ui/mp/search/play")); + searchPlay.position = new Vector(370, 395); + searchPlay.extent = new Vector(94, 45); + searchPlay.disabled = true; + searchPlay.pressedAction = (e) -> { + if (selectedIdx != -1) { + var mis = retrieveMissionList[selectedIdx]; + cast(this.parent, Canvas).marbleGame.playMission(mis.mis); + } + } + this.addChild(searchPlay); + + var searchTitle = new GuiText(domcasual24); + searchTitle.position = new Vector(52, 23); + searchTitle.extent = new Vector(64, 25); + searchTitle.text.textColor = 0x696969; + searchTitle.text.text = "Title:"; + this.addChild(searchTitle); + + var searchEdit = new GuiTextInput(domcasual24); + searchEdit.text.textColor = 0; + searchEdit.text.selectionColor.setColor(0xFFFFFFFF); + searchEdit.text.selectionTile = h2d.Tile.fromColor(0x808080, 0, hxd.Math.ceil(searchEdit.text.font.lineHeight)); + searchEdit.position = new Vector(91, 23); + searchEdit.extent = new Vector(373, 29); + searchEdit.onTextChange = (txt) -> { + sortBy(currentSortBy, txt); + }; + this.addChild(searchEdit); + + scrollCtrl = new GuiScrollCtrl(ResourceLoader.getResource("data/ui/common/philscroll.png", ResourceLoader.getImage, this.imageResources).toTile()); + scrollCtrl.position = new Vector(18, 68); + scrollCtrl.extent = new Vector(447, 317); + scrollCtrl.childrenHandleScroll = true; + this.addChild(scrollCtrl); + + searchMissionList = new GuiTextListCtrl(markerFelt24, displayList, 0xFFFFFF); + searchMissionList.selectedColor = 0xFFFFFF; + searchMissionList.selectedFillColor = 0x7585E3; + searchMissionList.horizSizing = Width; + searchMissionList.position = new Vector(4, -1); + searchMissionList.extent = new Vector(432, 2880); + searchMissionList.textYOffset = -6; + searchMissionList.scrollable = true; + searchMissionList.onSelectedFunc = (sel) -> { + selectedIdx = sel; + if (retrieveMissionList.length <= selectedIdx || selectedIdx < 0) { + searchPlay.disabled = true; + } else { + searchPlay.disabled = false; + } + } + scrollCtrl.addChild(searchMissionList); + scrollCtrl.setScrollMax(searchMissionList.calculateFullHeight()); + + var optionsPopup:GuiButton = null; + + var searchOptions = new GuiButton(loadButtonImages("data/ui/mp/search/options")); + searchOptions.vertSizing = Top; + searchOptions.horizSizing = Right; + searchOptions.position = new Vector(121, 398); + searchOptions.extent = new Vector(94, 45); + searchOptions.pressedAction = (e) -> { + MarbleGame.canvas.pushDialog(optionsPopup); + } + this.addChild(searchOptions); + + var temprev = new BitmapData(1, 1); + temprev.setPixel(0, 0, 0); + var tmpprevtile = Tile.fromBitmap(temprev); + + optionsPopup = new GuiButton([tmpprevtile, tmpprevtile, tmpprevtile]); + optionsPopup.horizSizing = Width; + optionsPopup.vertSizing = Height; + optionsPopup.position = new Vector(0, 0); + optionsPopup.extent = new Vector(640, 480); + optionsPopup.pressedAction = (e) -> { + MarbleGame.canvas.popDialog(optionsPopup, false); + } + + var optionsPopupInner = new GuiControl(); + optionsPopupInner.horizSizing = Center; + optionsPopupInner.vertSizing = Center; + optionsPopupInner.position = new Vector(80, 7); + optionsPopupInner.extent = new Vector(480, 465); + optionsPopup.addChild(optionsPopupInner); + + var optionsBgR = ResourceLoader.getResource('data/ui/mp/play/moremenu.png', ResourceLoader.getImage, this.imageResources).toTile(); + + var optionsBg = new GuiImage(optionsBgR); + optionsBg.position = new Vector(0, 281); + optionsBg.extent = new Vector(348, 148); + optionsPopupInner.addChild(optionsBg); + + var searchByFile = new GuiButton(loadButtonImages("data/ui/mp/search/file")); + searchByFile.buttonType = Radio; + searchByFile.position = new Vector(229, 45); + searchByFile.extent = new Vector(67, 45); + searchByFile.pressedAction = (e) -> { + searchTitle.text.text = "File:"; + currentSortBy = "file"; + sortBy("file"); + }; + optionsBg.addChild(searchByFile); + + var searchByartist = new GuiButton(loadButtonImages("data/ui/mp/search/artist")); + searchByartist.buttonType = Radio; + searchByartist.position = new Vector(159, 45); + searchByartist.extent = new Vector(71, 45); + searchByartist.pressedAction = (e) -> { + searchTitle.text.text = "Artist:"; + currentSortBy = "artist"; + sortBy("artist"); + }; + optionsBg.addChild(searchByartist); + + var searchByTitle = new GuiButton(loadButtonImages("data/ui/mp/search/name")); + searchByTitle.buttonType = Radio; + searchByTitle.position = new Vector(92, 45); + searchByTitle.extent = new Vector(68, 45); + searchByTitle.pressed = true; + searchByTitle.pressedAction = (e) -> { + searchTitle.text.text = "Title:"; + currentSortBy = "title"; + sortBy("title"); + }; + optionsBg.addChild(searchByTitle); + + var searchRandom = new GuiButton(loadButtonImages("data/ui/mp/search/random")); + searchRandom.vertSizing = Top; + searchRandom.position = new Vector(44, 45); + searchRandom.extent = new Vector(44, 44); + searchRandom.pressedAction = (e) -> { + var mis = missionList[Math.floor(Math.random() * missionList.length)]; + cast(this.parent, Canvas).marbleGame.playMission(mis.mis); + } + optionsBg.addChild(searchRandom); + } +} diff --git a/src/gui/MPServerDlg.hx b/src/gui/MPServerDlg.hx new file mode 100644 index 00000000..0c34e10b --- /dev/null +++ b/src/gui/MPServerDlg.hx @@ -0,0 +1,203 @@ +package gui; + +import h2d.filter.DropShadow; +import src.Marbleland; +import h2d.Tile; +import hxd.BitmapData; +import src.MarbleGame; +import hxd.res.BitmapFont; +import h3d.Vector; +import src.ResourceLoader; +import src.Settings; +import src.MissionList; + +class MPServerDlg extends GuiImage { + public function new() { + var img = ResourceLoader.getImage("data/ui/mp/settings/serversettings.png"); + super(img.resource.toTile()); + + this.horizSizing = Center; + this.vertSizing = Center; + this.position = new Vector(100, 17); + this.extent = new Vector(440, 446); + + function loadButtonImages(path:String) { + var normal = ResourceLoader.getResource('${path}_n.png', ResourceLoader.getImage, this.imageResources).toTile(); + var hover = ResourceLoader.getResource('${path}_h.png', ResourceLoader.getImage, this.imageResources).toTile(); + var pressed = ResourceLoader.getResource('${path}_d.png', ResourceLoader.getImage, this.imageResources).toTile(); + return [normal, hover, pressed]; + } + + var markerFelt32fontdata = ResourceLoader.getFileEntry("data/font/MarkerFelt.fnt"); + var markerFelt32b = new BitmapFont(markerFelt32fontdata.entry); + @:privateAccess markerFelt32b.loader = ResourceLoader.loader; + var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); + var markerFelt24 = markerFelt32b.toSdfFont(cast 20 * Settings.uiScale, MultiChannel); + var markerFelt20 = markerFelt32b.toSdfFont(cast 18.5 * Settings.uiScale, MultiChannel); + var markerFelt18 = markerFelt32b.toSdfFont(cast 17 * Settings.uiScale, MultiChannel); + var markerFelt26 = markerFelt32b.toSdfFont(cast 22 * Settings.uiScale, MultiChannel); + + var cancelBtn = new GuiButton(loadButtonImages("data/ui/mp/join/cancel")); + cancelBtn.vertSizing = Top; + cancelBtn.horizSizing = Left; + cancelBtn.position = new Vector(123, 384); + cancelBtn.extent = new Vector(94, 45); + cancelBtn.pressedAction = (e) -> { + MarbleGame.canvas.popDialog(this); + } + this.addChild(cancelBtn); + + var saveBtn = new GuiButton(loadButtonImages("data/ui/mp/join/save")); + saveBtn.horizSizing = Left; + saveBtn.vertSizing = Top; + saveBtn.position = new Vector(223, 384); + saveBtn.extent = new Vector(94, 45); + this.addChild(saveBtn); + + var title = new GuiText(markerFelt32); + title.text.text = "Server Settings"; + title.text.textColor = 0xFFFFFF; + title.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + title.justify = Center; + title.position = new Vector(11, 21); + title.extent = new Vector(418, 14); + title.horizSizing = Width; + this.addChild(title); + + // var showPwdTitle = new GuiText(markerFelt18); + // showPwdTitle.text.text = "Show Password"; + // showPwdTitle.text.textColor = 0xFFFFFF; + // showPwdTitle.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + // showPwdTitle.position = new Vector(259, 94); + // showPwdTitle.extent = new Vector(129, 14); + // showPwdTitle.horizSizing = Left; + // this.addChild(showPwdTitle); + + // var showPasswords = new GuiButton(loadButtonImages("data/ui/mp/lb_chkbx")); + // showPasswords.buttonType = Toggle; + // showPasswords.horizSizing = Left; + // showPasswords.position = new Vector(389, 86); + // showPasswords.extent = new Vector(31, 31); + // this.addChild(showPasswords); + + var serverSettingsContainer = new GuiControl(); + serverSettingsContainer.vertSizing = Height; + serverSettingsContainer.horizSizing = Left; + serverSettingsContainer.position = new Vector(16, 65); + serverSettingsContainer.extent = new Vector(390, 276); + this.addChild(serverSettingsContainer); + + var serverName = new GuiText(markerFelt18); + serverName.text.text = "Server Name:"; + serverName.text.textColor = 0xFFFFFF; + serverName.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + serverName.position = new Vector(0, 0); + serverName.extent = new Vector(206, 14); + serverSettingsContainer.addChild(serverName); + + var serverNameEditBg = new GuiImage(ResourceLoader.getResource("data/ui/mp/settings/inputbg.png", ResourceLoader.getImage, this.imageResources) + .toTile()); + serverNameEditBg.position = new Vector(93, 0); + serverNameEditBg.extent = new Vector(297, 35); + serverSettingsContainer.addChild(serverNameEditBg); + + var serverNameEdit = new GuiTextInput(markerFelt18); + serverNameEdit.position = new Vector(3, 3); + serverNameEdit.extent = new Vector(291, 29); + serverNameEdit.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + serverNameEdit.horizSizing = Left; + serverNameEditBg.addChild(serverNameEdit); + + var password = new GuiText(markerFelt18); + password.text.text = "Password:"; + password.text.textColor = 0xFFFFFF; + password.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + password.position = new Vector(0, 39); + password.extent = new Vector(206, 14); + serverSettingsContainer.addChild(password); + + var passwordEditBg = new GuiImage(ResourceLoader.getResource("data/ui/mp/settings/inputbg.png", ResourceLoader.getImage, this.imageResources) + .toTile()); + passwordEditBg.position = new Vector(93, 6 + 29); + passwordEditBg.extent = new Vector(297, 35); + serverSettingsContainer.addChild(passwordEditBg); + + var passwordEdit = new GuiTextInput(markerFelt18); + passwordEdit.position = new Vector(3, 3); + passwordEdit.extent = new Vector(291, 29); + passwordEdit.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + passwordEdit.horizSizing = Left; + passwordEditBg.addChild(passwordEdit); + + var serverDescTitle = new GuiText(markerFelt18); + serverDescTitle.text.text = "Server Info:"; + serverDescTitle.text.textColor = 0xFFFFFF; + serverDescTitle.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + serverDescTitle.position = new Vector(0, 39 * 2); + serverDescTitle.extent = new Vector(206, 14); + serverSettingsContainer.addChild(serverDescTitle); + + var serverDescEditBg = new GuiImage(ResourceLoader.getResource("data/ui/mp/settings/inputbg.png", ResourceLoader.getImage, this.imageResources) + .toTile()); + serverDescEditBg.position = new Vector(0, 39 * 3); + serverDescEditBg.extent = new Vector(297 + 93, 35); + serverSettingsContainer.addChild(serverDescEditBg); + + var serverDescEdit = new GuiTextInput(markerFelt18); + serverDescEdit.position = new Vector(3, 3); + serverDescEdit.extent = new Vector(291 + 93, 29); + serverDescEdit.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + serverDescEdit.horizSizing = Left; + serverDescEditBg.addChild(serverDescEdit); + + var maxPlayers = new GuiText(markerFelt18); + maxPlayers.text.text = "Max Players: 8"; + maxPlayers.text.textColor = 0xFFFFFF; + maxPlayers.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + maxPlayers.position = new Vector(0, 39 * 4); + maxPlayers.extent = new Vector(206, 14); + serverSettingsContainer.addChild(maxPlayers); + + var playerMinus = new GuiButton(loadButtonImages("data/ui/mp/settings/minus")); + playerMinus.position = new Vector(331, 9 + 29 * 5); + playerMinus.extent = new Vector(31, 31); + playerMinus.pressedAction = (sender) -> {}; + serverSettingsContainer.addChild(playerMinus); + + var playerPlus = new GuiButton(loadButtonImages("data/ui/mp/settings/plus")); + playerPlus.position = new Vector(359, 9 + 29 * 5); + playerPlus.extent = new Vector(31, 31); + playerPlus.pressedAction = (sender) -> {}; + serverSettingsContainer.addChild(playerPlus); + + var forceSpectators = new GuiText(markerFelt18); + forceSpectators.text.text = "Force Spectators:"; + forceSpectators.text.textColor = 0xFFFFFF; + forceSpectators.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + forceSpectators.position = new Vector(0, 39 * 5); + forceSpectators.extent = new Vector(206, 14); + serverSettingsContainer.addChild(forceSpectators); + + var forceSpectatorsChk = new GuiButton(loadButtonImages("data/ui/mp/lb_chkbx")); + forceSpectatorsChk.position = new Vector(359, 9 * 2 + 29 * 6 + 2); + forceSpectatorsChk.extent = new Vector(31, 31); + forceSpectatorsChk.buttonType = Toggle; + forceSpectatorsChk.pressedAction = (sender) -> {}; + serverSettingsContainer.addChild(forceSpectatorsChk); + + var quickRespawn = new GuiText(markerFelt18); + quickRespawn.text.text = "Allow Quick Respawn:"; + quickRespawn.text.textColor = 0xFFFFFF; + quickRespawn.text.filter = new DropShadow(1.414, 0.785, 0x0000000F, 1, 0, 0.4, 1, true); + quickRespawn.position = new Vector(0, 39 * 6); + quickRespawn.extent = new Vector(206, 14); + serverSettingsContainer.addChild(quickRespawn); + + var quickRespawnChk = new GuiButton(loadButtonImages("data/ui/mp/lb_chkbx")); + quickRespawnChk.position = new Vector(359, 9 * 3 + 29 * 7 + 4); + quickRespawnChk.extent = new Vector(31, 31); + quickRespawnChk.buttonType = Toggle; + quickRespawnChk.pressedAction = (sender) -> {}; + serverSettingsContainer.addChild(quickRespawnChk); + } +}