From ad7144c800d9c5c4490e5bd83416215c4e139f12 Mon Sep 17 00:00:00 2001 From: Lewin Kelly Date: Thu, 12 Oct 2023 06:30:06 +0100 Subject: [PATCH] Improve plugin notification animations --- Sync/Plugin/Plugin.lua | 146 ++++++++++++++++++++++++++------------ Sync/Plugin/icon.png | Bin 2534 -> 2438 bytes Sync/Plugin/icon2.png | Bin 2786 -> 0 bytes Sync/Plugin/innerIcon.png | Bin 0 -> 811 bytes Sync/Plugin/outerIcon.png | Bin 0 -> 2271 bytes 5 files changed, 100 insertions(+), 46 deletions(-) delete mode 100644 Sync/Plugin/icon2.png create mode 100644 Sync/Plugin/innerIcon.png create mode 100644 Sync/Plugin/outerIcon.png diff --git a/Sync/Plugin/Plugin.lua b/Sync/Plugin/Plugin.lua index 58969b2..4d8a1e9 100644 --- a/Sync/Plugin/Plugin.lua +++ b/Sync/Plugin/Plugin.lua @@ -17,11 +17,14 @@ local function initiate() end local toolbar = plugin:CreateToolbar "Mercury Sync" -local button = toolbar:CreateButton( - "", -- The text next to the icon. Leave this blank if the icon is sufficient. - "Sync!", -- hover text - "icon.png" -- The icon file's name. Make sure you change it to your own icon file's name! -) + +local buttons = { + toolbar:CreateButton( + "", -- The text next to the icon. Leave this blank if the icon is sufficient. + "Sync!", -- hover text + "icon.png" -- The icon file's name. Make sure you change it to your own icon file's name! + ), +} local Fusion = LoadLibrary "RbxFusion" @@ -29,6 +32,9 @@ local New = Fusion.New local Children = Fusion.Children local Value = Fusion.Value local Spring = Fusion.Spring +-- local Tween = Fusion.Tween +-- local TweenInfo = Fusion.TweenInfo +local Observer = Fusion.Observer local peek = Fusion.peek local g @@ -69,28 +75,34 @@ local function gui() return g end -local function notifyCount() - local count = 0 - for _, _ in pairs(notifications) do - count = count + 1 - end - return count -end - local idCount = 0 +local nCount = 0 local function notify(text) - local startCount = notifyCount() - local position = Value(UDim2.new(0, -WIDTH, 0, 60 * (startCount + 1) - 50)) - local transparency = Value(0) - + nCount = nCount + 1 idCount = idCount + 1 local id = idCount + local position = Value(UDim2.new(0, -WIDTH, 0, 60 * nCount - 50)) + local transparency = Value(0) + local textValue = Value(text) + local textChanged = Observer(textValue) + local arrowRotation = Value(0) + local done = Value(false) + local background = Value(Color3.new()) + local backgroundSpring = Spring(background, 4) + local start = tick() + + local disconn = textChanged:onChange(function() + if tick() - start > 0.5 then -- don't change color if it's just appearing + backgroundSpring:setPosition(Color3.new(0.4, 0.4, 0.4)) + end + end) + local t = New "Frame" { Name = "Notification", Parent = gui().Notifications, - BackgroundColor3 = Color3.new(), + BackgroundColor3 = backgroundSpring, BackgroundTransparency = Spring(transparency, 15), BorderSizePixel = 0, Position = Spring(position, 15), @@ -98,16 +110,25 @@ local function notify(text) [Children] = { New "ImageLabel" { - Image = "rbxasset://../../../Plugins/TestPlugin/icon2.png", + Name = "InnerIcon", + Image = "rbxasset://../../../Plugins/TestPlugin/innerIcon.png", BackgroundTransparency = 1, Position = UDim2.new(0, 5, 0, 5), Size = UDim2.new(0, 40, 0, 40), }, + New "ImageLabel" { + Name = "OuterIcon", + Image = "rbxasset://../../../Plugins/TestPlugin/outerIcon.png", + BackgroundTransparency = 1, + Position = UDim2.new(0, 5, 0, 5), + Rotation = Spring(arrowRotation), + Size = UDim2.new(0, 40, 0, 40), + }, New "TextLabel" { Position = UDim2.new(0, 50, 0, 0), Size = UDim2.new(1, -60, 1, 0), BackgroundTransparency = 1, - Text = text, + Text = textValue, TextWrapped = true, TextColor3 = Color3.new(1, 1, 1), Font = Enum.Font.SourceSans, @@ -117,48 +138,81 @@ local function notify(text) }, }, } - local tbl = { - obj = t, - pos = position, - } - notifications[id] = tbl - position:set(peek(position) + UDim2.new(0, WIDTH, 0, 0)) - transparency:set(0.5) - wait(3) + Spawn(function() + local tbl = { + obj = t, + pos = position, + } - position:set(UDim2.new(0, 0, 0, -60)) - transparency:set(1) + notifications[id] = tbl - notifications[id] = nil + position:set(peek(position) + UDim2.new(0, WIDTH, 0, 0)) + transparency:set(0.5) - for _, v in pairs(notifications) do - if peek(v.pos).Y.Offset > peek(position).Y.Offset then - v.pos:set(peek(v.pos) - UDim2.new(0, 0, 0, 60)) + repeat + wait(1) + until peek(done) + + wait(3) + + position:set(UDim2.new(0, 0, 0, -60)) + transparency:set(1) + + notifications[id] = nil + nCount = nCount - 1 + + for _, v in pairs(notifications) do + if peek(v.pos).Y.Offset > peek(position).Y.Offset then + v.pos:set(peek(v.pos) - UDim2.new(0, 0, 0, 60)) + end end - end - wait(1) - t:Destroy() + wait(1) + disconn() + t:Destroy() + end) + + return { + text = textValue, + arrowRotation = arrowRotation, + done = done, + } end local debounce -button.Click:connect(function() + +buttons[1].Click:connect(function() if debounce then return end debounce = true initiate() - local ok, res = ypcall(function() - return HttpService:GetAsync "http://localhost:2013/" + local n = notify "Syncing..." + + Spawn(function() + while not peek(n.done) do + n.arrowRotation:set(peek(n.arrowRotation) + 180) + wait(0.9) + end end) - if ok then - notify("Synced: " .. res) - else - notify "Failed to sync! Is Mercury Sync Server running?" - end + Spawn(function() + local ok, res = ypcall(function() + return HttpService:GetAsync( + "http://localhost:2013/sync?" .. tick() * 10000 + -- nocache parameter doesn't work + ) + end) - debounce = false + if ok then + n.text:set("Synced: " .. res) + else + n.text:set "Failed to sync! Is Mercury Sync Server running?" + end + n.done:set(true) + + debounce = false + end) end) diff --git a/Sync/Plugin/icon.png b/Sync/Plugin/icon.png index 36c335f646fc7493ed8e53a2f1af4a9a1c1f1223..42cd6b27b56b68d6a1b9c713671664dc9f63eeca 100644 GIT binary patch delta 2391 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 JPDHLkV1gTio)!QA delta 2488 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 diff --git a/Sync/Plugin/innerIcon.png b/Sync/Plugin/innerIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..c67e3fff720250b6805fe339a2e381f8e2273854 GIT binary patch literal 811 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9FrogmDZn=$tnP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&di3`_?+T^vIy7~kG*^t~M*aO|V^RYt2O_k@;` z$t6u~oE*Ya{3etzn`uZ-;r+mI_rPB5^SL5xB&^Fg?*FZyl&W%IT1EW1@Ar(;fF|Pt zwzHPqG<#gL+5Exx+N`$fP28UjnymTDU!9u%ijS@CtU`^ADeBtymqK~)qCqQBtB){x}`G5XTitY z%Ox5%Z0($S?EUJ_KwgKZ%x0x4|7A9XFbiCJ8eDBO)v{jvDTB-5vQLX0wtm?@g;`*l zuu02Djg>xAsu&KHy}8wJYtDY}Hii(hq<8Bqp1+@@$dGs@ZDP*j?fTvfhgOGkOf{?i zmBMvk!da!0mi5zp7&-RNc3t{$wN7Uaqs6Tosak*6<}h-+R?cR=RQyj*l35_mq($=C zpV&=o4^|~_)(Cx>pUUg-V|(P2=e?@hf7hO2{INT7%Ephkr&}^4zC5n)ty9f#=*D!9 z`q>Oi8SdQv`KIUkA^mf6<@wF_-|By_=A_9mRsOo!{@%_h{}rw>>xgx`SIaHf`R0$D zz0Z|4167TH`k+k313_9s)u9U=cXdq4d-x@`N$?CWZ7MN%)Azb2gbeHil2`{ne- zKR7a6cg|ZB*_|Ep{m$#VlVUlv`kOS6tc{+wxI7iIKOL*u_v*^d(|LZ?^vdx|$aVAlQY zbbMunx`8Fr1Q|w;J_Z$chDpi{Cj}dxa5xmPD1e1=r7NKL4u^V%<)0*K7`?2Qfs}c= L`njxgN@xNA3lUNH literal 0 HcmV?d00001 diff --git a/Sync/Plugin/outerIcon.png b/Sync/Plugin/outerIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..3d31ad07af840863aeb1b8b4ec50102f229c1389 GIT binary patch literal 2271 zcmV<52q5=~P)w!k#B^8c+a4g&tTi%cpI+r7oVQBw%u~6>Y@{M1upc)#6r7czap3nae zDciAvsBF2krAB)0;I5@2A@goiTN&zc?QdPQ@`K7=E< z+L5!+cTvMBgE?@2^^W7uX|BN4_FGJc8*FJ6?BA~T98=TW!1M(Fl-iaL?Y*A%_IhF?(j!>4ErAbq=>wr1fcEQ*|%)xDpGcF z6x$4pt^n-~-H~hZmBai+5gE+{z8)p{n3+>8}F?W ztSAD}V*xzeAs6Hr^T9Uc{OOxl4(9x@5AnY~2g7;c47qDQ?i535;GyG+A`rC&un+Qz z#%c07NOMh2*sH#R_N8sfIOxQ|r;5f?2)@79V?_vqX?yuMhzq-i&uw`}iLl>&jPZg} zAE*T2f*W^;2P;-Gq3?pP3C{N)i~J*maKf)KJe%5{V+ZXK?K4-|370+QQHYz#%@rvg*`d)O6DMJh{HC&_+j2`LHH17G9A9zfpG7ZCV!R;!iG4P zq?8N7I({`K;NhD!2CF)MO}qcV{KX!D;h4S6Ez1E>N_ z2P0V{NEKj0r~*ujhCE5KZJd%15(O}%(kPnin{f`ttl2Lj} zN-k97&+6AZxE(+xXe*Ey$ft)JK7QQ-EEWrP1~uf5I)u{mf&97OB$0N5K|0&FOisw3 z)#goC0ltzynjV%AxW%3f`SWGh34Q$mhLmJLwyxv$W#U?{sXr^7BA$-6@|}`DU-q5U zr$=c>Ne1Mry1qMf;zK)wvzd_eJe7ffbN$xvr{6XJaEnIYZ8^a$wB{!V@{K&7E$h2D z@I}VHaL|XNMosH4P!iJ0W? zD;b0}{aX7=1};=zLyp@1lCc83f*jq>r(_Uj_ZdSt2Xfl*Jh$r~Xb1;-Uh&vis!cB_I3OE~ogLv>f4MQbhFZ2}gscpGLLYFX{&|}s1 zF05Fgj-stBC<5)p@_0SUMQ@=Y=NaTF?)R}gVsJIEBDXNcDUEY~9NamhNJLQp2CmnB zN@-}wErP^_*FRdXfYMhnT0ygLxpiS-oA$k-@!)IzY_IuWibzZasK_}ya^vAiVNB=$ zhSJm6@_r28el!JO;1(ko%M46~D_i~^YaV9oEn}`p=}Tiv#rA&8Nw~2UK(g-89J#RN zZHi2us3w3>Gq9JHEgw_H@yFOT?7GKi8k*PURV#AM{rg4Y{KqjAppO~gY?jyLLYoau zmlgdM{P>BRslfi^hs!OWe}}kk)v>w7oagA-n?K+2U~24fal)mUEiqj7%$Try_#Ba3 zxJ7~8`GUsd9Pi+iA-3N=1irQAw4zRwG=7z=)=GbaOqrE z?XSGb=pea$aIFaY>nn2p`aZLhq_BhLzEi%IzH-`_3cy0)4j;ds#T@>?g^2&4-vJ!c te($E39fvlZS1u2o_Z(%E?68(K{{z#6oT&iNQPltd002ovPDHLkV1n^NR=)rM literal 0 HcmV?d00001