1 | local TweenService = game:GetService("TweenService"); |
2 | local RunService = game:GetService("RunService"); |
3 | local TextService = game:GetService("TextService"); |
4 | |
5 | local Player = game:GetService("Players").LocalPlayer; |
6 | |
7 | local NotifGui = Instance.new("ScreenGui"); |
8 | NotifGui.Name = "AkaliNotif"; |
9 | NotifGui.Parent = RunService:IsStudio() and Player.PlayerGui or game:GetService("CoreGui"); |
10 | |
11 | local Container = Instance.new("Frame"); |
12 | Container.Name = "Container"; |
13 | Container.Position = UDim2.new(0, 20, 0.5, -20); |
14 | Container.Size = UDim2.new(0, 300, 0.5, 0); |
15 | Container.BackgroundTransparency = 1; |
16 | Container.Parent = NotifGui; |
17 | |
18 | local function Image(ID, Button) |
19 | local NewImage = Instance.new(string.format("Image%s", Button and "Button" or "Label")); |
20 | NewImage.Image = ID; |
21 | NewImage.BackgroundTransparency = 1; |
22 | return NewImage; |
23 | end |
24 | |
25 | local function Round2px() |
26 | local NewImage = Image("http://www.roblox.com/asset/?id=5761488251"); |
27 | NewImage.ScaleType = Enum.ScaleType.Slice; |
28 | NewImage.SliceCenter = Rect.new(2, 2, 298, 298); |
29 | NewImage.ImageColor3 = Color3.fromRGB(26, 26, 26); |
30 | return NewImage; |
31 | end |
32 | |
33 | local function Shadow2px() |
34 | local NewImage = Image("http://www.roblox.com/asset/?id=5761498316"); |
35 | NewImage.ScaleType = Enum.ScaleType.Slice; |
36 | NewImage.SliceCenter = Rect.new(17, 17, 283, 283); |
37 | NewImage.Size = UDim2.fromScale(1, 1) + UDim2.fromOffset(30, 30); |
38 | NewImage.Position = -UDim2.fromOffset(15, 15); |
39 | NewImage.ImageColor3 = Color3.fromRGB(26, 26, 26); |
40 | return NewImage; |
41 | end |
42 | |
43 | local Padding = 10; |
44 | local DescriptionPadding = 10; |
45 | local InstructionObjects = {}; |
46 | local TweenTime = 1; |
47 | local TweenStyle = Enum.EasingStyle.Sine; |
48 | local TweenDirection = Enum.EasingDirection.Out; |
49 | |
50 | local LastTick = tick(); |
51 | |
52 | local function CalculateBounds(TableOfObjects) |
53 | local TableOfObjects = typeof(TableOfObjects) == "table" and TableOfObjects or {}; |
54 | local X, Y = 0, 0; |
55 | for _, Object in next, TableOfObjects do |
56 | X += Object.AbsoluteSize.X; |
57 | Y += Object.AbsoluteSize.Y; |
58 | end |
59 | return {X = X, Y = Y, x = X, y = Y}; |
60 | end |
61 | |
62 | local CachedObjects = {}; |
63 | |
64 | local function Update() |
65 | local DeltaTime = tick() - LastTick; |
66 | local PreviousObjects = {}; |
67 | for CurObj, Object in next, InstructionObjects do |
68 | local Label, Delta, Done = Object[1], Object[2], Object[3]; |
69 | if (not Done) then |
70 | if (Delta < TweenTime) then |
71 | Object[2] = math.clamp(Delta + DeltaTime, 0, 1); |
72 | Delta = Object[2]; |
73 | else |
74 | Object[3] = true; |
75 | end |
76 | end |
77 | local NewValue = TweenService:GetValue(Delta, TweenStyle, TweenDirection); |
78 | local CurrentPos = Label.Position; |
79 | local PreviousBounds = CalculateBounds(PreviousObjects); |
80 | local TargetPos = UDim2.new(0, 0, 0, PreviousBounds.Y + (Padding * #PreviousObjects)); |
81 | Label.Position = CurrentPos:Lerp(TargetPos, NewValue); |
82 | table.insert(PreviousObjects, Label); |
83 | end |
84 | CachedObjects = PreviousObjects; |
85 | LastTick = tick(); |
86 | end |
87 | |
88 | RunService:BindToRenderStep("UpdateList", 0, Update); |
89 | |
90 | local TitleSettings = { |
91 | Font = Enum.Font.GothamSemibold; |
92 | Size = 14; |
93 | } |
94 | |
95 | local DescriptionSettings = { |
96 | Font = Enum.Font.Gotham; |
97 | Size = 14; |
98 | } |
99 | |
100 | local MaxWidth = (Container.AbsoluteSize.X - Padding - DescriptionPadding); |
101 | |
102 | local function Label(Text, Font, Size, Button) |
103 | local Label = Instance.new(string.format("Text%s", Button and "Button" or "Label")); |
104 | Label.Text = Text; |
105 | Label.Font = Font; |
106 | Label.TextSize = Size; |
107 | Label.BackgroundTransparency = 1; |
108 | Label.TextXAlignment = Enum.TextXAlignment.Left; |
109 | Label.RichText = true; |
110 | Label.TextColor3 = Color3.fromRGB(255, 255, 255); |
111 | return Label; |
112 | end |
113 | |
114 | local function TitleLabel(Text) |
115 | return Label(Text, TitleSettings.Font, TitleSettings.Size); |
116 | end |
117 | |
118 | local function DescriptionLabel(Text) |
119 | return Label(Text, DescriptionSettings.Font, DescriptionSettings.Size); |
120 | end |
121 | |
122 | local PropertyTweenOut = { |
123 | Text = "TextTransparency", |
124 | Fram = "BackgroundTransparency", |
125 | Imag = "ImageTransparency" |
126 | } |
127 | |
128 | local function FadeProperty(Object) |
129 | local Prop = PropertyTweenOut[string.sub(Object.ClassName, 1, 4)]; |
130 | TweenService:Create(Object, TweenInfo.new(0.25, TweenStyle, TweenDirection), { |
131 | [Prop] = 1; |
132 | }):Play(); |
133 | end |
134 | |
135 | local function SearchTableFor(Table, For) |
136 | for _, v in next, Table do |
137 | if (v == For) then |
138 | return true; |
139 | end |
140 | end |
141 | return false; |
142 | end |
143 | |
144 | local function FindIndexByDependency(Table, Dependency) |
145 | for Index, Object in next, Table do |
146 | if (typeof(Object) == "table") then |
147 | local Found = SearchTableFor(Object, Dependency); |
148 | if (Found) then |
149 | return Index; |
150 | end |
151 | else |
152 | if (Object == Dependency) then |
153 | return Index; |
154 | end |
155 | end |
156 | end |
157 | end |
158 | |
159 | local function ResetObjects() |
160 | for _, Object in next, InstructionObjects do |
161 | Object[2] = 0; |
162 | Object[3] = false; |
163 | end |
164 | end |
165 | |
166 | local function FadeOutAfter(Object, Seconds) |
167 | wait(Seconds); |
168 | FadeProperty(Object); |
169 | for _, SubObj in next, Object:GetDescendants() do |
170 | FadeProperty(SubObj); |
171 | end |
172 | wait(0.25); |
173 | table.remove(InstructionObjects, FindIndexByDependency(InstructionObjects, Object)); |
174 | ResetObjects(); |
175 | end |
176 | |
177 | return { |
178 | Notify = function(Properties) |
179 | local Properties = typeof(Properties) == "table" and Properties or {}; |
180 | local Title = Properties.Title; |
181 | local Description = Properties.Description; |
182 | local Duration = Properties.Duration or 5; |
183 | if (Title) or (Description) then -- Check that user has provided title and/or description |
184 | local Y = Title and 26 or 0; |
185 | if (Description) then |
186 | local TextSize = TextService:GetTextSize(Description, DescriptionSettings.Size, DescriptionSettings.Font, Vector2.new(0, 0)); |
187 | for i = 1, math.ceil(TextSize.X / MaxWidth) do |
188 | Y += TextSize.Y; |
189 | end |
190 | Y += 8; |
191 | end |
192 | local NewLabel = Round2px(); |
193 | NewLabel.Size = UDim2.new(1, 0, 0, Y); |
194 | NewLabel.Position = UDim2.new(-1, 20, 0, CalculateBounds(CachedObjects).Y + (Padding * #CachedObjects)); |
195 | if (Title) then |
196 | local NewTitle = TitleLabel(Title); |
197 | NewTitle.Size = UDim2.new(1, -10, 0, 26); |
198 | NewTitle.Position = UDim2.fromOffset(10, 0); |
199 | NewTitle.Parent = NewLabel; |
200 | end |
201 | if (Description) then |
202 | local NewDescription = DescriptionLabel(Description); |
203 | NewDescription.TextWrapped = true; |
204 | NewDescription.Size = UDim2.fromScale(1, 1) + UDim2.fromOffset(-DescriptionPadding, Title and -26 or 0); |
205 | NewDescription.Position = UDim2.fromOffset(10, Title and 26 or 0); |
206 | NewDescription.TextYAlignment = Enum.TextYAlignment[Title and "Top" or "Center"]; |
207 | NewDescription.Parent = NewLabel; |
208 | end |
209 | Shadow2px().Parent = NewLabel; |
210 | NewLabel.Parent = Container; |
211 | table.insert(InstructionObjects, {NewLabel, 0, false}); |
212 | coroutine.wrap(FadeOutAfter)(NewLabel, Duration); |
213 | end |
214 | end, |
215 | } |