azul-sync 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/.gitattributes +1 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +31 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. package/README.md +142 -0
  5. package/dist/build.d.ts +19 -0
  6. package/dist/build.d.ts.map +1 -0
  7. package/dist/build.js +92 -0
  8. package/dist/build.js.map +1 -0
  9. package/dist/cli.d.ts +3 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +397 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/config.d.ts +26 -0
  14. package/dist/config.d.ts.map +1 -0
  15. package/dist/config.js +105 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/fs/fileWriter.d.ts +100 -0
  18. package/dist/fs/fileWriter.d.ts.map +1 -0
  19. package/dist/fs/fileWriter.js +342 -0
  20. package/dist/fs/fileWriter.js.map +1 -0
  21. package/dist/fs/treeManager.d.ts +84 -0
  22. package/dist/fs/treeManager.d.ts.map +1 -0
  23. package/dist/fs/treeManager.js +365 -0
  24. package/dist/fs/treeManager.js.map +1 -0
  25. package/dist/fs/watcher.d.ts +39 -0
  26. package/dist/fs/watcher.d.ts.map +1 -0
  27. package/dist/fs/watcher.js +120 -0
  28. package/dist/fs/watcher.js.map +1 -0
  29. package/dist/index.d.ts +61 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +349 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/ipc/httpPolling.d.ts +56 -0
  34. package/dist/ipc/httpPolling.d.ts.map +1 -0
  35. package/dist/ipc/httpPolling.js +171 -0
  36. package/dist/ipc/httpPolling.js.map +1 -0
  37. package/dist/ipc/messages.d.ts +112 -0
  38. package/dist/ipc/messages.d.ts.map +1 -0
  39. package/dist/ipc/messages.js +5 -0
  40. package/dist/ipc/messages.js.map +1 -0
  41. package/dist/ipc/server.d.ts +50 -0
  42. package/dist/ipc/server.d.ts.map +1 -0
  43. package/dist/ipc/server.js +168 -0
  44. package/dist/ipc/server.js.map +1 -0
  45. package/dist/pack.d.ts +19 -0
  46. package/dist/pack.d.ts.map +1 -0
  47. package/dist/pack.js +225 -0
  48. package/dist/pack.js.map +1 -0
  49. package/dist/push.d.ts +43 -0
  50. package/dist/push.d.ts.map +1 -0
  51. package/dist/push.js +532 -0
  52. package/dist/push.js.map +1 -0
  53. package/dist/rojo.d.ts +9 -0
  54. package/dist/rojo.d.ts.map +1 -0
  55. package/dist/rojo.js +114 -0
  56. package/dist/rojo.js.map +1 -0
  57. package/dist/snapshot/rojo.d.ts +39 -0
  58. package/dist/snapshot/rojo.d.ts.map +1 -0
  59. package/dist/snapshot/rojo.js +364 -0
  60. package/dist/snapshot/rojo.js.map +1 -0
  61. package/dist/snapshot.d.ts +23 -0
  62. package/dist/snapshot.d.ts.map +1 -0
  63. package/dist/snapshot.js +132 -0
  64. package/dist/snapshot.js.map +1 -0
  65. package/dist/sourcemap/generator.d.ts +78 -0
  66. package/dist/sourcemap/generator.d.ts.map +1 -0
  67. package/dist/sourcemap/generator.js +351 -0
  68. package/dist/sourcemap/generator.js.map +1 -0
  69. package/dist/sourcemap/propertyLoader.d.ts +19 -0
  70. package/dist/sourcemap/propertyLoader.d.ts.map +1 -0
  71. package/dist/sourcemap/propertyLoader.js +131 -0
  72. package/dist/sourcemap/propertyLoader.js.map +1 -0
  73. package/dist/util/id.d.ts +9 -0
  74. package/dist/util/id.d.ts.map +1 -0
  75. package/dist/util/id.js +14 -0
  76. package/dist/util/id.js.map +1 -0
  77. package/dist/util/log.d.ts +13 -0
  78. package/dist/util/log.d.ts.map +1 -0
  79. package/dist/util/log.js +51 -0
  80. package/dist/util/log.js.map +1 -0
  81. package/docs/assets/azul-logo.pdn +0 -0
  82. package/docs/assets/logo-200px.png +0 -0
  83. package/docs/assets/logo.png +0 -0
  84. package/docs/assets/plugin/toolbox.png +0 -0
  85. package/docs/assets/synced.png +0 -0
  86. package/package.json +41 -0
  87. package/plugin/README.md +54 -0
  88. package/plugin/sourcemap.json +264 -0
  89. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Actor/AzulSync.server.luau +905 -0
  90. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/AzulService.luau +1010 -0
  91. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Config.luau +29 -0
  92. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/Enums.luau +11 -0
  93. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/CollapsibleTitledSection.luau +214 -0
  94. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/ColorPicker.luau +360 -0
  95. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/CustomTextButton.luau +170 -0
  96. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/DropdownMenu.luau +363 -0
  97. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/HorizontalLine.luau +43 -0
  98. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/ImageButtonWithText.luau +181 -0
  99. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledCheckbox.luau +295 -0
  100. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledColorInputPicker.luau +294 -0
  101. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledMultiChoice.luau +163 -0
  102. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledNumberInput.luau +312 -0
  103. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledRadioButton.luau +55 -0
  104. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledSlider.luau +151 -0
  105. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledTextInput.luau +222 -0
  106. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/LabeledToggleButton.luau +73 -0
  107. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/StatefulImageButton.luau +125 -0
  108. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticalScrollingFrame.luau +100 -0
  109. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticalSpacer.luau +35 -0
  110. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/Components/VerticallyScalingListFrame.luau +107 -0
  111. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/GuiUtilities.luau +429 -0
  112. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/StudioWidgets/RbxGui.luau +4363 -0
  113. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/UI.luau +425 -0
  114. package/plugin/sync/ReplicatedFirst/AzulCompanionPlugin/WebSocketClient.luau +161 -0
  115. package/src/build.ts +120 -0
  116. package/src/cli.ts +496 -0
  117. package/src/config.ts +170 -0
  118. package/src/fs/fileWriter.ts +414 -0
  119. package/src/fs/treeManager.ts +458 -0
  120. package/src/fs/watcher.ts +142 -0
  121. package/src/index.ts +450 -0
  122. package/src/ipc/httpPolling.ts +214 -0
  123. package/src/ipc/messages.ts +159 -0
  124. package/src/ipc/server.ts +196 -0
  125. package/src/pack.ts +309 -0
  126. package/src/push.ts +726 -0
  127. package/src/snapshot/rojo.ts +467 -0
  128. package/src/snapshot.ts +161 -0
  129. package/src/sourcemap/generator.ts +504 -0
  130. package/src/sourcemap/propertyLoader.ts +195 -0
  131. package/src/util/id.ts +15 -0
  132. package/src/util/log.ts +94 -0
  133. package/tsconfig.json +24 -0
@@ -0,0 +1,4363 @@
1
+ local t = {}
2
+
3
+ local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
4
+ local eventConnection = nil
5
+
6
+ --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
7
+ local tryConnect = function()
8
+ if game:IsAncestorOf(parentInstance) then
9
+ --Entering the world, make sure we are connected/synced
10
+ if not eventConnection then
11
+ eventConnection = instance[event]:Connect(signalFunc)
12
+ if syncFunc then syncFunc() end
13
+ end
14
+ else
15
+ --Probably leaving the world, so disconnect for now
16
+ if eventConnection then
17
+ eventConnection:Disconnect()
18
+ if removeFunc then removeFunc() end
19
+ end
20
+ end
21
+ end
22
+
23
+ --Hook it up to ancestryChanged signal
24
+ local connection = parentInstance.AncestryChanged:Connect(tryConnect)
25
+
26
+ --Now connect us if we're already in the world
27
+ tryConnect()
28
+
29
+ return connection
30
+ end
31
+
32
+ local function getLayerCollectorAncestor(instance)
33
+ local localInstance = instance
34
+ while localInstance and not localInstance:IsA("LayerCollector") do
35
+ localInstance = localInstance.Parent
36
+ end
37
+ return localInstance
38
+ end
39
+
40
+ local function CreateButtons(frame, buttons, yPos, ySize)
41
+ local buttonNum = 1
42
+ local buttonObjs = {}
43
+ for i, obj in ipairs(buttons) do
44
+ local button = Instance.new("TextButton")
45
+ button.Name = "Button" .. buttonNum
46
+ button.Font = Enum.Font.Arial
47
+ button.FontSize = Enum.FontSize.Size18
48
+ button.AutoButtonColor = true
49
+ button.Modal = true
50
+ if obj["Style"] then
51
+ button.Style = obj.Style
52
+ else
53
+ button.Style = Enum.ButtonStyle.RobloxButton
54
+ end
55
+ if obj["ZIndex"] then
56
+ button.ZIndex = obj.ZIndex
57
+ end
58
+ button.Text = obj.Text
59
+ button.TextColor3 = Color3.new(1,1,1)
60
+ button.MouseButton1Click:Connect(obj.Function)
61
+ button.Parent = frame
62
+ buttonObjs[buttonNum] = button
63
+
64
+ buttonNum = buttonNum + 1
65
+ end
66
+ local numButtons = buttonNum-1
67
+
68
+ if numButtons == 1 then
69
+ frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
70
+ frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
71
+ elseif numButtons == 2 then
72
+ frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
73
+ frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
74
+
75
+ frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
76
+ frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
77
+ elseif numButtons >= 3 then
78
+ local spacing = .1 / numButtons
79
+ local buttonSize = .9 / numButtons
80
+
81
+ buttonNum = 1
82
+ while buttonNum <= numButtons do
83
+ buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
84
+ buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
85
+ buttonNum = buttonNum + 1
86
+ end
87
+ end
88
+ end
89
+
90
+ local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
91
+
92
+ local newStep = steps - 1 --otherwise we really get one more step than we want
93
+ local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
94
+ local wholeNum, remainder = math.modf(relativePosX * newStep)
95
+ if remainder > 0.5 then
96
+ wholeNum = wholeNum + 1
97
+ end
98
+ relativePosX = wholeNum/newStep
99
+
100
+ local result = math.ceil(relativePosX * newStep)
101
+ if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
102
+ sliderPosition.Value = result + 1
103
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
104
+ end
105
+
106
+ end
107
+
108
+ --- Updates the slider's position and corresponding IntValue based on absolute an X position.
109
+ --- Snaps the slider to the nearest step between min and max values.
110
+ ---
111
+ --- @param newAbsPosX number -- The new absolute X position.
112
+ --- @param slider ImageButton -- The slider button being moved.
113
+ --- @param sliderPosition IntValue -- The IntValue representing the slider's current step-based position.
114
+ --- @param bar TextButton -- The slider bar.
115
+ --- @param stepCount number -- The number of total steps (maxValue - minValue).
116
+ --- @param minValue number -- The minimum selectable value.
117
+ local function setSliderPosNewest(newAbsPosX: number, slider: ImageButton, sliderPosition: IntValue, bar: TextButton, stepCount: number, minValue: number)
118
+
119
+ local newStep = stepCount - 1 --otherwise we really get one more step than we want
120
+ local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
121
+ local wholeNum, remainder = math.modf(relativePosX * stepCount)
122
+ if remainder > 0.5 then
123
+ wholeNum = wholeNum + 1
124
+ end
125
+ relativePosX = wholeNum/newStep
126
+
127
+ local value = minValue + wholeNum
128
+ if sliderPosition.Value ~= value then
129
+ sliderPosition.Value = value
130
+ slider.Position = UDim2.new(relativePosX, -slider.AbsoluteSize.X/2, slider.Position.Y.Scale, slider.Position.Y.Offset)
131
+ end
132
+
133
+ end
134
+
135
+ local function cancelSlide(areaSoak)
136
+ areaSoak.Visible = false
137
+ end
138
+
139
+ t.CreateStyledMessageDialog = function(title, message, style, buttons)
140
+ local frame = Instance.new("Frame")
141
+ frame.Size = UDim2.new(0.5, 0, 0, 165)
142
+ frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
143
+ frame.Name = "MessageDialog"
144
+ frame.Active = true
145
+ frame.Style = Enum.FrameStyle.RobloxRound
146
+
147
+ local styleImage = Instance.new("ImageLabel")
148
+ styleImage.Name = "StyleImage"
149
+ styleImage.BackgroundTransparency = 1
150
+ styleImage.Position = UDim2.new(0,5,0,15)
151
+ if style == "error" or style == "Error" then
152
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
153
+ styleImage.Image = "https://www.roblox.com/asset/?id=42565285"
154
+ elseif style == "notify" or style == "Notify" then
155
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
156
+ styleImage.Image = "https://www.roblox.com/asset/?id=42604978"
157
+ elseif style == "confirm" or style == "Confirm" then
158
+ styleImage.Size = UDim2.new(0, 74, 0, 76)
159
+ styleImage.Image = "https://www.roblox.com/asset/?id=42557901"
160
+ else
161
+ return t.CreateMessageDialog(title,message,buttons)
162
+ end
163
+ styleImage.Parent = frame
164
+
165
+ local titleLabel = Instance.new("TextLabel")
166
+ titleLabel.Name = "Title"
167
+ titleLabel.Text = title
168
+ titleLabel.TextStrokeTransparency = 0
169
+ titleLabel.BackgroundTransparency = 1
170
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
171
+ titleLabel.Position = UDim2.new(0, 80, 0, 0)
172
+ titleLabel.Size = UDim2.new(1, -80, 0, 40)
173
+ titleLabel.Font = Enum.Font.ArialBold
174
+ titleLabel.FontSize = Enum.FontSize.Size36
175
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
176
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
177
+ titleLabel.Parent = frame
178
+
179
+ local messageLabel = Instance.new("TextLabel")
180
+ messageLabel.Name = "Message"
181
+ messageLabel.Text = message
182
+ messageLabel.TextStrokeTransparency = 0
183
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
184
+ messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
185
+ messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
186
+ messageLabel.BackgroundTransparency = 1
187
+ messageLabel.Font = Enum.Font.Arial
188
+ messageLabel.FontSize = Enum.FontSize.Size18
189
+ messageLabel.TextWrap = true
190
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
191
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
192
+ messageLabel.Parent = frame
193
+
194
+ CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
195
+
196
+ return frame
197
+ end
198
+
199
+ t.CreateMessageDialog = function(title, message, buttons)
200
+ local frame = Instance.new("Frame")
201
+ frame.Size = UDim2.new(0.5, 0, 0.5, 0)
202
+ frame.Position = UDim2.new(0.25, 0, 0.25, 0)
203
+ frame.Name = "MessageDialog"
204
+ frame.Active = true
205
+ frame.Style = Enum.FrameStyle.RobloxRound
206
+
207
+ local titleLabel = Instance.new("TextLabel")
208
+ titleLabel.Name = "Title"
209
+ titleLabel.Text = title
210
+ titleLabel.BackgroundTransparency = 1
211
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
212
+ titleLabel.Position = UDim2.new(0, 0, 0, 0)
213
+ titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
214
+ titleLabel.Font = Enum.Font.ArialBold
215
+ titleLabel.FontSize = Enum.FontSize.Size36
216
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
217
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
218
+ titleLabel.Parent = frame
219
+
220
+ local messageLabel = Instance.new("TextLabel")
221
+ messageLabel.Name = "Message"
222
+ messageLabel.Text = message
223
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
224
+ messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
225
+ messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
226
+ messageLabel.BackgroundTransparency = 1
227
+ messageLabel.Font = Enum.Font.Arial
228
+ messageLabel.FontSize = Enum.FontSize.Size18
229
+ messageLabel.TextWrap = true
230
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
231
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
232
+ messageLabel.Parent = frame
233
+
234
+ CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
235
+
236
+ return frame
237
+ end
238
+
239
+ -- written by jmargh
240
+ -- to be used for the new settings menu
241
+ t.CreateScrollingDropDownMenu = function(onSelectedCallback, size, position, baseZ)
242
+ local maxVisibleList = 6
243
+ local baseZIndex = 0
244
+ if type(baseZ) == 'number' then
245
+ baseZIndex = baseZ
246
+ end
247
+
248
+ local dropDownMenu = {}
249
+ local currentList = nil
250
+
251
+ local updateFunc = nil
252
+ local frame = Instance.new('Frame')
253
+ frame.Name = "DropDownMenuFrame"
254
+ frame.Size = size
255
+ frame.Position = position
256
+ frame.BackgroundTransparency = 1
257
+ dropDownMenu.Frame = frame
258
+
259
+ local currentSelectionName = Instance.new('TextButton')
260
+ currentSelectionName.Name = "CurrentSelectionName"
261
+ currentSelectionName.Size = UDim2.new(1, 0, 1, 0)
262
+ currentSelectionName.BackgroundTransparency = 1
263
+ currentSelectionName.Font = Enum.Font.SourceSansBold
264
+ currentSelectionName.FontSize = Enum.FontSize.Size18
265
+ currentSelectionName.TextXAlignment = Enum.TextXAlignment.Left
266
+ currentSelectionName.TextYAlignment = Enum.TextYAlignment.Center
267
+ currentSelectionName.TextColor3 = Color3.new(0.5, 0.5, 0.5)
268
+ currentSelectionName.TextWrap = true
269
+ currentSelectionName.ZIndex = baseZIndex
270
+ currentSelectionName.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
271
+ currentSelectionName.Text = "Choose One"
272
+ currentSelectionName.Parent = frame
273
+ dropDownMenu.CurrentSelectionButton = currentSelectionName
274
+
275
+ local icon = Instance.new('ImageLabel')
276
+ icon.Name = "DropDownIcon"
277
+ icon.Size = UDim2.new(0, 16, 0, 12)
278
+ icon.Position = UDim2.new(1, -17, 0.5, -6)
279
+ icon.Image = 'rbxasset://textures/ui/dropdown_arrow.png'
280
+ icon.BackgroundTransparency = 1
281
+ icon.ZIndex = baseZIndex
282
+ icon.Parent = currentSelectionName
283
+
284
+ local listMenu = nil
285
+ local scrollingBackground = nil
286
+ local visibleCount = 0
287
+ local isOpen = false
288
+
289
+ local function onEntrySelected()
290
+ icon.Rotation = 0
291
+ scrollingBackground:TweenSize(UDim2.new(1, 0, 0, currentSelectionName.AbsoluteSize.y), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.15, true)
292
+ --
293
+ listMenu.ScrollBarThickness = 0
294
+ listMenu:TweenSize(UDim2.new(1, -16, 0, 24), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.15, true, function()
295
+ if not isOpen then
296
+ listMenu.Visible = false
297
+ scrollingBackground.Visible = false
298
+ end
299
+ end)
300
+ isOpen = false
301
+ end
302
+
303
+ currentSelectionName.MouseButton1Click:Connect(function()
304
+ if not currentSelectionName.Active or #currentList == 0 then return end
305
+ if isOpen then
306
+ onEntrySelected()
307
+ return
308
+ end
309
+ --
310
+ isOpen = true
311
+ icon.Rotation = 180
312
+ if listMenu then listMenu.Visible = true end
313
+ if scrollingBackground then scrollingBackground.Visible = true end
314
+ --
315
+ if scrollingBackground then
316
+ scrollingBackground:TweenSize(UDim2.new(1, 0, 0, visibleCount * 24 + 8), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.15, true)
317
+ end
318
+ if listMenu then
319
+ listMenu:TweenSize(UDim2.new(1, -16, 0, visibleCount * 24), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 0.15, true, function()
320
+ listMenu.ScrollBarThickness = 6
321
+ end)
322
+ end
323
+ end)
324
+
325
+ --[[ Public API ]]--
326
+ dropDownMenu.IsOpen = function()
327
+ return isOpen
328
+ end
329
+
330
+ dropDownMenu.Close = function()
331
+ onEntrySelected()
332
+ end
333
+
334
+ dropDownMenu.Reset = function()
335
+ isOpen = false
336
+ icon.Rotation = 0
337
+ listMenu.ScrollBarThickness = 0
338
+ listMenu.Size = UDim2.new(1, -16, 0, 24)
339
+ listMenu.Visible = false
340
+ scrollingBackground.Visible = false
341
+ end
342
+
343
+ dropDownMenu.SetVisible = function(isVisible)
344
+ if frame then
345
+ frame.Visible = isVisible
346
+ end
347
+ end
348
+
349
+ dropDownMenu.UpdateZIndex = function(newZIndexBase)
350
+ currentSelectionName.ZIndex = newZIndexBase
351
+ icon.ZIndex = newZIndexBase
352
+ if scrollingBackground then scrollingBackground.ZIndex = newZIndexBase + 1 end
353
+ if listMenu then
354
+ listMenu.ZIndex = newZIndexBase + 2
355
+ for _,child in pairs(listMenu:GetChildren()) do
356
+ child.ZIndex = newZIndexBase + 4
357
+ end
358
+ end
359
+ end
360
+
361
+ dropDownMenu.SetActive = function(isActive)
362
+ currentSelectionName.Active = isActive
363
+ end
364
+
365
+ dropDownMenu.SetSelectionText = function(text)
366
+ currentSelectionName.Text = text
367
+ end
368
+
369
+ dropDownMenu.CreateList = function(list)
370
+ currentSelectionName.Text = "Choose One"
371
+ if listMenu then listMenu:Destroy() end
372
+ if scrollingBackground then scrollingBackground:Destroy() end
373
+ --
374
+ currentList = list
375
+ local length = #list
376
+ visibleCount = math.min(maxVisibleList, length)
377
+ local listMenuOffset = visibleCount * 24
378
+
379
+ listMenu = Instance.new('ScrollingFrame')
380
+ listMenu.Name = "ListMenu"
381
+ listMenu.Size = UDim2.new(1, -16, 0, 24)
382
+ listMenu.Position = UDim2.new(0, 12, 0, 32)
383
+ listMenu.CanvasSize = UDim2.new(0, 0, 0, length * 24)
384
+ listMenu.BackgroundTransparency = 1
385
+ listMenu.BorderSizePixel = 0
386
+ listMenu.ZIndex = baseZIndex + 2
387
+ listMenu.Visible = false
388
+ listMenu.Active = true
389
+ listMenu.BottomImage = 'rbxasset://textures/ui/scroll-bottom.png'
390
+ listMenu.MidImage = 'rbxasset://textures/ui/scroll-middle.png'
391
+ listMenu.TopImage = 'rbxasset://textures/ui/scroll-top.png'
392
+ listMenu.ScrollBarThickness = 0
393
+ listMenu.Parent = frame
394
+
395
+ scrollingBackground = Instance.new('TextButton')
396
+ scrollingBackground.Name = "ScrollingBackground"
397
+ scrollingBackground.Size = UDim2.new(1, 0, 0, currentSelectionName.AbsoluteSize.y)
398
+ scrollingBackground.Position = UDim2.new(0, 0, 0, 28)
399
+ scrollingBackground.BackgroundColor3 = Color3.new(1, 1, 1)
400
+ scrollingBackground.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
401
+ scrollingBackground.ZIndex = baseZIndex + 1
402
+ scrollingBackground.Text = ""
403
+ scrollingBackground.Visible = false
404
+ scrollingBackground.AutoButtonColor = false
405
+ scrollingBackground.Parent = frame
406
+
407
+ for i = 1, length do
408
+ local entry = list[i]
409
+ local btn = Instance.new('TextButton')
410
+ btn.Name = entry
411
+ btn.Size = UDim2.new(1, 0, 0, 24)
412
+ btn.Position = UDim2.new(0, 0, 0, (i - 1) * 24)
413
+ btn.BackgroundTransparency = 0
414
+ btn.BackgroundColor3 = Color3.new(1, 1, 1)
415
+ btn.BorderSizePixel = 0
416
+ btn.Font = Enum.Font.SourceSans
417
+ btn.FontSize = Enum.FontSize.Size18
418
+ btn.TextColor3 = Color3.new(0.5, 0.5, 0.5)
419
+ btn.TextXAlignment = Enum.TextXAlignment.Left
420
+ btn.TextYAlignment = Enum.TextYAlignment.Center
421
+ btn.Text = entry
422
+ btn.ZIndex = baseZIndex + 4
423
+ btn.AutoButtonColor = false
424
+ btn.Parent = listMenu
425
+
426
+ btn.MouseButton1Click:Connect(function()
427
+ currentSelectionName.Text = btn.Text
428
+ onEntrySelected()
429
+ btn.Font = Enum.Font.SourceSans
430
+ btn.TextColor3 = Color3.new(0.5, 0.5, 0.5)
431
+ btn.BackgroundColor3 = Color3.new(1, 1, 1)
432
+ onSelectedCallback(btn.Text)
433
+ end)
434
+
435
+ btn.MouseEnter:Connect(function()
436
+ btn.TextColor3 = Color3.new(1, 1, 1)
437
+ btn.BackgroundColor3 = Color3.new(0.75, 0.75, 0.75)
438
+ end)
439
+ btn.MouseLeave:Connect(function()
440
+ btn.TextColor3 = Color3.new(0.5, 0.5, 0.5)
441
+ btn.BackgroundColor3 = Color3.new(1, 1, 1)
442
+ end)
443
+ end
444
+ end
445
+
446
+ return dropDownMenu
447
+ end
448
+
449
+ t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ)
450
+ local baseZIndex = 0
451
+ if (type(baseZ) == "number") then
452
+ baseZIndex = baseZ
453
+ end
454
+ local width = UDim.new(0, 100)
455
+ local height = UDim.new(0, 32)
456
+
457
+ local xPos = 0.055
458
+ local frame = Instance.new("Frame")
459
+ local textColor = Color3.new(1,1,1)
460
+ if (whiteSkin) then
461
+ textColor = Color3.new(0.5, 0.5, 0.5)
462
+ end
463
+ frame.Name = "DropDownMenu"
464
+ frame.BackgroundTransparency = 1
465
+ frame.Size = UDim2.new(width, height)
466
+
467
+ local dropDownMenu = Instance.new("TextButton")
468
+ dropDownMenu.Name = "DropDownMenuButton"
469
+ dropDownMenu.TextWrap = true
470
+ dropDownMenu.TextColor3 = textColor
471
+ dropDownMenu.Text = "Choose One"
472
+ dropDownMenu.Font = Enum.Font.ArialBold
473
+ dropDownMenu.FontSize = Enum.FontSize.Size18
474
+ dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
475
+ dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
476
+ dropDownMenu.BackgroundTransparency = 1
477
+ dropDownMenu.AutoButtonColor = true
478
+ if (whiteSkin) then
479
+ dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
480
+ else
481
+ dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
482
+ end
483
+ dropDownMenu.Size = UDim2.new(1,0,1,0)
484
+ dropDownMenu.Parent = frame
485
+ dropDownMenu.ZIndex = 2 + baseZIndex
486
+
487
+ local dropDownIcon = Instance.new("ImageLabel")
488
+ dropDownIcon.Name = "Icon"
489
+ dropDownIcon.Active = false
490
+ if (whiteSkin) then
491
+ dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png"
492
+ dropDownIcon.Size = UDim2.new(0,16,0,12)
493
+ dropDownIcon.Position = UDim2.new(1,-17,0.5, -6)
494
+ else
495
+ dropDownIcon.Image = "https://www.roblox.com/asset/?id=45732894"
496
+ dropDownIcon.Size = UDim2.new(0,11,0,6)
497
+ dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
498
+ end
499
+ dropDownIcon.BackgroundTransparency = 1
500
+ dropDownIcon.Parent = dropDownMenu
501
+ dropDownIcon.ZIndex = 2 + baseZIndex
502
+
503
+ local itemCount = #items
504
+ local dropDownItemCount = #items
505
+ local useScrollButtons = false
506
+ if dropDownItemCount > 6 then
507
+ useScrollButtons = true
508
+ dropDownItemCount = 6
509
+ end
510
+
511
+ local droppedDownMenu = Instance.new("TextButton")
512
+ droppedDownMenu.Name = "List"
513
+ droppedDownMenu.Text = ""
514
+ droppedDownMenu.BackgroundTransparency = 1
515
+ --droppedDownMenu.AutoButtonColor = true
516
+ if (whiteSkin) then
517
+ droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
518
+ else
519
+ droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
520
+ end
521
+ droppedDownMenu.Visible = false
522
+ droppedDownMenu.Active = true --Blocks clicks
523
+ droppedDownMenu.Position = UDim2.new(0,0,0,0)
524
+ droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
525
+ droppedDownMenu.Parent = frame
526
+ droppedDownMenu.ZIndex = 2 + baseZIndex
527
+
528
+ local choiceButton = Instance.new("TextButton")
529
+ choiceButton.Name = "ChoiceButton"
530
+ choiceButton.BackgroundTransparency = 1
531
+ choiceButton.BorderSizePixel = 0
532
+ choiceButton.Text = "ReplaceMe"
533
+ choiceButton.TextColor3 = textColor
534
+ choiceButton.TextXAlignment = Enum.TextXAlignment.Left
535
+ choiceButton.TextYAlignment = Enum.TextYAlignment.Center
536
+ choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
537
+ choiceButton.Font = Enum.Font.Arial
538
+ choiceButton.FontSize = Enum.FontSize.Size18
539
+ if useScrollButtons then
540
+ choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
541
+ else
542
+ choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
543
+ end
544
+ choiceButton.TextWrap = true
545
+ choiceButton.ZIndex = 2 + baseZIndex
546
+
547
+ local areaSoak = Instance.new("TextButton")
548
+ areaSoak.Name = "AreaSoak"
549
+ areaSoak.Text = ""
550
+ areaSoak.BackgroundTransparency = 1
551
+ areaSoak.Active = true
552
+ areaSoak.Size = UDim2.new(1,0,1,0)
553
+ areaSoak.Visible = false
554
+ areaSoak.ZIndex = 3 + baseZIndex
555
+
556
+ local dropDownSelected = false
557
+
558
+ local scrollUpButton
559
+ local scrollDownButton
560
+ local scrollMouseCount = 0
561
+
562
+ local setZIndex = function(baseZIndex)
563
+ droppedDownMenu.ZIndex = baseZIndex +1
564
+ if scrollUpButton then
565
+ scrollUpButton.ZIndex = baseZIndex + 3
566
+ end
567
+ if scrollDownButton then
568
+ scrollDownButton.ZIndex = baseZIndex + 3
569
+ end
570
+
571
+ local children = droppedDownMenu:GetChildren()
572
+ if children then
573
+ for i, child in ipairs(children) do
574
+ if child.Name == "ChoiceButton" then
575
+ child.ZIndex = baseZIndex + 2
576
+ elseif child.Name == "ClickCaptureButton" then
577
+ child.ZIndex = baseZIndex
578
+ end
579
+ end
580
+ end
581
+ end
582
+
583
+ local scrollBarPosition = 1
584
+ local updateScroll = function()
585
+ if scrollUpButton then
586
+ scrollUpButton.Active = scrollBarPosition > 1
587
+ end
588
+ if scrollDownButton then
589
+ scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
590
+ end
591
+
592
+ local children = droppedDownMenu:GetChildren()
593
+ if not children then return end
594
+
595
+ local childNum = 1
596
+ for i, obj in ipairs(children) do
597
+ if obj.Name == "ChoiceButton" then
598
+ if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
599
+ obj.Visible = false
600
+ else
601
+ obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
602
+ obj.Visible = true
603
+ end
604
+ obj.TextColor3 = textColor
605
+ obj.BackgroundTransparency = 1
606
+
607
+ childNum = childNum + 1
608
+ end
609
+ end
610
+ end
611
+ local toggleVisibility = function()
612
+ dropDownSelected = not dropDownSelected
613
+
614
+ areaSoak.Visible = not areaSoak.Visible
615
+ dropDownMenu.Visible = not dropDownSelected
616
+ droppedDownMenu.Visible = dropDownSelected
617
+ if dropDownSelected then
618
+ setZIndex(4 + baseZIndex)
619
+ else
620
+ setZIndex(2 + baseZIndex)
621
+ end
622
+ if useScrollButtons then
623
+ updateScroll()
624
+ end
625
+ end
626
+ droppedDownMenu.MouseButton1Click:Connect(toggleVisibility)
627
+
628
+ local updateSelection = function(text)
629
+ local foundItem = false
630
+ local children = droppedDownMenu:GetChildren()
631
+ local childNum = 1
632
+ if children then
633
+ for i, obj in ipairs(children) do
634
+ if obj.Name == "ChoiceButton" then
635
+ if obj.Text == text then
636
+ obj.Font = Enum.Font.ArialBold
637
+ foundItem = true
638
+ scrollBarPosition = childNum
639
+ if (whiteSkin) then
640
+ obj.TextColor3 = Color3.new(90/255,142/255,233/255)
641
+ end
642
+ else
643
+ obj.Font = Enum.Font.Arial
644
+ if (whiteSkin) then
645
+ obj.TextColor3 = textColor
646
+ end
647
+ end
648
+ childNum = childNum + 1
649
+ end
650
+ end
651
+ end
652
+ if not text then
653
+ dropDownMenu.Text = "Choose One"
654
+ scrollBarPosition = 1
655
+ else
656
+ if not foundItem then
657
+ error("Invalid Selection Update -- " .. text)
658
+ end
659
+
660
+ if scrollBarPosition + dropDownItemCount > itemCount + 1 then
661
+ scrollBarPosition = itemCount - dropDownItemCount + 1
662
+ end
663
+
664
+ dropDownMenu.Text = text
665
+ end
666
+ end
667
+
668
+ local function scrollDown()
669
+ if scrollBarPosition + dropDownItemCount <= itemCount then
670
+ scrollBarPosition = scrollBarPosition + 1
671
+ updateScroll()
672
+ return true
673
+ end
674
+ return false
675
+ end
676
+ local function scrollUp()
677
+ if scrollBarPosition > 1 then
678
+ scrollBarPosition = scrollBarPosition - 1
679
+ updateScroll()
680
+ return true
681
+ end
682
+ return false
683
+ end
684
+
685
+ if useScrollButtons then
686
+ --Make some scroll buttons
687
+ scrollUpButton = Instance.new("ImageButton")
688
+ scrollUpButton.Name = "ScrollUpButton"
689
+ scrollUpButton.BackgroundTransparency = 1
690
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
691
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
692
+ scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
693
+ scrollUpButton.MouseButton1Click:Connect(
694
+ function()
695
+ scrollMouseCount = scrollMouseCount + 1
696
+ end)
697
+ scrollUpButton.MouseLeave:Connect(
698
+ function()
699
+ scrollMouseCount = scrollMouseCount + 1
700
+ end)
701
+ scrollUpButton.MouseButton1Down:Connect(
702
+ function()
703
+ scrollMouseCount = scrollMouseCount + 1
704
+
705
+ scrollUp()
706
+ local val = scrollMouseCount
707
+ wait(0.5)
708
+ while val == scrollMouseCount do
709
+ if scrollUp() == false then
710
+ break
711
+ end
712
+ wait(0.1)
713
+ end
714
+ end)
715
+
716
+ scrollUpButton.Parent = droppedDownMenu
717
+
718
+ scrollDownButton = Instance.new("ImageButton")
719
+ scrollDownButton.Name = "ScrollDownButton"
720
+ scrollDownButton.BackgroundTransparency = 1
721
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
722
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
723
+ scrollDownButton.Position = UDim2.new(1,-11,1,-11)
724
+ scrollDownButton.Parent = droppedDownMenu
725
+ scrollDownButton.MouseButton1Click:Connect(
726
+ function()
727
+ scrollMouseCount = scrollMouseCount + 1
728
+ end)
729
+ scrollDownButton.MouseLeave:Connect(
730
+ function()
731
+ scrollMouseCount = scrollMouseCount + 1
732
+ end)
733
+ scrollDownButton.MouseButton1Down:Connect(
734
+ function()
735
+ scrollMouseCount = scrollMouseCount + 1
736
+
737
+ scrollDown()
738
+ local val = scrollMouseCount
739
+ wait(0.5)
740
+ while val == scrollMouseCount do
741
+ if scrollDown() == false then
742
+ break
743
+ end
744
+ wait(0.1)
745
+ end
746
+ end)
747
+
748
+ local scrollbar = Instance.new("ImageLabel")
749
+ scrollbar.Name = "ScrollBar"
750
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
751
+ scrollbar.BackgroundTransparency = 1
752
+ scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
753
+ scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
754
+ scrollbar.Parent = droppedDownMenu
755
+ end
756
+
757
+ for i,item in ipairs(items) do
758
+ -- needed to maintain local scope for items in event listeners below
759
+ local button = choiceButton:clone()
760
+ if forRoblox then
761
+ button.RobloxLocked = true
762
+ end
763
+ button.Text = item
764
+ button.Parent = droppedDownMenu
765
+ if (whiteSkin) then
766
+ button.TextColor3 = textColor
767
+ end
768
+
769
+ button.MouseButton1Click:Connect(function()
770
+ --Remove Highlight
771
+ if (not whiteSkin) then
772
+ button.TextColor3 = Color3.new(1,1,1)
773
+ end
774
+ button.BackgroundTransparency = 1
775
+
776
+ updateSelection(item)
777
+ onSelect(item)
778
+
779
+ toggleVisibility()
780
+ end)
781
+ button.MouseEnter:Connect(function()
782
+ --Add Highlight
783
+ if (not whiteSkin) then
784
+ button.TextColor3 = Color3.new(0,0,0)
785
+ end
786
+ button.BackgroundTransparency = 0
787
+ end)
788
+
789
+ button.MouseLeave:Connect(function()
790
+ --Remove Highlight
791
+ if (not whiteSkin) then
792
+ button.TextColor3 = Color3.new(1,1,1)
793
+ end
794
+ button.BackgroundTransparency = 1
795
+ end)
796
+ end
797
+
798
+ --This does the initial layout of the buttons
799
+ updateScroll()
800
+
801
+ frame.AncestryChanged:Connect(function(child,parent)
802
+ if parent == nil then
803
+ areaSoak.Parent = nil
804
+ else
805
+ areaSoak.Parent = getLayerCollectorAncestor(frame)
806
+ end
807
+ end)
808
+
809
+ dropDownMenu.MouseButton1Click:Connect(toggleVisibility)
810
+ areaSoak.MouseButton1Click:Connect(toggleVisibility)
811
+ return frame, updateSelection
812
+ end
813
+
814
+ t.CreatePropertyDropDownMenu = function(instance, property, enum)
815
+
816
+ local items = enum:GetEnumItems()
817
+ local names = {}
818
+ local nameToItem = {}
819
+ for i,obj in ipairs(items) do
820
+ names[i] = obj.Name
821
+ nameToItem[obj.Name] = obj
822
+ end
823
+
824
+ local frame
825
+ local updateSelection
826
+ frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
827
+
828
+ ScopedConnect(frame, instance, "Changed",
829
+ function(prop)
830
+ if prop == property then
831
+ updateSelection(instance[property].Name)
832
+ end
833
+ end,
834
+ function()
835
+ updateSelection(instance[property].Name)
836
+ end)
837
+
838
+ return frame
839
+ end
840
+
841
+ t.GetFontHeight = function(font, fontSize)
842
+ if font == nil or fontSize == nil then
843
+ error("Font and FontSize must be non-nil")
844
+ end
845
+
846
+ local fontSizeInt = tonumber(fontSize.Name:match("%d+")) -- Clever hack to extract the size from the enum itself.
847
+
848
+ if font == Enum.Font.Legacy then -- Legacy has a 50% bigger size.
849
+ return math.ceil(fontSizeInt*1.5)
850
+ else -- Size is literally just the fontSizeInt
851
+ return fontSizeInt
852
+ end
853
+ end
854
+
855
+ local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
856
+ local totalPixels = frame.AbsoluteSize.Y
857
+ local pixelsRemaining = frame.AbsoluteSize.Y
858
+ for i, child in ipairs(guiObjects) do
859
+ if child:IsA("TextLabel") or child:IsA("TextButton") then
860
+ local isLabel = child:IsA("TextLabel")
861
+ if isLabel then
862
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
863
+ else
864
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
865
+ end
866
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
867
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
868
+
869
+ if child.TextFits and child.TextBounds.Y < pixelsRemaining then
870
+ child.Visible = true
871
+ if isLabel then
872
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
873
+ else
874
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
875
+ end
876
+
877
+ while not child.TextFits do
878
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
879
+ end
880
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
881
+
882
+ if isLabel then
883
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
884
+ else
885
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
886
+ end
887
+ else
888
+ child.Visible = false
889
+ pixelsRemaining = -1
890
+ end
891
+
892
+ else
893
+ --GuiObject
894
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
895
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
896
+ child.Visible = (pixelsRemaining >= 0)
897
+ end
898
+ end
899
+ end
900
+
901
+ t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
902
+ if not frame:IsA("GuiObject") then
903
+ error("Frame must be a GuiObject")
904
+ end
905
+ for i, child in ipairs(guiObjects) do
906
+ if not child:IsA("GuiObject") then
907
+ error("All elements that are layed out must be of type GuiObject")
908
+ end
909
+ end
910
+
911
+ if not settingsTable then
912
+ settingsTable = {}
913
+ end
914
+
915
+ if not settingsTable["TextLabelSizePadY"] then
916
+ settingsTable["TextLabelSizePadY"] = 0
917
+ end
918
+ if not settingsTable["TextLabelPositionPadY"] then
919
+ settingsTable["TextLabelPositionPadY"] = 0
920
+ end
921
+ if not settingsTable["TextButtonSizePadY"] then
922
+ settingsTable["TextButtonSizePadY"] = 12
923
+ end
924
+ if not settingsTable["TextButtonPositionPadY"] then
925
+ settingsTable["TextButtonPositionPadY"] = 2
926
+ end
927
+
928
+ --Wrapper frame takes care of styled objects
929
+ local wrapperFrame = Instance.new("Frame")
930
+ wrapperFrame.Name = "WrapperFrame"
931
+ wrapperFrame.BackgroundTransparency = 1
932
+ wrapperFrame.Size = UDim2.new(1,0,1,0)
933
+ wrapperFrame.Parent = frame
934
+
935
+ for i, child in ipairs(guiObjects) do
936
+ child.Parent = wrapperFrame
937
+ end
938
+
939
+ local recalculate = function()
940
+ wait()
941
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
942
+ end
943
+
944
+ frame.Changed:Connect(
945
+ function(prop)
946
+ if prop == "AbsoluteSize" then
947
+ --Wait a heartbeat for it to sync in
948
+ recalculate(nil)
949
+ end
950
+ end)
951
+ frame.AncestryChanged:Connect(recalculate)
952
+
953
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
954
+ end
955
+
956
+
957
+ t.CreateSlider = function(steps,width,position)
958
+ local sliderGui = Instance.new("Frame")
959
+ sliderGui.Size = UDim2.new(1,0,1,0)
960
+ sliderGui.BackgroundTransparency = 1
961
+ sliderGui.Name = "SliderGui"
962
+
963
+ local sliderSteps = Instance.new("IntValue")
964
+ sliderSteps.Name = "SliderSteps"
965
+ sliderSteps.Value = steps
966
+ sliderSteps.Parent = sliderGui
967
+
968
+ local areaSoak = Instance.new("TextButton")
969
+ areaSoak.Name = "AreaSoak"
970
+ areaSoak.Text = ""
971
+ areaSoak.BackgroundTransparency = 1
972
+ areaSoak.Active = false
973
+ areaSoak.Size = UDim2.new(1,0,1,0)
974
+ areaSoak.Visible = false
975
+ areaSoak.ZIndex = 4
976
+
977
+ sliderGui.AncestryChanged:Connect(function(child,parent)
978
+ if parent == nil then
979
+ areaSoak.Parent = nil
980
+ else
981
+ areaSoak.Parent = getLayerCollectorAncestor(sliderGui)
982
+ end
983
+ end)
984
+
985
+ local sliderPosition = Instance.new("IntValue")
986
+ sliderPosition.Name = "SliderPosition"
987
+ sliderPosition.Value = 0
988
+ sliderPosition.Parent = sliderGui
989
+
990
+ local id = math.random(1,100)
991
+
992
+ local bar = Instance.new("TextButton")
993
+ bar.Text = ""
994
+ bar.AutoButtonColor = false
995
+ bar.Name = "Bar"
996
+ bar.BackgroundColor3 = Color3.new(0,0,0)
997
+ if type(width) == "number" then
998
+ bar.Size = UDim2.new(0,width,0,5)
999
+ else
1000
+ bar.Size = UDim2.new(0,200,0,5)
1001
+ end
1002
+ bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
1003
+ bar.ZIndex = 2
1004
+ bar.Parent = sliderGui
1005
+
1006
+ if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
1007
+ bar.Position = position
1008
+ end
1009
+
1010
+ local slider = Instance.new("ImageButton")
1011
+ slider.Name = "Slider"
1012
+ slider.BackgroundTransparency = 1
1013
+ slider.Image = "rbxasset://textures/ui/Slider.png"
1014
+ slider.Position = UDim2.new(0,0,0.5,-10)
1015
+ slider.Size = UDim2.new(0,20,0,20)
1016
+ slider.ZIndex = 3
1017
+ slider.Parent = bar
1018
+
1019
+ local areaSoakMouseMoveCon = nil
1020
+
1021
+ areaSoak.MouseLeave:Connect(function()
1022
+ if areaSoak.Visible then
1023
+ cancelSlide(areaSoak)
1024
+ end
1025
+ end)
1026
+ areaSoak.MouseButton1Up:Connect(function()
1027
+ if areaSoak.Visible then
1028
+ cancelSlide(areaSoak)
1029
+ end
1030
+ end)
1031
+
1032
+ slider.MouseButton1Down:Connect(function()
1033
+ areaSoak.Visible = true
1034
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:Disconnect() end
1035
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:Connect(function(x,y)
1036
+ setSliderPos(x,slider,sliderPosition,bar,steps)
1037
+ end)
1038
+ end)
1039
+
1040
+ slider.MouseButton1Up:Connect(function() cancelSlide(areaSoak) end)
1041
+
1042
+ sliderPosition.Changed:Connect(function(prop)
1043
+ sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
1044
+ local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
1045
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
1046
+ end)
1047
+
1048
+ bar.MouseButton1Down:Connect(function(x,y)
1049
+ setSliderPos(x,slider,sliderPosition,bar,steps)
1050
+ end)
1051
+
1052
+ return sliderGui, sliderPosition, sliderSteps
1053
+
1054
+ end
1055
+
1056
+ --- Creates a customizable horizontal slider UI element.
1057
+ --- This newest version supports setting a minimum and maximum value.
1058
+ --- Returns the slider GUI frame and the IntValue holding the current position
1059
+ --- @param minValue number -- The minimum selectable value on the slider.
1060
+ --- @param maxValue number -- The maximum selectable value on the slider.
1061
+ --- @param width number -- The pixel width of the slider bar.
1062
+ --- @param position UDim2 -- The UDim2 position to place the slider bar.
1063
+ --- @return Frame -- The slider GUI container.
1064
+ --- @return IntValue -- The current slider position (updated when the user moves the slider).
1065
+ t.CreateSliderNewest = function(minValue: number, maxValue: number, width: number, position: UDim2)
1066
+ minValue = minValue or 0
1067
+ maxValue = maxValue or 100
1068
+ width = width or 200
1069
+ assert(minValue < maxValue, "Min value cannot be greater than or equal to max value")
1070
+
1071
+ local stepCount = maxValue - minValue
1072
+
1073
+ local sliderGui = Instance.new("Frame")
1074
+ sliderGui.Size = UDim2.new(1,0,1,0)
1075
+ sliderGui.BackgroundTransparency = 1
1076
+ sliderGui.Name = "SliderGui"
1077
+
1078
+ local sliderMinValue = Instance.new("IntValue")
1079
+ sliderMinValue.Name = "SliderMinValue"
1080
+ sliderMinValue.Value = minValue
1081
+ sliderMinValue.Parent = sliderGui
1082
+
1083
+ local sliderMaxValue = Instance.new("IntValue")
1084
+ sliderMaxValue.Name = "SliderMaxValue"
1085
+ sliderMaxValue.Value = maxValue
1086
+ sliderMaxValue.Parent = sliderGui
1087
+
1088
+ local areaSoak = Instance.new("TextButton")
1089
+ areaSoak.Name = "AreaSoak_slider"
1090
+ areaSoak.Text = ""
1091
+ areaSoak.BackgroundTransparency = 1
1092
+ areaSoak.Active = false
1093
+ areaSoak.Size = UDim2.new(1,0,1,0)
1094
+ areaSoak.Visible = false
1095
+ areaSoak.ZIndex = 4
1096
+
1097
+ sliderGui.AncestryChanged:Connect(function(child,parent)
1098
+ if parent == nil then
1099
+ areaSoak.Parent = nil
1100
+ else
1101
+ areaSoak.Parent = getLayerCollectorAncestor(sliderGui)
1102
+ end
1103
+ end)
1104
+
1105
+ local sliderPosition = Instance.new("IntValue")
1106
+ sliderPosition.Name = "SliderPosition"
1107
+ sliderPosition.Value = minValue
1108
+ sliderPosition.Parent = sliderGui
1109
+
1110
+ local bar = Instance.new("TextButton")
1111
+ bar.Text = ""
1112
+ bar.AutoButtonColor = false
1113
+ bar.Name = "Bar"
1114
+ bar.BackgroundColor3 = Color3.new(0,0,0)
1115
+ bar.Size = UDim2.new(0,width,0,5)
1116
+ bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
1117
+ bar.ZIndex = 2
1118
+ bar.Parent = sliderGui
1119
+
1120
+ if typeof(position) == "UDim2" then
1121
+ bar.Position = position
1122
+ end
1123
+
1124
+ local slider = Instance.new("ImageButton")
1125
+ slider.Name = "Slider"
1126
+ slider.BackgroundTransparency = 1
1127
+ slider.Image = "rbxasset://textures/ui/Slider.png"
1128
+ slider.Position = UDim2.new(0,0,0.5,-10)
1129
+ slider.Size = UDim2.new(0,20,0,20)
1130
+ slider.ZIndex = 3
1131
+ slider.Parent = bar
1132
+
1133
+ local areaSoakMouseMoveCon = nil
1134
+
1135
+ areaSoak.MouseLeave:Connect(function()
1136
+ if areaSoak.Visible then
1137
+ cancelSlide(areaSoak)
1138
+ end
1139
+ end)
1140
+ areaSoak.MouseButton1Up:Connect(function()
1141
+ if areaSoak.Visible then
1142
+ cancelSlide(areaSoak)
1143
+ end
1144
+ end)
1145
+
1146
+ slider.MouseButton1Down:Connect(function()
1147
+ areaSoak.Visible = true
1148
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:Disconnect() end
1149
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:Connect(function(x,y)
1150
+ setSliderPosNewest(x,slider,sliderPosition,bar,stepCount,minValue)
1151
+ end)
1152
+ end)
1153
+
1154
+ slider.MouseButton1Up:Connect(function() cancelSlide(areaSoak) end)
1155
+
1156
+ sliderPosition.Changed:Connect(function(prop)
1157
+ local clamped = math.clamp(sliderPosition.Value, minValue, maxValue)
1158
+ if sliderPosition.Value ~= clamped then
1159
+ sliderPosition.Value = clamped
1160
+ return -- should return now since a new .Changed event will be triggered by the line above
1161
+ end
1162
+ local relativePosX = (sliderPosition.Value - minValue) / stepCount
1163
+ slider.Position = UDim2.new(relativePosX, -slider.AbsoluteSize.X/2, slider.Position.Y.Scale, slider.Position.Y.Offset)
1164
+ end)
1165
+
1166
+ bar.MouseButton1Down:Connect(function(x,y)
1167
+ setSliderPosNewest(x,slider,sliderPosition,bar,stepCount,minValue)
1168
+ end)
1169
+
1170
+ return sliderGui, sliderPosition
1171
+
1172
+ end
1173
+
1174
+
1175
+ t.CreateSliderNew = function(steps,width,position)
1176
+ local sliderGui = Instance.new("Frame")
1177
+ sliderGui.Size = UDim2.new(1,0,1,0)
1178
+ sliderGui.BackgroundTransparency = 1
1179
+ sliderGui.Name = "SliderGui"
1180
+
1181
+ local sliderSteps = Instance.new("IntValue")
1182
+ sliderSteps.Name = "SliderSteps"
1183
+ sliderSteps.Value = steps
1184
+ sliderSteps.Parent = sliderGui
1185
+
1186
+ local areaSoak = Instance.new("TextButton")
1187
+ areaSoak.Name = "AreaSoak"
1188
+ areaSoak.Text = ""
1189
+ areaSoak.BackgroundTransparency = 1
1190
+ areaSoak.Active = false
1191
+ areaSoak.Size = UDim2.new(1,0,1,0)
1192
+ areaSoak.Visible = false
1193
+ areaSoak.ZIndex = 6
1194
+
1195
+ sliderGui.AncestryChanged:Connect(function(child,parent)
1196
+ if parent == nil then
1197
+ areaSoak.Parent = nil
1198
+ else
1199
+ areaSoak.Parent = getLayerCollectorAncestor(sliderGui)
1200
+ end
1201
+ end)
1202
+
1203
+ local sliderPosition = Instance.new("IntValue")
1204
+ sliderPosition.Name = "SliderPosition"
1205
+ sliderPosition.Value = 0
1206
+ sliderPosition.Parent = sliderGui
1207
+
1208
+ local id = math.random(1,100)
1209
+
1210
+ local sliderBarImgHeight = 7
1211
+ local sliderBarCapImgWidth = 4
1212
+
1213
+ local bar = Instance.new("ImageButton")
1214
+ bar.BackgroundTransparency = 1
1215
+ bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png"
1216
+ bar.Name = "Bar"
1217
+ local displayWidth = 200
1218
+ if type(width) == "number" then
1219
+ bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight)
1220
+ displayWidth = width - (sliderBarCapImgWidth * 2)
1221
+ else
1222
+ bar.Size = UDim2.new(0,200,0,sliderBarImgHeight)
1223
+ end
1224
+ bar.ZIndex = 3
1225
+ bar.Parent = sliderGui
1226
+ if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
1227
+ bar.Position = position
1228
+ end
1229
+
1230
+ local barLeft = bar:clone()
1231
+ barLeft.Name = "BarLeft"
1232
+ barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png"
1233
+ barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight)
1234
+ barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset)
1235
+ barLeft.Parent = sliderGui
1236
+ barLeft.ZIndex = 3
1237
+
1238
+ local barRight = barLeft:clone()
1239
+ barRight.Name = "BarRight"
1240
+ barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png"
1241
+ barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset)
1242
+ barRight.Parent = sliderGui
1243
+
1244
+ local fillLeft = barLeft:clone()
1245
+ fillLeft.Name = "FillLeft"
1246
+ fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png"
1247
+ fillLeft.Parent = sliderGui
1248
+ fillLeft.ZIndex = 4
1249
+
1250
+ local fill = fillLeft:clone()
1251
+ fill.Name = "Fill"
1252
+ fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png"
1253
+ fill.Parent = bar
1254
+ fill.ZIndex = 4
1255
+ fill.Position = UDim2.new(0, 0, 0, 0)
1256
+ fill.Size = UDim2.new(0.5, 0, 1, 0)
1257
+
1258
+
1259
+ -- bar.Visible = false
1260
+
1261
+ local slider = Instance.new("ImageButton")
1262
+ slider.Name = "Slider"
1263
+ slider.BackgroundTransparency = 1
1264
+ slider.Image = "rbxasset://textures/ui/slider_new_tab.png"
1265
+ slider.Position = UDim2.new(0,0,0.5,-14)
1266
+ slider.Size = UDim2.new(0,28,0,28)
1267
+ slider.ZIndex = 5
1268
+ slider.Parent = bar
1269
+
1270
+ local areaSoakMouseMoveCon = nil
1271
+
1272
+ areaSoak.MouseLeave:Connect(function()
1273
+ if areaSoak.Visible then
1274
+ cancelSlide(areaSoak)
1275
+ end
1276
+ end)
1277
+ areaSoak.MouseButton1Up:Connect(function()
1278
+ if areaSoak.Visible then
1279
+ cancelSlide(areaSoak)
1280
+ end
1281
+ end)
1282
+
1283
+ slider.MouseButton1Down:Connect(function()
1284
+ areaSoak.Visible = true
1285
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:Disconnect() end
1286
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:Connect(function(x,y)
1287
+ setSliderPos(x,slider,sliderPosition,bar,steps)
1288
+ end)
1289
+ end)
1290
+
1291
+ slider.MouseButton1Up:Connect(function() cancelSlide(areaSoak) end)
1292
+
1293
+ sliderPosition.Changed:Connect(function(prop)
1294
+ sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
1295
+ local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
1296
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
1297
+ fill.Size = UDim2.new(relativePosX, 0, 1, 0)
1298
+ end)
1299
+
1300
+ bar.MouseButton1Down:Connect(function(x,y)
1301
+ setSliderPos(x,slider,sliderPosition,bar,steps)
1302
+ end)
1303
+
1304
+ fill.MouseButton1Down:Connect(function(x,y)
1305
+ setSliderPos(x,slider,sliderPosition,bar,steps)
1306
+ end)
1307
+
1308
+ fillLeft.MouseButton1Down:Connect(function(x,y)
1309
+ setSliderPos(x,slider,sliderPosition,bar,steps)
1310
+ end)
1311
+
1312
+
1313
+ return sliderGui, sliderPosition, sliderSteps
1314
+
1315
+ end
1316
+
1317
+
1318
+
1319
+
1320
+
1321
+ t.CreateTrueScrollingFrame = function()
1322
+ local lowY = nil
1323
+ local highY = nil
1324
+
1325
+ local dragCon = nil
1326
+ local upCon = nil
1327
+
1328
+ local internalChange = false
1329
+
1330
+ local descendantsChangeConMap = {}
1331
+
1332
+ local scrollingFrame = Instance.new("Frame")
1333
+ scrollingFrame.Name = "ScrollingFrame"
1334
+ scrollingFrame.Active = true
1335
+ scrollingFrame.Size = UDim2.new(1,0,1,0)
1336
+ scrollingFrame.ClipsDescendants = true
1337
+
1338
+ local controlFrame = Instance.new("Frame")
1339
+ controlFrame.Name = "ControlFrame"
1340
+ controlFrame.BackgroundTransparency = 1
1341
+ controlFrame.Size = UDim2.new(0,18,1,0)
1342
+ controlFrame.Position = UDim2.new(1,-20,0,0)
1343
+ controlFrame.Parent = scrollingFrame
1344
+
1345
+ local scrollBottom = Instance.new("BoolValue")
1346
+ scrollBottom.Value = false
1347
+ scrollBottom.Name = "ScrollBottom"
1348
+ scrollBottom.Parent = controlFrame
1349
+
1350
+ local scrollUp = Instance.new("BoolValue")
1351
+ scrollUp.Value = false
1352
+ scrollUp.Name = "scrollUp"
1353
+ scrollUp.Parent = controlFrame
1354
+
1355
+ local scrollUpButton = Instance.new("TextButton")
1356
+ scrollUpButton.Name = "ScrollUpButton"
1357
+ scrollUpButton.Text = ""
1358
+ scrollUpButton.AutoButtonColor = false
1359
+ scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
1360
+ scrollUpButton.BorderColor3 = Color3.new(1,1,1)
1361
+ scrollUpButton.BackgroundTransparency = 0.5
1362
+ scrollUpButton.Size = UDim2.new(0,18,0,18)
1363
+ scrollUpButton.ZIndex = 2
1364
+ scrollUpButton.Parent = controlFrame
1365
+ for i = 1, 6 do
1366
+ local triFrame = Instance.new("Frame")
1367
+ triFrame.BorderColor3 = Color3.new(1,1,1)
1368
+ triFrame.Name = "tri" .. tostring(i)
1369
+ triFrame.ZIndex = 3
1370
+ triFrame.BackgroundTransparency = 0.5
1371
+ triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
1372
+ triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
1373
+ triFrame.Parent = scrollUpButton
1374
+ end
1375
+ scrollUpButton.MouseEnter:Connect(function()
1376
+ scrollUpButton.BackgroundTransparency = 0.1
1377
+ local upChildren = scrollUpButton:GetChildren()
1378
+ for i = 1, #upChildren do
1379
+ upChildren[i].BackgroundTransparency = 0.1
1380
+ end
1381
+ end)
1382
+ scrollUpButton.MouseLeave:Connect(function()
1383
+ scrollUpButton.BackgroundTransparency = 0.5
1384
+ local upChildren = scrollUpButton:GetChildren()
1385
+ for i = 1, #upChildren do
1386
+ upChildren[i].BackgroundTransparency = 0.5
1387
+ end
1388
+ end)
1389
+
1390
+ local scrollDownButton = scrollUpButton:clone()
1391
+ scrollDownButton.Name = "ScrollDownButton"
1392
+ scrollDownButton.Position = UDim2.new(0,0,1,-18)
1393
+ local downChildren = scrollDownButton:GetChildren()
1394
+ for i = 1, #downChildren do
1395
+ downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
1396
+ end
1397
+ scrollDownButton.MouseEnter:Connect(function()
1398
+ scrollDownButton.BackgroundTransparency = 0.1
1399
+ local downChildren = scrollDownButton:GetChildren()
1400
+ for i = 1, #downChildren do
1401
+ downChildren[i].BackgroundTransparency = 0.1
1402
+ end
1403
+ end)
1404
+ scrollDownButton.MouseLeave:Connect(function()
1405
+ scrollDownButton.BackgroundTransparency = 0.5
1406
+ local downChildren = scrollDownButton:GetChildren()
1407
+ for i = 1, #downChildren do
1408
+ downChildren[i].BackgroundTransparency = 0.5
1409
+ end
1410
+ end)
1411
+ scrollDownButton.Parent = controlFrame
1412
+
1413
+ local scrollTrack = Instance.new("Frame")
1414
+ scrollTrack.Name = "ScrollTrack"
1415
+ scrollTrack.BackgroundTransparency = 1
1416
+ scrollTrack.Size = UDim2.new(0,18,1,-38)
1417
+ scrollTrack.Position = UDim2.new(0,0,0,19)
1418
+ scrollTrack.Parent = controlFrame
1419
+
1420
+ local scrollbar = Instance.new("TextButton")
1421
+ scrollbar.BackgroundColor3 = Color3.new(0,0,0)
1422
+ scrollbar.BorderColor3 = Color3.new(1,1,1)
1423
+ scrollbar.BackgroundTransparency = 0.5
1424
+ scrollbar.AutoButtonColor = false
1425
+ scrollbar.Text = ""
1426
+ scrollbar.Active = true
1427
+ scrollbar.Name = "ScrollBar"
1428
+ scrollbar.ZIndex = 2
1429
+ scrollbar.BackgroundTransparency = 0.5
1430
+ scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
1431
+ scrollbar.Position = UDim2.new(0,0,0,0)
1432
+ scrollbar.Parent = scrollTrack
1433
+
1434
+ local scrollNub = Instance.new("Frame")
1435
+ scrollNub.Name = "ScrollNub"
1436
+ scrollNub.BorderColor3 = Color3.new(1,1,1)
1437
+ scrollNub.Size = UDim2.new(0,10,0,0)
1438
+ scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
1439
+ scrollNub.ZIndex = 2
1440
+ scrollNub.BackgroundTransparency = 0.5
1441
+ scrollNub.Parent = scrollbar
1442
+
1443
+ local newNub = scrollNub:clone()
1444
+ newNub.Position = UDim2.new(0.5,-5,0.5,-2)
1445
+ newNub.Parent = scrollbar
1446
+
1447
+ local lastNub = scrollNub:clone()
1448
+ lastNub.Position = UDim2.new(0.5,-5,0.5,2)
1449
+ lastNub.Parent = scrollbar
1450
+
1451
+ scrollbar.MouseEnter:Connect(function()
1452
+ scrollbar.BackgroundTransparency = 0.1
1453
+ scrollNub.BackgroundTransparency = 0.1
1454
+ newNub.BackgroundTransparency = 0.1
1455
+ lastNub.BackgroundTransparency = 0.1
1456
+ end)
1457
+ scrollbar.MouseLeave:Connect(function()
1458
+ scrollbar.BackgroundTransparency = 0.5
1459
+ scrollNub.BackgroundTransparency = 0.5
1460
+ newNub.BackgroundTransparency = 0.5
1461
+ lastNub.BackgroundTransparency = 0.5
1462
+ end)
1463
+
1464
+ local mouseDrag = Instance.new("ImageButton")
1465
+ mouseDrag.Active = false
1466
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
1467
+ mouseDrag.AutoButtonColor = false
1468
+ mouseDrag.BackgroundTransparency = 1
1469
+ mouseDrag.Name = "mouseDrag"
1470
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
1471
+ mouseDrag.ZIndex = 10
1472
+
1473
+ local function positionScrollBar(x,y,offset)
1474
+ local oldPos = scrollbar.Position
1475
+
1476
+ if y < scrollTrack.AbsolutePosition.y then
1477
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
1478
+ return (oldPos ~= scrollbar.Position)
1479
+ end
1480
+
1481
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
1482
+
1483
+ if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
1484
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
1485
+ return (oldPos ~= scrollbar.Position)
1486
+ end
1487
+ local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
1488
+ if newScaleYPos + relativeSize > 1 then
1489
+ newScaleYPos = 1 - relativeSize
1490
+ scrollBottom.Value = true
1491
+ scrollUp.Value = false
1492
+ elseif newScaleYPos <= 0 then
1493
+ newScaleYPos = 0
1494
+ scrollUp.Value = true
1495
+ scrollBottom.Value = false
1496
+ else
1497
+ scrollUp.Value = false
1498
+ scrollBottom.Value = false
1499
+ end
1500
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
1501
+
1502
+ return (oldPos ~= scrollbar.Position)
1503
+ end
1504
+
1505
+ local function drillDownSetHighLow(instance)
1506
+ if not instance or not instance:IsA("GuiObject") then return end
1507
+ if instance == controlFrame then return end
1508
+ if instance:IsDescendantOf(controlFrame) then return end
1509
+ if not instance.Visible then return end
1510
+
1511
+ if lowY and lowY > instance.AbsolutePosition.Y then
1512
+ lowY = instance.AbsolutePosition.Y
1513
+ elseif not lowY then
1514
+ lowY = instance.AbsolutePosition.Y
1515
+ end
1516
+ if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
1517
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
1518
+ elseif not highY then
1519
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
1520
+ end
1521
+ local children = instance:GetChildren()
1522
+ for i = 1, #children do
1523
+ drillDownSetHighLow(children[i])
1524
+ end
1525
+ end
1526
+
1527
+ local function resetHighLow()
1528
+ local firstChildren = scrollingFrame:GetChildren()
1529
+
1530
+ for i = 1, #firstChildren do
1531
+ drillDownSetHighLow(firstChildren[i])
1532
+ end
1533
+ end
1534
+
1535
+ local function recalculate()
1536
+ internalChange = true
1537
+
1538
+ local percentFrame = 0
1539
+ if scrollbar.Position.Y.Scale > 0 then
1540
+ if scrollbar.Visible then
1541
+ percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
1542
+ else
1543
+ percentFrame = 0
1544
+ end
1545
+ end
1546
+ if percentFrame > 0.99 then percentFrame = 1 end
1547
+
1548
+ local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
1549
+
1550
+ local guiChildren = scrollingFrame:GetChildren()
1551
+ for i = 1, #guiChildren do
1552
+ if guiChildren[i] ~= controlFrame then
1553
+ guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
1554
+ 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
1555
+ end
1556
+ end
1557
+
1558
+ lowY = nil
1559
+ highY = nil
1560
+ resetHighLow()
1561
+ internalChange = false
1562
+ end
1563
+
1564
+ local function setSliderSizeAndPosition()
1565
+ if not highY or not lowY then return end
1566
+
1567
+ local totalYSpan = math.abs(highY - lowY)
1568
+ if totalYSpan == 0 then
1569
+ scrollbar.Visible = false
1570
+ scrollDownButton.Visible = false
1571
+ scrollUpButton.Visible = false
1572
+
1573
+ if dragCon then dragCon:Disconnect() dragCon = nil end
1574
+ if upCon then upCon:Disconnect() upCon = nil end
1575
+ return
1576
+ end
1577
+
1578
+ local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
1579
+ if percentShown >= 1 then
1580
+ scrollbar.Visible = false
1581
+ scrollDownButton.Visible = false
1582
+ scrollUpButton.Visible = false
1583
+ recalculate()
1584
+ else
1585
+ scrollbar.Visible = true
1586
+ scrollDownButton.Visible = true
1587
+ scrollUpButton.Visible = true
1588
+
1589
+ scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
1590
+ end
1591
+
1592
+ local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
1593
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
1594
+
1595
+ if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
1596
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
1597
+ end
1598
+
1599
+ if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
1600
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
1601
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
1602
+ end
1603
+ end
1604
+
1605
+ local buttonScrollAmountPixels = 7
1606
+ local reentrancyGuardScrollUp = false
1607
+ local function doScrollUp()
1608
+ if reentrancyGuardScrollUp then return end
1609
+
1610
+ reentrancyGuardScrollUp = true
1611
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
1612
+ recalculate()
1613
+ end
1614
+ reentrancyGuardScrollUp = false
1615
+ end
1616
+
1617
+ local reentrancyGuardScrollDown = false
1618
+ local function doScrollDown()
1619
+ if reentrancyGuardScrollDown then return end
1620
+
1621
+ reentrancyGuardScrollDown = true
1622
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
1623
+ recalculate()
1624
+ end
1625
+ reentrancyGuardScrollDown = false
1626
+ end
1627
+
1628
+ local function scrollUp(mouseYPos)
1629
+ if scrollUpButton.Active then
1630
+ scrollStamp = tick()
1631
+ local current = scrollStamp
1632
+ local upCon
1633
+ upCon = mouseDrag.MouseButton1Up:Connect(function()
1634
+ scrollStamp = tick()
1635
+ mouseDrag.Parent = nil
1636
+ upCon:Disconnect()
1637
+ end)
1638
+ mouseDrag.Parent = getLayerCollectorAncestor(scrollbar)
1639
+ doScrollUp()
1640
+ wait(0.2)
1641
+ local t = tick()
1642
+ local w = 0.1
1643
+ while scrollStamp == current do
1644
+ doScrollUp()
1645
+ if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
1646
+ break
1647
+ end
1648
+ if not scrollUpButton.Active then break end
1649
+ if tick()-t > 5 then
1650
+ w = 0
1651
+ elseif tick()-t > 2 then
1652
+ w = 0.06
1653
+ end
1654
+ wait(w)
1655
+ end
1656
+ end
1657
+ end
1658
+
1659
+ local function scrollDown(mouseYPos)
1660
+ if scrollDownButton.Active then
1661
+ scrollStamp = tick()
1662
+ local current = scrollStamp
1663
+ local downCon
1664
+ downCon = mouseDrag.MouseButton1Up:Connect(function()
1665
+ scrollStamp = tick()
1666
+ mouseDrag.Parent = nil
1667
+ downCon:Disconnect()
1668
+ end)
1669
+ mouseDrag.Parent = getLayerCollectorAncestor(scrollbar)
1670
+ doScrollDown()
1671
+ wait(0.2)
1672
+ local t = tick()
1673
+ local w = 0.1
1674
+ while scrollStamp == current do
1675
+ doScrollDown()
1676
+ if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
1677
+ break
1678
+ end
1679
+ if not scrollDownButton.Active then break end
1680
+ if tick()-t > 5 then
1681
+ w = 0
1682
+ elseif tick()-t > 2 then
1683
+ w = 0.06
1684
+ end
1685
+ wait(w)
1686
+ end
1687
+ end
1688
+ end
1689
+
1690
+ scrollbar.MouseButton1Down:Connect(function(x,y)
1691
+ if scrollbar.Active then
1692
+ scrollStamp = tick()
1693
+ local mouseOffset = y - scrollbar.AbsolutePosition.y
1694
+ if dragCon then dragCon:Disconnect() dragCon = nil end
1695
+ if upCon then upCon:Disconnect() upCon = nil end
1696
+ local prevY = y
1697
+ local reentrancyGuardMouseScroll = false
1698
+ dragCon = mouseDrag.MouseMoved:Connect(function(x,y)
1699
+ if reentrancyGuardMouseScroll then return end
1700
+
1701
+ reentrancyGuardMouseScroll = true
1702
+ if positionScrollBar(x,y,mouseOffset) then
1703
+ recalculate()
1704
+ end
1705
+ reentrancyGuardMouseScroll = false
1706
+
1707
+ end)
1708
+ upCon = mouseDrag.MouseButton1Up:Connect(function()
1709
+ scrollStamp = tick()
1710
+ mouseDrag.Parent = nil
1711
+ dragCon:Disconnect(); dragCon = nil
1712
+ upCon:Disconnect(); drag = nil
1713
+ end)
1714
+ mouseDrag.Parent = getLayerCollectorAncestor(scrollbar)
1715
+ end
1716
+ end)
1717
+
1718
+ local scrollMouseCount = 0
1719
+
1720
+ scrollUpButton.MouseButton1Down:Connect(function()
1721
+ scrollUp()
1722
+ end)
1723
+ scrollUpButton.MouseButton1Up:Connect(function()
1724
+ scrollStamp = tick()
1725
+ end)
1726
+
1727
+ scrollDownButton.MouseButton1Up:Connect(function()
1728
+ scrollStamp = tick()
1729
+ end)
1730
+ scrollDownButton.MouseButton1Down:Connect(function()
1731
+ scrollDown()
1732
+ end)
1733
+
1734
+ scrollbar.MouseButton1Up:Connect(function()
1735
+ scrollStamp = tick()
1736
+ end)
1737
+
1738
+ local function heightCheck(instance)
1739
+ if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
1740
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
1741
+ elseif not highY then
1742
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
1743
+ end
1744
+ setSliderSizeAndPosition()
1745
+ end
1746
+
1747
+ local function highLowRecheck()
1748
+ local oldLowY = lowY
1749
+ local oldHighY = highY
1750
+ lowY = nil
1751
+ highY = nil
1752
+ resetHighLow()
1753
+
1754
+ if (lowY ~= oldLowY) or (highY ~= oldHighY) then
1755
+ setSliderSizeAndPosition()
1756
+ end
1757
+ end
1758
+
1759
+ local function descendantChanged(this, prop)
1760
+ if internalChange then return end
1761
+ if not this.Visible then return end
1762
+
1763
+ if prop == "Size" or prop == "Position" then
1764
+ wait()
1765
+ highLowRecheck()
1766
+ end
1767
+ end
1768
+
1769
+ scrollingFrame.DescendantAdded:Connect(function(instance)
1770
+ if not instance:IsA("GuiObject") then return end
1771
+
1772
+ if instance.Visible then
1773
+ wait() -- wait a heartbeat for sizes to reconfig
1774
+ highLowRecheck()
1775
+ end
1776
+
1777
+ descendantsChangeConMap[instance] = instance.Changed:Connect(function(prop) descendantChanged(instance, prop) end)
1778
+ end)
1779
+
1780
+ scrollingFrame.DescendantRemoving:Connect(function(instance)
1781
+ if not instance:IsA("GuiObject") then return end
1782
+ if descendantsChangeConMap[instance] then
1783
+ descendantsChangeConMap[instance]:Disconnect()
1784
+ descendantsChangeConMap[instance] = nil
1785
+ end
1786
+ wait() -- wait a heartbeat for sizes to reconfig
1787
+ highLowRecheck()
1788
+ end)
1789
+
1790
+ scrollingFrame.Changed:Connect(function(prop)
1791
+ if prop == "AbsoluteSize" then
1792
+ if not highY or not lowY then return end
1793
+
1794
+ highLowRecheck()
1795
+ setSliderSizeAndPosition()
1796
+ end
1797
+ end)
1798
+
1799
+ return scrollingFrame, controlFrame
1800
+ end
1801
+
1802
+ t.CreateScrollingFrame = function(orderList,scrollStyle)
1803
+ local frame = Instance.new("Frame")
1804
+ frame.Name = "ScrollingFrame"
1805
+ frame.BackgroundTransparency = 1
1806
+ frame.Size = UDim2.new(1,0,1,0)
1807
+
1808
+ local scrollUpButton = Instance.new("ImageButton")
1809
+ scrollUpButton.Name = "ScrollUpButton"
1810
+ scrollUpButton.BackgroundTransparency = 1
1811
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
1812
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
1813
+
1814
+
1815
+ local scrollDownButton = Instance.new("ImageButton")
1816
+ scrollDownButton.Name = "ScrollDownButton"
1817
+ scrollDownButton.BackgroundTransparency = 1
1818
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
1819
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
1820
+
1821
+ local scrollbar = Instance.new("ImageButton")
1822
+ scrollbar.Name = "ScrollBar"
1823
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
1824
+ scrollbar.BackgroundTransparency = 1
1825
+ scrollbar.Size = UDim2.new(0, 18, 0, 150)
1826
+
1827
+ local scrollStamp = 0
1828
+
1829
+ local scrollDrag = Instance.new("ImageButton")
1830
+ scrollDrag.Image = "https://www.roblox.com/asset/?id=61367186"
1831
+ scrollDrag.Size = UDim2.new(1, 0, 0, 16)
1832
+ scrollDrag.BackgroundTransparency = 1
1833
+ scrollDrag.Name = "ScrollDrag"
1834
+ scrollDrag.Active = true
1835
+ scrollDrag.Parent = scrollbar
1836
+
1837
+ local mouseDrag = Instance.new("ImageButton")
1838
+ mouseDrag.Active = false
1839
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
1840
+ mouseDrag.AutoButtonColor = false
1841
+ mouseDrag.BackgroundTransparency = 1
1842
+ mouseDrag.Name = "mouseDrag"
1843
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
1844
+ mouseDrag.ZIndex = 10
1845
+
1846
+ local style = "simple"
1847
+ if scrollStyle and tostring(scrollStyle) then
1848
+ style = scrollStyle
1849
+ end
1850
+
1851
+ local scrollPosition = 1
1852
+ local rowSize = 0
1853
+ local howManyDisplayed = 0
1854
+
1855
+ local layoutGridScrollBar = function()
1856
+ howManyDisplayed = 0
1857
+ local guiObjects = {}
1858
+ if orderList then
1859
+ for i, child in ipairs(orderList) do
1860
+ if child.Parent == frame then
1861
+ table.insert(guiObjects, child)
1862
+ end
1863
+ end
1864
+ else
1865
+ local children = frame:GetChildren()
1866
+ if children then
1867
+ for i, child in ipairs(children) do
1868
+ if child:IsA("GuiObject") then
1869
+ table.insert(guiObjects, child)
1870
+ end
1871
+ end
1872
+ end
1873
+ end
1874
+ if #guiObjects == 0 then
1875
+ scrollUpButton.Active = false
1876
+ scrollDownButton.Active = false
1877
+ scrollDrag.Active = false
1878
+ scrollPosition = 1
1879
+ return
1880
+ end
1881
+
1882
+ if scrollPosition > #guiObjects then
1883
+ scrollPosition = #guiObjects
1884
+ end
1885
+
1886
+ if scrollPosition < 1 then scrollPosition = 1 end
1887
+
1888
+ local totalPixelsY = frame.AbsoluteSize.Y
1889
+ local pixelsRemainingY = frame.AbsoluteSize.Y
1890
+
1891
+ local totalPixelsX = frame.AbsoluteSize.X
1892
+
1893
+ local xCounter = 0
1894
+ local rowSizeCounter = 0
1895
+ local setRowSize = true
1896
+
1897
+ local pixelsBelowScrollbar = 0
1898
+ local pos = #guiObjects
1899
+
1900
+ local currentRowY = 0
1901
+
1902
+ pos = scrollPosition
1903
+ --count up from current scroll position to fill out grid
1904
+ while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
1905
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
1906
+ --previous pos was the end of a row
1907
+ if xCounter >= totalPixelsX then
1908
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
1909
+ currentRowY = 0
1910
+ xCounter = guiObjects[pos].AbsoluteSize.X
1911
+ end
1912
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
1913
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
1914
+ end
1915
+ pos = pos + 1
1916
+ end
1917
+ --Count wherever current row left off
1918
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
1919
+ currentRowY = 0
1920
+
1921
+ pos = scrollPosition - 1
1922
+ xCounter = 0
1923
+
1924
+ --objects with varying X,Y dimensions can rarely cause minor errors
1925
+ --rechecking every new scrollPosition is necessary to avoid 100% of errors
1926
+
1927
+ --count backwards from current scrollPosition to see if we can add more rows
1928
+ while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
1929
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
1930
+ rowSizeCounter = rowSizeCounter + 1
1931
+ if xCounter >= totalPixelsX then
1932
+ rowSize = rowSizeCounter - 1
1933
+ rowSizeCounter = 0
1934
+ xCounter = guiObjects[pos].AbsoluteSize.X
1935
+ if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
1936
+ --It fits, so back up our scroll position
1937
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
1938
+ if scrollPosition <= rowSize then
1939
+ scrollPosition = 1
1940
+ break
1941
+ else
1942
+ scrollPosition = scrollPosition - rowSize
1943
+ end
1944
+ currentRowY = 0
1945
+ else
1946
+ break
1947
+ end
1948
+ end
1949
+
1950
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
1951
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
1952
+ end
1953
+
1954
+ pos = pos - 1
1955
+ end
1956
+
1957
+ --Do check last time if pos = 0
1958
+ if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
1959
+ scrollPosition = 1
1960
+ end
1961
+
1962
+ xCounter = 0
1963
+ --pos = scrollPosition
1964
+ rowSizeCounter = 0
1965
+ setRowSize = true
1966
+ local lastChildSize = 0
1967
+
1968
+ local xOffset,yOffset = 0
1969
+ if guiObjects[1] then
1970
+ yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
1971
+ xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
1972
+ end
1973
+
1974
+ for i, child in ipairs(guiObjects) do
1975
+ if i < scrollPosition then
1976
+ child.Visible = false
1977
+ else
1978
+ if pixelsRemainingY < 0 then
1979
+ child.Visible = false
1980
+ else
1981
+ --GuiObject
1982
+ if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
1983
+ if xCounter + child.AbsoluteSize.X >= totalPixelsX then
1984
+ if setRowSize then
1985
+ rowSize = rowSizeCounter - 1
1986
+ setRowSize = false
1987
+ end
1988
+ xCounter = 0
1989
+ pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
1990
+ end
1991
+ child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
1992
+ xCounter = xCounter + child.AbsoluteSize.X
1993
+ child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
1994
+ if child.Visible then
1995
+ howManyDisplayed = howManyDisplayed + 1
1996
+ end
1997
+ lastChildSize = child.AbsoluteSize
1998
+ end
1999
+ end
2000
+ end
2001
+
2002
+ scrollUpButton.Active = (scrollPosition > 1)
2003
+ if lastChildSize == 0 then
2004
+ scrollDownButton.Active = false
2005
+ else
2006
+ scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
2007
+ end
2008
+ scrollDrag.Active = #guiObjects > howManyDisplayed
2009
+ scrollDrag.Visible = scrollDrag.Active
2010
+ end
2011
+
2012
+
2013
+
2014
+ local layoutSimpleScrollBar = function()
2015
+ local guiObjects = {}
2016
+ howManyDisplayed = 0
2017
+
2018
+ if orderList then
2019
+ for i, child in ipairs(orderList) do
2020
+ if child.Parent == frame then
2021
+ table.insert(guiObjects, child)
2022
+ end
2023
+ end
2024
+ else
2025
+ local children = frame:GetChildren()
2026
+ if children then
2027
+ for i, child in ipairs(children) do
2028
+ if child:IsA("GuiObject") then
2029
+ table.insert(guiObjects, child)
2030
+ end
2031
+ end
2032
+ end
2033
+ end
2034
+ if #guiObjects == 0 then
2035
+ scrollUpButton.Active = false
2036
+ scrollDownButton.Active = false
2037
+ scrollDrag.Active = false
2038
+ scrollPosition = 1
2039
+ return
2040
+ end
2041
+
2042
+ if scrollPosition > #guiObjects then
2043
+ scrollPosition = #guiObjects
2044
+ end
2045
+
2046
+ local totalPixels = frame.AbsoluteSize.Y
2047
+ local pixelsRemaining = frame.AbsoluteSize.Y
2048
+
2049
+ local pixelsBelowScrollbar = 0
2050
+ local pos = #guiObjects
2051
+ while pixelsBelowScrollbar < totalPixels and pos >= 1 do
2052
+ if pos >= scrollPosition then
2053
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
2054
+ else
2055
+ if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
2056
+ --It fits, so back up our scroll position
2057
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
2058
+ if scrollPosition <= 1 then
2059
+ scrollPosition = 1
2060
+ break
2061
+ else
2062
+ --local ("Backing up ScrollPosition from -- " ..scrollPosition)
2063
+ scrollPosition = scrollPosition - 1
2064
+ end
2065
+ else
2066
+ break
2067
+ end
2068
+ end
2069
+ pos = pos - 1
2070
+ end
2071
+
2072
+ pos = scrollPosition
2073
+ for i, child in ipairs(guiObjects) do
2074
+ if i < scrollPosition then
2075
+ child.Visible = false
2076
+ else
2077
+ if pixelsRemaining < 0 then
2078
+ child.Visible = false
2079
+ else
2080
+ --GuiObject
2081
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
2082
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
2083
+ if (pixelsRemaining >= 0) then
2084
+ child.Visible = true
2085
+ howManyDisplayed = howManyDisplayed + 1
2086
+ else
2087
+ child.Visible = false
2088
+ end
2089
+ end
2090
+ end
2091
+ end
2092
+ scrollUpButton.Active = (scrollPosition > 1)
2093
+ scrollDownButton.Active = (pixelsRemaining < 0)
2094
+ scrollDrag.Active = #guiObjects > howManyDisplayed
2095
+ scrollDrag.Visible = scrollDrag.Active
2096
+ end
2097
+
2098
+
2099
+ local moveDragger = function()
2100
+ local guiObjects = 0
2101
+ local children = frame:GetChildren()
2102
+ if children then
2103
+ for i, child in ipairs(children) do
2104
+ if child:IsA("GuiObject") then
2105
+ guiObjects = guiObjects + 1
2106
+ end
2107
+ end
2108
+ end
2109
+
2110
+ if not scrollDrag.Parent then return end
2111
+
2112
+ local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
2113
+ if dragSizeY < 16 then dragSizeY = 16 end
2114
+ scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
2115
+
2116
+ local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
2117
+ if relativeYPos > 1 then relativeYPos = 1
2118
+ elseif relativeYPos < 0 then relativeYPos = 0 end
2119
+ local absYPos = 0
2120
+
2121
+ if relativeYPos ~= 0 then
2122
+ absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
2123
+ end
2124
+
2125
+ scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
2126
+ end
2127
+
2128
+ local reentrancyGuard = false
2129
+ local recalculate = function()
2130
+ if reentrancyGuard then
2131
+ return
2132
+ end
2133
+ reentrancyGuard = true
2134
+ wait()
2135
+ local success, err = nil
2136
+ if style == "grid" then
2137
+ success, err = pcall(function() layoutGridScrollBar() end)
2138
+ elseif style == "simple" then
2139
+ success, err = pcall(function() layoutSimpleScrollBar() end)
2140
+ end
2141
+ if not success then print(err) end
2142
+ moveDragger()
2143
+ reentrancyGuard = false
2144
+ end
2145
+
2146
+ local doScrollUp = function()
2147
+ scrollPosition = (scrollPosition) - rowSize
2148
+ if scrollPosition < 1 then scrollPosition = 1 end
2149
+ recalculate(nil)
2150
+ end
2151
+
2152
+ local doScrollDown = function()
2153
+ scrollPosition = (scrollPosition) + rowSize
2154
+ recalculate(nil)
2155
+ end
2156
+
2157
+ local scrollUp = function(mouseYPos)
2158
+ if scrollUpButton.Active then
2159
+ scrollStamp = tick()
2160
+ local current = scrollStamp
2161
+ local upCon
2162
+ upCon = mouseDrag.MouseButton1Up:Connect(function()
2163
+ scrollStamp = tick()
2164
+ mouseDrag.Parent = nil
2165
+ upCon:Disconnect()
2166
+ end)
2167
+ mouseDrag.Parent = getLayerCollectorAncestor(scrollbar)
2168
+ doScrollUp()
2169
+ wait(0.2)
2170
+ local t = tick()
2171
+ local w = 0.1
2172
+ while scrollStamp == current do
2173
+ doScrollUp()
2174
+ if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
2175
+ break
2176
+ end
2177
+ if not scrollUpButton.Active then break end
2178
+ if tick()-t > 5 then
2179
+ w = 0
2180
+ elseif tick()-t > 2 then
2181
+ w = 0.06
2182
+ end
2183
+ wait(w)
2184
+ end
2185
+ end
2186
+ end
2187
+
2188
+ local scrollDown = function(mouseYPos)
2189
+ if scrollDownButton.Active then
2190
+ scrollStamp = tick()
2191
+ local current = scrollStamp
2192
+ local downCon
2193
+ downCon = mouseDrag.MouseButton1Up:Connect(function()
2194
+ scrollStamp = tick()
2195
+ mouseDrag.Parent = nil
2196
+ downCon:Disconnect()
2197
+ end)
2198
+ mouseDrag.Parent = getLayerCollectorAncestor(scrollbar)
2199
+ doScrollDown()
2200
+ wait(0.2)
2201
+ local t = tick()
2202
+ local w = 0.1
2203
+ while scrollStamp == current do
2204
+ doScrollDown()
2205
+ if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
2206
+ break
2207
+ end
2208
+ if not scrollDownButton.Active then break end
2209
+ if tick()-t > 5 then
2210
+ w = 0
2211
+ elseif tick()-t > 2 then
2212
+ w = 0.06
2213
+ end
2214
+ wait(w)
2215
+ end
2216
+ end
2217
+ end
2218
+
2219
+ local y = 0
2220
+ scrollDrag.MouseButton1Down:Connect(function(x,y)
2221
+ if scrollDrag.Active then
2222
+ scrollStamp = tick()
2223
+ local mouseOffset = y - scrollDrag.AbsolutePosition.y
2224
+ local dragCon
2225
+ local upCon
2226
+ dragCon = mouseDrag.MouseMoved:Connect(function(x,y)
2227
+ local barAbsPos = scrollbar.AbsolutePosition.y
2228
+ local barAbsSize = scrollbar.AbsoluteSize.y
2229
+
2230
+ local dragAbsSize = scrollDrag.AbsoluteSize.y
2231
+ local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
2232
+ y = y - mouseOffset
2233
+ y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
2234
+ y = y - barAbsPos
2235
+
2236
+ local guiObjects = 0
2237
+ local children = frame:GetChildren()
2238
+ if children then
2239
+ for i, child in ipairs(children) do
2240
+ if child:IsA("GuiObject") then
2241
+ guiObjects = guiObjects + 1
2242
+ end
2243
+ end
2244
+ end
2245
+
2246
+ local doublePercent = y/(barAbsSize-dragAbsSize)
2247
+ local rowDiff = rowSize
2248
+ local totalScrollCount = guiObjects - (howManyDisplayed - 1)
2249
+ local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
2250
+ if newScrollPosition < scrollPosition then
2251
+ rowDiff = -rowDiff
2252
+ end
2253
+
2254
+ if newScrollPosition < 1 then
2255
+ newScrollPosition = 1
2256
+ end
2257
+
2258
+ scrollPosition = newScrollPosition
2259
+ recalculate(nil)
2260
+ end)
2261
+ upCon = mouseDrag.MouseButton1Up:Connect(function()
2262
+ scrollStamp = tick()
2263
+ mouseDrag.Parent = nil
2264
+ dragCon:Disconnect(); dragCon = nil
2265
+ upCon:Disconnect(); drag = nil
2266
+ end)
2267
+ mouseDrag.Parent = getLayerCollectorAncestor(scrollbar)
2268
+ end
2269
+ end)
2270
+
2271
+ local scrollMouseCount = 0
2272
+
2273
+ scrollUpButton.MouseButton1Down:Connect(
2274
+ function()
2275
+ scrollUp()
2276
+ end)
2277
+ scrollUpButton.MouseButton1Up:Connect(function()
2278
+ scrollStamp = tick()
2279
+ end)
2280
+
2281
+
2282
+ scrollDownButton.MouseButton1Up:Connect(function()
2283
+ scrollStamp = tick()
2284
+ end)
2285
+ scrollDownButton.MouseButton1Down:Connect(
2286
+ function()
2287
+ scrollDown()
2288
+ end)
2289
+
2290
+ scrollbar.MouseButton1Up:Connect(function()
2291
+ scrollStamp = tick()
2292
+ end)
2293
+ scrollbar.MouseButton1Down:Connect(
2294
+ function(x,y)
2295
+ if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
2296
+ scrollDown(y)
2297
+ elseif y < (scrollDrag.AbsolutePosition.y) then
2298
+ scrollUp(y)
2299
+ end
2300
+ end)
2301
+
2302
+
2303
+ frame.ChildAdded:Connect(function()
2304
+ recalculate(nil)
2305
+ end)
2306
+
2307
+ frame.ChildRemoved:Connect(function()
2308
+ recalculate(nil)
2309
+ end)
2310
+
2311
+ frame.Changed:Connect(
2312
+ function(prop)
2313
+ if prop == "AbsoluteSize" then
2314
+ --Wait a heartbeat for it to sync in
2315
+ recalculate(nil)
2316
+ end
2317
+ end)
2318
+ frame.AncestryChanged:Connect(function() recalculate(nil) end)
2319
+
2320
+ return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
2321
+ end
2322
+ local function binaryGrow(min, max, fits)
2323
+ if min > max then
2324
+ return min
2325
+ end
2326
+ local biggestLegal = min
2327
+
2328
+ while min <= max do
2329
+ local mid = min + math.floor((max - min) / 2)
2330
+ if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
2331
+ biggestLegal = mid
2332
+
2333
+ --Try growing
2334
+ min = mid + 1
2335
+ else
2336
+ --Doesn't fit, shrink
2337
+ max = mid - 1
2338
+ end
2339
+ end
2340
+ return biggestLegal
2341
+ end
2342
+
2343
+
2344
+ local function binaryShrink(min, max, fits)
2345
+ if min > max then
2346
+ return min
2347
+ end
2348
+ local smallestLegal = max
2349
+
2350
+ while min <= max do
2351
+ local mid = min + math.floor((max - min) / 2)
2352
+ if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
2353
+ smallestLegal = mid
2354
+
2355
+ --It fits, shrink
2356
+ max = mid - 1
2357
+ else
2358
+ --Doesn't fit, grow
2359
+ min = mid + 1
2360
+ end
2361
+ end
2362
+ return smallestLegal
2363
+ end
2364
+
2365
+
2366
+ local function getGuiOwner(instance)
2367
+ while instance ~= nil do
2368
+ if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
2369
+ return instance
2370
+ end
2371
+ instance = instance.Parent
2372
+ end
2373
+ return nil
2374
+ end
2375
+
2376
+ t.AutoTruncateTextObject = function(textLabel)
2377
+ local text = textLabel.Text
2378
+
2379
+ local fullLabel = textLabel:Clone()
2380
+ fullLabel.Name = "Full" .. textLabel.Name
2381
+ fullLabel.BorderSizePixel = 0
2382
+ fullLabel.BackgroundTransparency = 0
2383
+ fullLabel.Text = text
2384
+ fullLabel.TextXAlignment = Enum.TextXAlignment.Center
2385
+ fullLabel.Position = UDim2.new(0,-3,0,0)
2386
+ fullLabel.Size = UDim2.new(0,100,1,0)
2387
+ fullLabel.Visible = false
2388
+ fullLabel.Parent = textLabel
2389
+
2390
+ local shortText = nil
2391
+ local mouseEnterConnection = nil
2392
+ local mouseLeaveConnection= nil
2393
+
2394
+ local checkForResize = function()
2395
+ if getGuiOwner(textLabel) == nil then
2396
+ return
2397
+ end
2398
+ textLabel.Text = text
2399
+ if textLabel.TextFits then
2400
+ --Tear down the rollover if it is active
2401
+ if mouseEnterConnection then
2402
+ mouseEnterConnection:Disconnect()
2403
+ mouseEnterConnection = nil
2404
+ end
2405
+ if mouseLeaveConnection then
2406
+ mouseLeaveConnection:Disconnect()
2407
+ mouseLeaveConnection = nil
2408
+ end
2409
+ else
2410
+ local len = string.len(text)
2411
+ textLabel.Text = text .. "~"
2412
+
2413
+ --Shrink the text
2414
+ local textSize = binaryGrow(0, len,
2415
+ function(pos)
2416
+ if pos == 0 then
2417
+ textLabel.Text = "~"
2418
+ else
2419
+ textLabel.Text = string.sub(text, 1, pos) .. "~"
2420
+ end
2421
+ return textLabel.TextFits
2422
+ end)
2423
+ shortText = string.sub(text, 1, textSize) .. "~"
2424
+ textLabel.Text = shortText
2425
+
2426
+ --Make sure the fullLabel fits
2427
+ if not fullLabel.TextFits then
2428
+ --Already too small, grow it really bit to start
2429
+ fullLabel.Size = UDim2.new(0, 10000, 1, 0)
2430
+ end
2431
+
2432
+ --Okay, now try to binary shrink it back down
2433
+ local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
2434
+ function(size)
2435
+ fullLabel.Size = UDim2.new(0, size, 1, 0)
2436
+ return fullLabel.TextFits
2437
+ end)
2438
+ fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
2439
+
2440
+ --Now setup the rollover effects, if they are currently off
2441
+ if mouseEnterConnection == nil then
2442
+ mouseEnterConnection = textLabel.MouseEnter:Connect(
2443
+ function()
2444
+ fullLabel.ZIndex = textLabel.ZIndex + 1
2445
+ fullLabel.Visible = true
2446
+ --textLabel.Text = ""
2447
+ end)
2448
+ end
2449
+ if mouseLeaveConnection == nil then
2450
+ mouseLeaveConnection = textLabel.MouseLeave:Connect(
2451
+ function()
2452
+ fullLabel.Visible = false
2453
+ --textLabel.Text = shortText
2454
+ end)
2455
+ end
2456
+ end
2457
+ end
2458
+ textLabel.AncestryChanged:Connect(checkForResize)
2459
+ textLabel.Changed:Connect(
2460
+ function(prop)
2461
+ if prop == "AbsoluteSize" then
2462
+ checkForResize()
2463
+ end
2464
+ end)
2465
+
2466
+ checkForResize()
2467
+
2468
+ local function changeText(newText)
2469
+ text = newText
2470
+ fullLabel.Text = text
2471
+ checkForResize()
2472
+ end
2473
+
2474
+ return textLabel, changeText
2475
+ end
2476
+
2477
+ local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
2478
+ if fromPage then
2479
+ fromPage.Visible = false
2480
+ if transitionFrame.Visible == false then
2481
+ transitionFrame.Size = fromPage.Size
2482
+ transitionFrame.Position = fromPage.Position
2483
+ end
2484
+ else
2485
+ if transitionFrame.Visible == false then
2486
+ transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
2487
+ transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
2488
+ end
2489
+ end
2490
+ transitionFrame.Visible = true
2491
+ currentPageValue.Value = nil
2492
+
2493
+ local newSize, newPosition
2494
+ if toPage then
2495
+ --Make it visible so it resizes
2496
+ toPage.Visible = true
2497
+
2498
+ newSize = toPage.Size
2499
+ newPosition = toPage.Position
2500
+
2501
+ toPage.Visible = false
2502
+ else
2503
+ newSize = UDim2.new(0.0,50,0.0,50)
2504
+ newPosition = UDim2.new(0.5,-25,0.5,-25)
2505
+ end
2506
+ transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
2507
+ function(state)
2508
+ if state == Enum.TweenStatus.Completed then
2509
+ transitionFrame.Visible = false
2510
+ if toPage then
2511
+ toPage.Visible = true
2512
+ currentPageValue.Value = toPage
2513
+ end
2514
+ end
2515
+ end)
2516
+ end
2517
+
2518
+ t.CreateTutorial = function(name, tutorialKey, createButtons)
2519
+ local frame = Instance.new("Frame")
2520
+ frame.Name = "Tutorial-" .. name
2521
+ frame.BackgroundTransparency = 1
2522
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
2523
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
2524
+
2525
+ local transitionFrame = Instance.new("Frame")
2526
+ transitionFrame.Name = "TransitionFrame"
2527
+ transitionFrame.Style = Enum.FrameStyle.RobloxRound
2528
+ transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
2529
+ transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
2530
+ transitionFrame.Visible = false
2531
+ transitionFrame.Parent = frame
2532
+
2533
+ local currentPageValue = Instance.new("ObjectValue")
2534
+ currentPageValue.Name = "CurrentTutorialPage"
2535
+ currentPageValue.Value = nil
2536
+ currentPageValue.Parent = frame
2537
+
2538
+ local boolValue = Instance.new("BoolValue")
2539
+ boolValue.Name = "Buttons"
2540
+ boolValue.Value = createButtons
2541
+ boolValue.Parent = frame
2542
+
2543
+ local pages = Instance.new("Frame")
2544
+ pages.Name = "Pages"
2545
+ pages.BackgroundTransparency = 1
2546
+ pages.Size = UDim2.new(1,0,1,0)
2547
+ pages.Parent = frame
2548
+
2549
+ local function getVisiblePageAndHideOthers()
2550
+ local visiblePage = nil
2551
+ local children = pages:GetChildren()
2552
+ if children then
2553
+ for i,child in ipairs(children) do
2554
+ if child.Visible then
2555
+ if visiblePage then
2556
+ child.Visible = false
2557
+ else
2558
+ visiblePage = child
2559
+ end
2560
+ end
2561
+ end
2562
+ end
2563
+ return visiblePage
2564
+ end
2565
+
2566
+ local showTutorial = function(alwaysShow)
2567
+ if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
2568
+ print("Showing tutorial-",tutorialKey)
2569
+ local currentTutorialPage = getVisiblePageAndHideOthers()
2570
+
2571
+ local firstPage = pages:FindFirstChild("TutorialPage1")
2572
+ if firstPage then
2573
+ TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
2574
+ else
2575
+ error("Could not find TutorialPage1")
2576
+ end
2577
+ end
2578
+ end
2579
+
2580
+ local dismissTutorial = function()
2581
+ local currentTutorialPage = getVisiblePageAndHideOthers()
2582
+
2583
+ if currentTutorialPage then
2584
+ TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
2585
+ end
2586
+
2587
+ UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
2588
+ end
2589
+
2590
+ local gotoPage = function(pageNum)
2591
+ local page = pages:FindFirstChild("TutorialPage" .. pageNum)
2592
+ local currentTutorialPage = getVisiblePageAndHideOthers()
2593
+ TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
2594
+ end
2595
+
2596
+ return frame, showTutorial, dismissTutorial, gotoPage
2597
+ end
2598
+
2599
+ local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
2600
+ local frame = Instance.new("Frame")
2601
+ frame.Name = "TutorialPage"
2602
+ frame.Style = Enum.FrameStyle.RobloxRound
2603
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
2604
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
2605
+ frame.Visible = false
2606
+
2607
+ local frameHeader = Instance.new("TextLabel")
2608
+ frameHeader.Name = "Header"
2609
+ frameHeader.Text = name
2610
+ frameHeader.BackgroundTransparency = 1
2611
+ frameHeader.FontSize = Enum.FontSize.Size24
2612
+ frameHeader.Font = Enum.Font.ArialBold
2613
+ frameHeader.TextColor3 = Color3.new(1,1,1)
2614
+ frameHeader.TextXAlignment = Enum.TextXAlignment.Center
2615
+ frameHeader.TextWrap = true
2616
+ frameHeader.Size = UDim2.new(1,-55, 0, 22)
2617
+ frameHeader.Position = UDim2.new(0,0,0,0)
2618
+ frameHeader.Parent = frame
2619
+
2620
+ local skipButton = Instance.new("ImageButton")
2621
+ skipButton.Name = "SkipButton"
2622
+ skipButton.AutoButtonColor = false
2623
+ skipButton.BackgroundTransparency = 1
2624
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
2625
+ skipButton.MouseButton1Click:Connect(function()
2626
+ skipTutorial()
2627
+ end)
2628
+ skipButton.MouseEnter:Connect(function()
2629
+ skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
2630
+ end)
2631
+ skipButton.MouseLeave:Connect(function()
2632
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
2633
+ end)
2634
+ skipButton.Size = UDim2.new(0, 25, 0, 25)
2635
+ skipButton.Position = UDim2.new(1, -25, 0, 0)
2636
+ skipButton.Parent = frame
2637
+
2638
+
2639
+ if giveDoneButton then
2640
+ local doneButton = Instance.new("TextButton")
2641
+ doneButton.Name = "DoneButton"
2642
+ doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
2643
+ doneButton.Text = "Done"
2644
+ doneButton.TextColor3 = Color3.new(1,1,1)
2645
+ doneButton.Font = Enum.Font.ArialBold
2646
+ doneButton.FontSize = Enum.FontSize.Size18
2647
+ doneButton.Size = UDim2.new(0,100,0,50)
2648
+ doneButton.Position = UDim2.new(0.5,-50,1,-50)
2649
+
2650
+ if skipTutorial then
2651
+ doneButton.MouseButton1Click:Connect(function() skipTutorial() end)
2652
+ end
2653
+
2654
+ doneButton.Parent = frame
2655
+ end
2656
+
2657
+ local innerFrame = Instance.new("Frame")
2658
+ innerFrame.Name = "ContentFrame"
2659
+ innerFrame.BackgroundTransparency = 1
2660
+ innerFrame.Position = UDim2.new(0,0,0,25)
2661
+ innerFrame.Parent = frame
2662
+
2663
+ local nextButton = Instance.new("TextButton")
2664
+ nextButton.Name = "NextButton"
2665
+ nextButton.Text = "Next"
2666
+ nextButton.TextColor3 = Color3.new(1,1,1)
2667
+ nextButton.Font = Enum.Font.Arial
2668
+ nextButton.FontSize = Enum.FontSize.Size18
2669
+ nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
2670
+ nextButton.Size = UDim2.new(0,80, 0, 32)
2671
+ nextButton.Position = UDim2.new(0.5, 5, 1, -32)
2672
+ nextButton.Active = false
2673
+ nextButton.Visible = false
2674
+ nextButton.Parent = frame
2675
+
2676
+ local prevButton = Instance.new("TextButton")
2677
+ prevButton.Name = "PrevButton"
2678
+ prevButton.Text = "Previous"
2679
+ prevButton.TextColor3 = Color3.new(1,1,1)
2680
+ prevButton.Font = Enum.Font.Arial
2681
+ prevButton.FontSize = Enum.FontSize.Size18
2682
+ prevButton.Style = Enum.ButtonStyle.RobloxButton
2683
+ prevButton.Size = UDim2.new(0,80, 0, 32)
2684
+ prevButton.Position = UDim2.new(0.5, -85, 1, -32)
2685
+ prevButton.Active = false
2686
+ prevButton.Visible = false
2687
+ prevButton.Parent = frame
2688
+
2689
+ if giveDoneButton then
2690
+ innerFrame.Size = UDim2.new(1,0,1,-75)
2691
+ else
2692
+ innerFrame.Size = UDim2.new(1,0,1,-22)
2693
+ end
2694
+
2695
+ local parentConnection = nil
2696
+
2697
+ local function basicHandleResize()
2698
+ if frame.Visible and frame.Parent then
2699
+ local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
2700
+ handleResize(200,maxSize)
2701
+ end
2702
+ end
2703
+
2704
+ frame.Changed:Connect(
2705
+ function(prop)
2706
+ if prop == "Parent" then
2707
+ if parentConnection ~= nil then
2708
+ parentConnection:Disconnect()
2709
+ parentConnection = nil
2710
+ end
2711
+ if frame.Parent and frame.Parent:IsA("GuiObject") then
2712
+ parentConnection = frame.Parent.Changed:Connect(
2713
+ function(parentProp)
2714
+ if parentProp == "AbsoluteSize" then
2715
+ wait()
2716
+ basicHandleResize()
2717
+ end
2718
+ end)
2719
+ basicHandleResize()
2720
+ end
2721
+ end
2722
+
2723
+ if prop == "Visible" then
2724
+ basicHandleResize()
2725
+ end
2726
+ end)
2727
+
2728
+ return frame, innerFrame
2729
+ end
2730
+
2731
+ t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
2732
+ local frame = nil
2733
+ local contentFrame = nil
2734
+
2735
+ local textLabel = Instance.new("TextLabel")
2736
+ textLabel.BackgroundTransparency = 1
2737
+ textLabel.TextColor3 = Color3.new(1,1,1)
2738
+ textLabel.Text = text
2739
+ textLabel.TextWrap = true
2740
+ textLabel.TextXAlignment = Enum.TextXAlignment.Left
2741
+ textLabel.TextYAlignment = Enum.TextYAlignment.Center
2742
+ textLabel.Font = Enum.Font.Arial
2743
+ textLabel.FontSize = Enum.FontSize.Size14
2744
+ textLabel.Size = UDim2.new(1,0,1,0)
2745
+
2746
+ local function handleResize(minSize, maxSize)
2747
+ size = binaryShrink(minSize, maxSize,
2748
+ function(size)
2749
+ frame.Size = UDim2.new(0, size, 0, size)
2750
+ return textLabel.TextFits
2751
+ end)
2752
+ frame.Size = UDim2.new(0, size, 0, size)
2753
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
2754
+ end
2755
+
2756
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
2757
+ textLabel.Parent = contentFrame
2758
+
2759
+ return frame
2760
+ end
2761
+
2762
+ t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
2763
+ local frame = nil
2764
+ local contentFrame = nil
2765
+
2766
+ local imageLabel = Instance.new("ImageLabel")
2767
+ imageLabel.BackgroundTransparency = 1
2768
+ imageLabel.Image = imageAsset
2769
+ imageLabel.Size = UDim2.new(0,x,0,y)
2770
+ imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
2771
+
2772
+ local function handleResize(minSize, maxSize)
2773
+ size = binaryShrink(minSize, maxSize,
2774
+ function(size)
2775
+ return size >= x and size >= y
2776
+ end)
2777
+ if size >= x and size >= y then
2778
+ imageLabel.Size = UDim2.new(0,x, 0,y)
2779
+ imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
2780
+ else
2781
+ if x > y then
2782
+ --X is limiter, so
2783
+ imageLabel.Size = UDim2.new(1,0,y/x,0)
2784
+ imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
2785
+ else
2786
+ --Y is limiter
2787
+ imageLabel.Size = UDim2.new(x/y,0,1, 0)
2788
+ imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
2789
+ end
2790
+ end
2791
+ size = size + 50
2792
+ frame.Size = UDim2.new(0, size, 0, size)
2793
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
2794
+ end
2795
+
2796
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
2797
+ imageLabel.Parent = contentFrame
2798
+
2799
+ return frame
2800
+ end
2801
+
2802
+ t.AddTutorialPage = function(tutorial, tutorialPage)
2803
+ local transitionFrame = tutorial.TransitionFrame
2804
+ local currentPageValue = tutorial.CurrentTutorialPage
2805
+
2806
+ if not tutorial.Buttons.Value then
2807
+ tutorialPage.NextButton.Parent = nil
2808
+ tutorialPage.PrevButton.Parent = nil
2809
+ end
2810
+
2811
+ local children = tutorial.Pages:GetChildren()
2812
+ if children and #children > 0 then
2813
+ tutorialPage.Name = "TutorialPage" .. (#children+1)
2814
+ local previousPage = children[#children]
2815
+ if not previousPage:IsA("GuiObject") then
2816
+ error("All elements under Pages must be GuiObjects")
2817
+ end
2818
+
2819
+ if tutorial.Buttons.Value then
2820
+ if previousPage.NextButton.Active then
2821
+ error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
2822
+ end
2823
+ previousPage.NextButton.MouseButton1Click:Connect(
2824
+ function()
2825
+ TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
2826
+ end)
2827
+ previousPage.NextButton.Active = true
2828
+ previousPage.NextButton.Visible = true
2829
+
2830
+ if tutorialPage.PrevButton.Active then
2831
+ error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
2832
+ end
2833
+ tutorialPage.PrevButton.MouseButton1Click:Connect(
2834
+ function()
2835
+ TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
2836
+ end)
2837
+ tutorialPage.PrevButton.Active = true
2838
+ tutorialPage.PrevButton.Visible = true
2839
+ end
2840
+
2841
+ tutorialPage.Parent = tutorial.Pages
2842
+ else
2843
+ --First child
2844
+ tutorialPage.Name = "TutorialPage1"
2845
+ tutorialPage.Parent = tutorial.Pages
2846
+ end
2847
+ end
2848
+
2849
+ t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
2850
+
2851
+ if not userIdsForSets then
2852
+ error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
2853
+ end
2854
+ if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
2855
+ error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
2856
+ end
2857
+ if not objectSelected then
2858
+ error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
2859
+ end
2860
+ if type(objectSelected) ~= "function" then
2861
+ error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
2862
+ end
2863
+ if dialogClosed and type(dialogClosed) ~= "function" then
2864
+ error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
2865
+ end
2866
+
2867
+ if showAdminCategories == nil then -- by default, don't show beta sets
2868
+ showAdminCategories = false
2869
+ end
2870
+
2871
+ local arrayPosition = 1
2872
+ local insertButtons = {}
2873
+ local insertButtonCons = {}
2874
+ local contents = nil
2875
+ local setGui = nil
2876
+
2877
+ -- used for water selections
2878
+ local waterForceDirection = "NegX"
2879
+ local waterForce = "None"
2880
+ local waterGui, waterTypeChangedEvent = nil
2881
+
2882
+ local Data = {}
2883
+ Data.CurrentCategory = nil
2884
+ Data.Category = {}
2885
+ local SetCache = {}
2886
+
2887
+ local userCategoryButtons = nil
2888
+
2889
+ local buttonWidth = 64
2890
+ local buttonHeight = buttonWidth
2891
+
2892
+ local SmallThumbnailUrl = nil
2893
+ local LargeThumbnailUrl = nil
2894
+ local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
2895
+ local AssetGameUrl = string.gsub(BaseUrl, "www", "assetgame")
2896
+
2897
+ if useAssetVersionId then
2898
+ LargeThumbnailUrl = AssetGameUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
2899
+ SmallThumbnailUrl = AssetGameUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
2900
+ else
2901
+ LargeThumbnailUrl = AssetGameUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
2902
+ SmallThumbnailUrl = AssetGameUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
2903
+ end
2904
+
2905
+ local function drillDownSetZIndex(parent, index)
2906
+ local children = parent:GetChildren()
2907
+ for i = 1, #children do
2908
+ if children[i]:IsA("GuiObject") then
2909
+ children[i].ZIndex = index
2910
+ end
2911
+ drillDownSetZIndex(children[i], index)
2912
+ end
2913
+ end
2914
+
2915
+ -- for terrain stamping
2916
+ local currTerrainDropDownFrame = nil
2917
+ local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
2918
+ local terrainShapeMap = {}
2919
+ for i = 1, #terrainShapes do
2920
+ terrainShapeMap[terrainShapes[i]] = i - 1
2921
+ end
2922
+ terrainShapeMap[terrainShapes[#terrainShapes]] = 6
2923
+
2924
+ local function createWaterGui()
2925
+ local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
2926
+ local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
2927
+
2928
+ local waterFrame = Instance.new("Frame")
2929
+ waterFrame.Name = "WaterFrame"
2930
+ waterFrame.Style = Enum.FrameStyle.RobloxSquare
2931
+ waterFrame.Size = UDim2.new(0,150,0,110)
2932
+ waterFrame.Visible = false
2933
+
2934
+ local waterForceLabel = Instance.new("TextLabel")
2935
+ waterForceLabel.Name = "WaterForceLabel"
2936
+ waterForceLabel.BackgroundTransparency = 1
2937
+ waterForceLabel.Size = UDim2.new(1,0,0,12)
2938
+ waterForceLabel.Font = Enum.Font.ArialBold
2939
+ waterForceLabel.FontSize = Enum.FontSize.Size12
2940
+ waterForceLabel.TextColor3 = Color3.new(1,1,1)
2941
+ waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
2942
+ waterForceLabel.Text = "Water Force"
2943
+ waterForceLabel.Parent = waterFrame
2944
+
2945
+ local waterForceDirLabel = waterForceLabel:Clone()
2946
+ waterForceDirLabel.Name = "WaterForceDirectionLabel"
2947
+ waterForceDirLabel.Text = "Water Force Direction"
2948
+ waterForceDirLabel.Position = UDim2.new(0,0,0,50)
2949
+ waterForceDirLabel.Parent = waterFrame
2950
+
2951
+ local waterTypeChangedEvent = Instance.new("BindableEvent")
2952
+ waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
2953
+ waterTypeChangedEvent.Parent = waterFrame
2954
+
2955
+ local waterForceDirectionSelectedFunc = function(newForceDirection)
2956
+ waterForceDirection = newForceDirection
2957
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
2958
+ end
2959
+ local waterForceSelectedFunc = function(newForce)
2960
+ waterForce = newForce
2961
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
2962
+ end
2963
+
2964
+ local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
2965
+ waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
2966
+ waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
2967
+ forceWaterDirectionSelection("NegX")
2968
+ waterForceDirectionDropDown.Parent = waterForceDirLabel
2969
+
2970
+ local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
2971
+ forceWaterForceSelection("None")
2972
+ waterForceDropDown.Size = UDim2.new(1,0,0,25)
2973
+ waterForceDropDown.Position = UDim2.new(0,0,1,3)
2974
+ waterForceDropDown.Parent = waterForceLabel
2975
+
2976
+ return waterFrame, waterTypeChangedEvent
2977
+ end
2978
+
2979
+ -- Helper Function that contructs gui elements
2980
+ local function createSetGui()
2981
+
2982
+ local setGui = Instance.new("ScreenGui")
2983
+ setGui.Name = "SetGui"
2984
+
2985
+ local setPanel = Instance.new("Frame")
2986
+ setPanel.Name = "SetPanel"
2987
+ setPanel.Active = true
2988
+ setPanel.BackgroundTransparency = 1
2989
+ if position then
2990
+ setPanel.Position = position
2991
+ else
2992
+ setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
2993
+ end
2994
+ if size then
2995
+ setPanel.Size = size
2996
+ else
2997
+ setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
2998
+ end
2999
+ setPanel.Style = Enum.FrameStyle.RobloxRound
3000
+ setPanel.ZIndex = 6
3001
+ setPanel.Parent = setGui
3002
+
3003
+ -- Children of SetPanel
3004
+ local itemPreview = Instance.new("Frame")
3005
+ itemPreview.Name = "ItemPreview"
3006
+ itemPreview.BackgroundTransparency = 1
3007
+ itemPreview.Position = UDim2.new(0.8,5,0.085,0)
3008
+ itemPreview.Size = UDim2.new(0.21,0,0.9,0)
3009
+ itemPreview.ZIndex = 6
3010
+ itemPreview.Parent = setPanel
3011
+
3012
+ -- Children of ItemPreview
3013
+ local textPanel = Instance.new("Frame")
3014
+ textPanel.Name = "TextPanel"
3015
+ textPanel.BackgroundTransparency = 1
3016
+ textPanel.Position = UDim2.new(0,0,0.45,0)
3017
+ textPanel.Size = UDim2.new(1,0,0.55,0)
3018
+ textPanel.ZIndex = 6
3019
+ textPanel.Parent = itemPreview
3020
+
3021
+ -- Children of TextPanel
3022
+ local rolloverText = Instance.new("TextLabel")
3023
+ rolloverText.Name = "RolloverText"
3024
+ rolloverText.BackgroundTransparency = 1
3025
+ rolloverText.Size = UDim2.new(1,0,0,48)
3026
+ rolloverText.ZIndex = 6
3027
+ rolloverText.Font = Enum.Font.ArialBold
3028
+ rolloverText.FontSize = Enum.FontSize.Size24
3029
+ rolloverText.Text = ""
3030
+ rolloverText.TextColor3 = Color3.new(1,1,1)
3031
+ rolloverText.TextWrap = true
3032
+ rolloverText.TextXAlignment = Enum.TextXAlignment.Left
3033
+ rolloverText.TextYAlignment = Enum.TextYAlignment.Top
3034
+ rolloverText.Parent = textPanel
3035
+
3036
+ local largePreview = Instance.new("ImageLabel")
3037
+ largePreview.Name = "LargePreview"
3038
+ largePreview.BackgroundTransparency = 1
3039
+ largePreview.Image = ""
3040
+ largePreview.Size = UDim2.new(1,0,0,170)
3041
+ largePreview.ZIndex = 6
3042
+ largePreview.Parent = itemPreview
3043
+
3044
+ local sets = Instance.new("Frame")
3045
+ sets.Name = "Sets"
3046
+ sets.BackgroundTransparency = 1
3047
+ sets.Position = UDim2.new(0,0,0,5)
3048
+ sets.Size = UDim2.new(0.23,0,1,-5)
3049
+ sets.ZIndex = 6
3050
+ sets.Parent = setPanel
3051
+
3052
+ -- Children of Sets
3053
+ local line = Instance.new("Frame")
3054
+ line.Name = "Line"
3055
+ line.BackgroundColor3 = Color3.new(1,1,1)
3056
+ line.BackgroundTransparency = 0.7
3057
+ line.BorderSizePixel = 0
3058
+ line.Position = UDim2.new(1,-3,0.06,0)
3059
+ line.Size = UDim2.new(0,3,0.9,0)
3060
+ line.ZIndex = 6
3061
+ line.Parent = sets
3062
+
3063
+ local setsLists, controlFrame = t.CreateTrueScrollingFrame()
3064
+ setsLists.Size = UDim2.new(1,-6,0.94,0)
3065
+ setsLists.Position = UDim2.new(0,0,0.06,0)
3066
+ setsLists.BackgroundTransparency = 1
3067
+ setsLists.Name = "SetsLists"
3068
+ setsLists.ZIndex = 6
3069
+ setsLists.Parent = sets
3070
+ drillDownSetZIndex(controlFrame, 7)
3071
+
3072
+ local setsHeader = Instance.new("TextLabel")
3073
+ setsHeader.Name = "SetsHeader"
3074
+ setsHeader.BackgroundTransparency = 1
3075
+ setsHeader.Size = UDim2.new(0,47,0,24)
3076
+ setsHeader.ZIndex = 6
3077
+ setsHeader.Font = Enum.Font.ArialBold
3078
+ setsHeader.FontSize = Enum.FontSize.Size24
3079
+ setsHeader.Text = "Sets"
3080
+ setsHeader.TextColor3 = Color3.new(1,1,1)
3081
+ setsHeader.TextXAlignment = Enum.TextXAlignment.Left
3082
+ setsHeader.TextYAlignment = Enum.TextYAlignment.Top
3083
+ setsHeader.Parent = sets
3084
+
3085
+ local cancelButton = Instance.new("TextButton")
3086
+ cancelButton.Name = "CancelButton"
3087
+ cancelButton.Position = UDim2.new(1,-32,0,-2)
3088
+ cancelButton.Size = UDim2.new(0,34,0,34)
3089
+ cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
3090
+ cancelButton.ZIndex = 6
3091
+ cancelButton.Text = ""
3092
+ cancelButton.Modal = true
3093
+ cancelButton.Parent = setPanel
3094
+
3095
+ -- Children of Cancel Button
3096
+ local cancelImage = Instance.new("ImageLabel")
3097
+ cancelImage.Name = "CancelImage"
3098
+ cancelImage.BackgroundTransparency = 1
3099
+ cancelImage.Image = "https://www.roblox.com/asset/?id=54135717"
3100
+ cancelImage.Position = UDim2.new(0,-2,0,-2)
3101
+ cancelImage.Size = UDim2.new(0,16,0,16)
3102
+ cancelImage.ZIndex = 6
3103
+ cancelImage.Parent = cancelButton
3104
+
3105
+ return setGui
3106
+ end
3107
+
3108
+ local function createSetButton(text)
3109
+ local setButton = Instance.new("TextButton")
3110
+
3111
+ if text then setButton.Text = text
3112
+ else setButton.Text = "" end
3113
+
3114
+ setButton.AutoButtonColor = false
3115
+ setButton.BackgroundTransparency = 1
3116
+ setButton.BackgroundColor3 = Color3.new(1,1,1)
3117
+ setButton.BorderSizePixel = 0
3118
+ setButton.Size = UDim2.new(1,-5,0,18)
3119
+ setButton.ZIndex = 6
3120
+ setButton.Visible = false
3121
+ setButton.Font = Enum.Font.Arial
3122
+ setButton.FontSize = Enum.FontSize.Size18
3123
+ setButton.TextColor3 = Color3.new(1,1,1)
3124
+ setButton.TextXAlignment = Enum.TextXAlignment.Left
3125
+
3126
+ return setButton
3127
+ end
3128
+
3129
+ local function buildSetButton(name, setId, setImageId, i, count)
3130
+ local button = createSetButton(name)
3131
+ button.Text = name
3132
+ button.Name = "SetButton"
3133
+ button.Visible = true
3134
+
3135
+ local setValue = Instance.new("IntValue")
3136
+ setValue.Name = "SetId"
3137
+ setValue.Value = setId
3138
+ setValue.Parent = button
3139
+
3140
+ local setName = Instance.new("StringValue")
3141
+ setName.Name = "SetName"
3142
+ setName.Value = name
3143
+ setName.Parent = button
3144
+
3145
+ return button
3146
+ end
3147
+
3148
+ local function processCategory(sets)
3149
+ local setButtons = {}
3150
+ local numSkipped = 0
3151
+ for i = 1, #sets do
3152
+ if not showAdminCategories and sets[i].Name == "Beta" then
3153
+ numSkipped = numSkipped + 1
3154
+ else
3155
+ setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
3156
+ end
3157
+ end
3158
+ return setButtons
3159
+ end
3160
+
3161
+ local function handleResize()
3162
+ wait() -- neccessary to insure heartbeat happened
3163
+
3164
+ local itemPreview = setGui.SetPanel.ItemPreview
3165
+
3166
+ itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
3167
+ itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
3168
+ itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
3169
+ itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
3170
+ end
3171
+
3172
+ local function makeInsertAssetButton()
3173
+ local insertAssetButtonExample = Instance.new("Frame")
3174
+ insertAssetButtonExample.Name = "InsertAssetButtonExample"
3175
+ insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
3176
+ insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
3177
+ insertAssetButtonExample.BackgroundTransparency = 1
3178
+ insertAssetButtonExample.ZIndex = 6
3179
+ insertAssetButtonExample.Visible = false
3180
+
3181
+ local assetId = Instance.new("IntValue")
3182
+ assetId.Name = "AssetId"
3183
+ assetId.Value = 0
3184
+ assetId.Parent = insertAssetButtonExample
3185
+
3186
+ local assetName = Instance.new("StringValue")
3187
+ assetName.Name = "AssetName"
3188
+ assetName.Value = ""
3189
+ assetName.Parent = insertAssetButtonExample
3190
+
3191
+ local button = Instance.new("TextButton")
3192
+ button.Name = "Button"
3193
+ button.Text = ""
3194
+ button.Style = Enum.ButtonStyle.RobloxButton
3195
+ button.Position = UDim2.new(0.025,0,0.025,0)
3196
+ button.Size = UDim2.new(0.95,0,0.95,0)
3197
+ button.ZIndex = 6
3198
+ button.Parent = insertAssetButtonExample
3199
+
3200
+ local buttonImage = Instance.new("ImageLabel")
3201
+ buttonImage.Name = "ButtonImage"
3202
+ buttonImage.Image = ""
3203
+ buttonImage.Position = UDim2.new(0,-7,0,-7)
3204
+ buttonImage.Size = UDim2.new(1,14,1,14)
3205
+ buttonImage.BackgroundTransparency = 1
3206
+ buttonImage.ZIndex = 7
3207
+ buttonImage.Parent = button
3208
+
3209
+ local configIcon = buttonImage:clone()
3210
+ configIcon.Name = "ConfigIcon"
3211
+ configIcon.Visible = false
3212
+ configIcon.Position = UDim2.new(1,-23,1,-24)
3213
+ configIcon.Size = UDim2.new(0,16,0,16)
3214
+ configIcon.Image = ""
3215
+ configIcon.ZIndex = 6
3216
+ configIcon.Parent = insertAssetButtonExample
3217
+
3218
+ return insertAssetButtonExample
3219
+ end
3220
+
3221
+ local function showLargePreview(insertButton)
3222
+ if insertButton:FindFirstChild("AssetId") then
3223
+ delay(0,function()
3224
+ game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
3225
+ setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
3226
+ end)
3227
+ end
3228
+ if insertButton:FindFirstChild("AssetName") then
3229
+ setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
3230
+ end
3231
+ end
3232
+
3233
+ local function selectTerrainShape(shape)
3234
+ if currTerrainDropDownFrame then
3235
+ objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
3236
+ end
3237
+ end
3238
+
3239
+ local function createTerrainTypeButton(name, parent)
3240
+ local dropDownTextButton = Instance.new("TextButton")
3241
+ dropDownTextButton.Name = name .. "Button"
3242
+ dropDownTextButton.Font = Enum.Font.ArialBold
3243
+ dropDownTextButton.FontSize = Enum.FontSize.Size14
3244
+ dropDownTextButton.BorderSizePixel = 0
3245
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
3246
+ dropDownTextButton.Text = name
3247
+ dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
3248
+ dropDownTextButton.BackgroundTransparency = 1
3249
+ dropDownTextButton.ZIndex = parent.ZIndex + 1
3250
+ dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
3251
+ dropDownTextButton.Position = UDim2.new(0,1,0,0)
3252
+
3253
+ dropDownTextButton.MouseEnter:Connect(function()
3254
+ dropDownTextButton.BackgroundTransparency = 0
3255
+ dropDownTextButton.TextColor3 = Color3.new(0,0,0)
3256
+ end)
3257
+
3258
+ dropDownTextButton.MouseLeave:Connect(function()
3259
+ dropDownTextButton.BackgroundTransparency = 1
3260
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
3261
+ end)
3262
+
3263
+ dropDownTextButton.MouseButton1Click:Connect(function()
3264
+ dropDownTextButton.BackgroundTransparency = 1
3265
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
3266
+ if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
3267
+ dropDownTextButton.Parent.Visible = false
3268
+ end
3269
+ selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
3270
+ end)
3271
+
3272
+ return dropDownTextButton
3273
+ end
3274
+
3275
+ local function createTerrainDropDownMenu(zIndex)
3276
+ local dropDown = Instance.new("Frame")
3277
+ dropDown.Name = "TerrainDropDown"
3278
+ dropDown.BackgroundColor3 = Color3.new(0,0,0)
3279
+ dropDown.BorderColor3 = Color3.new(1,0,0)
3280
+ dropDown.Size = UDim2.new(0,200,0,0)
3281
+ dropDown.Visible = false
3282
+ dropDown.ZIndex = zIndex
3283
+ dropDown.Parent = setGui
3284
+
3285
+ for i = 1, #terrainShapes do
3286
+ local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
3287
+ shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
3288
+ shapeButton.Parent = dropDown
3289
+ dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
3290
+ end
3291
+
3292
+ dropDown.MouseLeave:Connect(function()
3293
+ dropDown.Visible = false
3294
+ end)
3295
+ end
3296
+
3297
+
3298
+ local function createDropDownMenuButton(parent)
3299
+ local dropDownButton = Instance.new("ImageButton")
3300
+ dropDownButton.Name = "DropDownButton"
3301
+ dropDownButton.Image = "https://www.roblox.com/asset/?id=67581509"
3302
+ dropDownButton.BackgroundTransparency = 1
3303
+ dropDownButton.Size = UDim2.new(0,16,0,16)
3304
+ dropDownButton.Position = UDim2.new(1,-24,0,6)
3305
+ dropDownButton.ZIndex = parent.ZIndex + 2
3306
+ dropDownButton.Parent = parent
3307
+
3308
+ if not setGui:FindFirstChild("TerrainDropDown") then
3309
+ createTerrainDropDownMenu(8)
3310
+ end
3311
+
3312
+ dropDownButton.MouseButton1Click:Connect(function()
3313
+ setGui.TerrainDropDown.Visible = true
3314
+ setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
3315
+ currTerrainDropDownFrame = parent
3316
+ end)
3317
+ end
3318
+
3319
+ local function buildInsertButton()
3320
+ local insertButton = makeInsertAssetButton()
3321
+ insertButton.Name = "InsertAssetButton"
3322
+ insertButton.Visible = true
3323
+
3324
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
3325
+ createDropDownMenuButton(insertButton)
3326
+ end
3327
+
3328
+ local lastEnter = nil
3329
+ local mouseEnterCon = insertButton.MouseEnter:Connect(function()
3330
+ lastEnter = insertButton
3331
+ delay(0.1,function()
3332
+ if lastEnter == insertButton then
3333
+ showLargePreview(insertButton)
3334
+ end
3335
+ end)
3336
+ end)
3337
+ return insertButton, mouseEnterCon
3338
+ end
3339
+
3340
+ local function realignButtonGrid(columns)
3341
+ local x = 0
3342
+ local y = 0
3343
+ for i = 1, #insertButtons do
3344
+ insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
3345
+ x = x + 1
3346
+ if x >= columns then
3347
+ x = 0
3348
+ y = y + 1
3349
+ end
3350
+ end
3351
+ end
3352
+
3353
+ local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
3354
+ if visible then
3355
+ insertFrame.AssetName.Value = name
3356
+ insertFrame.AssetId.Value = assetId
3357
+ local newImageUrl = SmallThumbnailUrl .. assetId
3358
+ if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
3359
+ delay(0,function()
3360
+ game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
3361
+ if insertFrame:findFirstChild("Button") then
3362
+ insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
3363
+ end
3364
+ end)
3365
+ end
3366
+ table.insert(insertButtonCons,
3367
+ insertFrame.Button.MouseButton1Click:Connect(function()
3368
+ -- special case for water, show water selection gui
3369
+ local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
3370
+ waterGui.Visible = isWaterSelected
3371
+ if isWaterSelected then
3372
+ objectSelected(name, tonumber(assetId), nil)
3373
+ else
3374
+ objectSelected(name, tonumber(assetId))
3375
+ end
3376
+ end)
3377
+ )
3378
+ insertFrame.Visible = true
3379
+ else
3380
+ insertFrame.Visible = false
3381
+ end
3382
+ end
3383
+
3384
+ local function loadSectionOfItems(setGui, rows, columns)
3385
+ local pageSize = rows * columns
3386
+
3387
+ if arrayPosition > #contents then return end
3388
+
3389
+ local origArrayPos = arrayPosition
3390
+
3391
+ local yCopy = 0
3392
+ for i = 1, pageSize + 1 do
3393
+ if arrayPosition >= #contents + 1 then
3394
+ break
3395
+ end
3396
+
3397
+ local buttonCon
3398
+ insertButtons[arrayPosition], buttonCon = buildInsertButton()
3399
+ table.insert(insertButtonCons,buttonCon)
3400
+ insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
3401
+ arrayPosition = arrayPosition + 1
3402
+ end
3403
+ realignButtonGrid(columns)
3404
+
3405
+ local indexCopy = origArrayPos
3406
+ for index = origArrayPos, arrayPosition do
3407
+ if insertButtons[index] then
3408
+ if contents[index] then
3409
+
3410
+ -- we don't want water to have a drop down button
3411
+ if contents[index].Name == "Water" then
3412
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
3413
+ insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
3414
+ end
3415
+ end
3416
+
3417
+ local assetId
3418
+ if useAssetVersionId then
3419
+ assetId = contents[index].AssetVersionId
3420
+ else
3421
+ assetId = contents[index].AssetId
3422
+ end
3423
+ setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
3424
+ else
3425
+ break
3426
+ end
3427
+ else
3428
+ break
3429
+ end
3430
+ indexCopy = index
3431
+ end
3432
+ end
3433
+
3434
+ local function setSetIndex()
3435
+ Data.Category[Data.CurrentCategory].Index = 0
3436
+
3437
+ rows = 7
3438
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
3439
+
3440
+ contents = Data.Category[Data.CurrentCategory].Contents
3441
+ if contents then
3442
+ -- destroy our buttons and their connections
3443
+ for i = 1, #insertButtons do
3444
+ insertButtons[i]:Destroy()
3445
+ end
3446
+
3447
+ for i = 1, #insertButtonCons do
3448
+ if insertButtonCons[i] then insertButtonCons[i]:Disconnect() end
3449
+ end
3450
+
3451
+ insertButtonCons = {}
3452
+ insertButtons = {}
3453
+
3454
+ arrayPosition = 1
3455
+ loadSectionOfItems(setGui, rows, columns)
3456
+ end
3457
+ end
3458
+
3459
+ local function selectSet(button, setName, setId, setIndex)
3460
+ if button and Data.Category[Data.CurrentCategory] ~= nil then
3461
+ if button ~= Data.Category[Data.CurrentCategory].Button then
3462
+ Data.Category[Data.CurrentCategory].Button = button
3463
+
3464
+ if SetCache[setId] == nil then
3465
+ SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
3466
+ end
3467
+ Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
3468
+
3469
+ Data.Category[Data.CurrentCategory].SetName = setName
3470
+ Data.Category[Data.CurrentCategory].SetId = setId
3471
+ end
3472
+ setSetIndex()
3473
+ end
3474
+ end
3475
+
3476
+ local function selectCategoryPage(buttons, page)
3477
+ if buttons ~= Data.CurrentCategory then
3478
+ if Data.CurrentCategory then
3479
+ for key, button in pairs(Data.CurrentCategory) do
3480
+ button.Visible = false
3481
+ end
3482
+ end
3483
+
3484
+ Data.CurrentCategory = buttons
3485
+ if Data.Category[Data.CurrentCategory] == nil then
3486
+ Data.Category[Data.CurrentCategory] = {}
3487
+ if #buttons > 0 then
3488
+ selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
3489
+ end
3490
+ else
3491
+ Data.Category[Data.CurrentCategory].Button = nil
3492
+ selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
3493
+ end
3494
+ end
3495
+ end
3496
+
3497
+ local function selectCategory(category)
3498
+ selectCategoryPage(category, 0)
3499
+ end
3500
+
3501
+ local function resetAllSetButtonSelection()
3502
+ local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
3503
+ for i = 1, #setButtons do
3504
+ if setButtons[i]:IsA("TextButton") then
3505
+ setButtons[i].Selected = false
3506
+ setButtons[i].BackgroundTransparency = 1
3507
+ setButtons[i].TextColor3 = Color3.new(1,1,1)
3508
+ setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
3509
+ end
3510
+ end
3511
+ end
3512
+
3513
+ local function populateSetsFrame()
3514
+ local currRow = 0
3515
+ for i = 1, #userCategoryButtons do
3516
+ local button = userCategoryButtons[i]
3517
+ button.Visible = true
3518
+ button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
3519
+ button.Parent = setGui.SetPanel.Sets.SetsLists
3520
+
3521
+ if i == 1 then -- we will have this selected by default, so show it
3522
+ button.Selected = true
3523
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
3524
+ button.TextColor3 = Color3.new(0,0,0)
3525
+ button.BackgroundTransparency = 0
3526
+ end
3527
+
3528
+ button.MouseEnter:Connect(function()
3529
+ if not button.Selected then
3530
+ button.BackgroundTransparency = 0
3531
+ button.TextColor3 = Color3.new(0,0,0)
3532
+ end
3533
+ end)
3534
+ button.MouseLeave:Connect(function()
3535
+ if not button.Selected then
3536
+ button.BackgroundTransparency = 1
3537
+ button.TextColor3 = Color3.new(1,1,1)
3538
+ end
3539
+ end)
3540
+ button.MouseButton1Click:Connect(function()
3541
+ resetAllSetButtonSelection()
3542
+ button.Selected = not button.Selected
3543
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
3544
+ button.TextColor3 = Color3.new(0,0,0)
3545
+ button.BackgroundTransparency = 0
3546
+ selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
3547
+ end)
3548
+
3549
+ currRow = currRow + 1
3550
+ end
3551
+
3552
+ local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
3553
+
3554
+ -- set first category as loaded for default
3555
+ if buttons then
3556
+ for i = 1, #buttons do
3557
+ if buttons[i]:IsA("TextButton") then
3558
+ selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
3559
+ selectCategory(userCategoryButtons)
3560
+ break
3561
+ end
3562
+ end
3563
+ end
3564
+ end
3565
+
3566
+ setGui = createSetGui()
3567
+ waterGui, waterTypeChangedEvent = createWaterGui()
3568
+ waterGui.Position = UDim2.new(0,55,0,0)
3569
+ waterGui.Parent = setGui
3570
+ setGui.Changed:Connect(function(prop) -- this resizes the preview image to always be the right size
3571
+ if prop == "AbsoluteSize" then
3572
+ handleResize()
3573
+ setSetIndex()
3574
+ end
3575
+ end)
3576
+
3577
+ local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
3578
+ scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
3579
+ scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
3580
+ scrollFrame.Name = "ItemsFrame"
3581
+ scrollFrame.ZIndex = 6
3582
+ scrollFrame.Parent = setGui.SetPanel
3583
+ scrollFrame.BackgroundTransparency = 1
3584
+
3585
+ drillDownSetZIndex(controlFrame,7)
3586
+
3587
+ controlFrame.Parent = setGui.SetPanel
3588
+ controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
3589
+
3590
+ local debounce = false
3591
+ controlFrame.ScrollBottom.Changed:Connect(function(prop)
3592
+ if controlFrame.ScrollBottom.Value == true then
3593
+ if debounce then return end
3594
+ debounce = true
3595
+ loadSectionOfItems(setGui, rows, columns)
3596
+ debounce = false
3597
+ end
3598
+ end)
3599
+
3600
+ local userData = {}
3601
+ for id = 1, #userIdsForSets do
3602
+ local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
3603
+ if newUserData and #newUserData > 2 then
3604
+ -- start at #3 to skip over My Decals and My Models for each account
3605
+ for category = 3, #newUserData do
3606
+ if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
3607
+ table.insert(userData,1,newUserData[category])
3608
+ else
3609
+ table.insert(userData, newUserData[category])
3610
+ end
3611
+ end
3612
+ end
3613
+
3614
+ end
3615
+ if userData then
3616
+ userCategoryButtons = processCategory(userData)
3617
+ end
3618
+
3619
+ rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
3620
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
3621
+
3622
+ populateSetsFrame()
3623
+
3624
+ setGui.SetPanel.CancelButton.MouseButton1Click:Connect(function()
3625
+ setGui.SetPanel.Visible = false
3626
+ if dialogClosed then dialogClosed() end
3627
+ end)
3628
+
3629
+ local setVisibilityFunction = function(visible)
3630
+ if visible then
3631
+ setGui.SetPanel.Visible = true
3632
+ else
3633
+ setGui.SetPanel.Visible = false
3634
+ end
3635
+ end
3636
+
3637
+ local getVisibilityFunction = function()
3638
+ if setGui then
3639
+ if setGui:FindFirstChild("SetPanel") then
3640
+ return setGui.SetPanel.Visible
3641
+ end
3642
+ end
3643
+
3644
+ return false
3645
+ end
3646
+
3647
+ return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
3648
+ end
3649
+
3650
+ t.CreateTerrainMaterialSelector = function(size,position)
3651
+ local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
3652
+ terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
3653
+
3654
+ local selectedButton = nil
3655
+
3656
+ local frame = Instance.new("Frame")
3657
+ frame.Name = "TerrainMaterialSelector"
3658
+ if size then
3659
+ frame.Size = size
3660
+ else
3661
+ frame.Size = UDim2.new(0, 245, 0, 230)
3662
+ end
3663
+ if position then
3664
+ frame.Position = position
3665
+ end
3666
+ frame.BorderSizePixel = 0
3667
+ frame.BackgroundColor3 = Color3.new(0,0,0)
3668
+ frame.Active = true
3669
+
3670
+ terrainMaterialSelectionChanged.Parent = frame
3671
+
3672
+ local waterEnabled = true -- todo: turn this on when water is ready
3673
+
3674
+ local materialToImageMap = {}
3675
+ local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
3676
+ if waterEnabled then
3677
+ table.insert(materialNames,"Water")
3678
+ end
3679
+ local currentMaterial = 1
3680
+
3681
+ function getEnumFromName(choice)
3682
+ if choice == "Grass" then return 1 end
3683
+ if choice == "Sand" then return 2 end
3684
+ if choice == "Erase" then return 0 end
3685
+ if choice == "Brick" then return 3 end
3686
+ if choice == "Granite" then return 4 end
3687
+ if choice == "Asphalt" then return 5 end
3688
+ if choice == "Iron" then return 6 end
3689
+ if choice == "Aluminum" then return 7 end
3690
+ if choice == "Gold" then return 8 end
3691
+ if choice == "Plank" then return 9 end
3692
+ if choice == "Log" then return 10 end
3693
+ if choice == "Gravel" then return 11 end
3694
+ if choice == "Cinder Block" then return 12 end
3695
+ if choice == "Stone Wall" then return 13 end
3696
+ if choice == "Concrete" then return 14 end
3697
+ if choice == "Plastic (red)" then return 15 end
3698
+ if choice == "Plastic (blue)" then return 16 end
3699
+ if choice == "Water" then return 17 end
3700
+ end
3701
+
3702
+ function getNameFromEnum(choice)
3703
+ if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
3704
+ if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
3705
+ if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
3706
+ if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
3707
+ if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
3708
+ if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
3709
+ if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
3710
+ if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
3711
+ if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
3712
+ if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
3713
+ if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
3714
+ if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
3715
+ if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
3716
+ if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
3717
+ if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
3718
+ if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
3719
+ if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
3720
+
3721
+ if waterEnabled then
3722
+ if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
3723
+ end
3724
+ end
3725
+
3726
+
3727
+ local function updateMaterialChoice(choice)
3728
+ currentMaterial = getEnumFromName(choice)
3729
+ terrainMaterialSelectionChanged:Fire(currentMaterial)
3730
+ end
3731
+
3732
+ -- we so need a better way to do this
3733
+ for i,v in pairs(materialNames) do
3734
+ materialToImageMap[v] = {}
3735
+ if v == "Grass" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=56563112"
3736
+ elseif v == "Sand" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=62356652"
3737
+ elseif v == "Brick" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=65961537"
3738
+ elseif v == "Granite" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532153"
3739
+ elseif v == "Asphalt" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532038"
3740
+ elseif v == "Iron" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532093"
3741
+ elseif v == "Aluminum" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67531995"
3742
+ elseif v == "Gold" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532118"
3743
+ elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67531848"
3744
+ elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67531924"
3745
+ elseif v == "Plank" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532015"
3746
+ elseif v == "Log" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532051"
3747
+ elseif v == "Gravel" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532206"
3748
+ elseif v == "Cinder Block" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532103"
3749
+ elseif v == "Stone Wall" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67531804"
3750
+ elseif v == "Concrete" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=67532059"
3751
+ elseif v == "Water" then materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=81407474"
3752
+ else materialToImageMap[v].Regular = "https://www.roblox.com/asset/?id=66887593" -- fill in the rest here!!
3753
+ end
3754
+ end
3755
+
3756
+ local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
3757
+ scrollFrame.Size = UDim2.new(0.85,0,1,0)
3758
+ scrollFrame.Position = UDim2.new(0,0,0,0)
3759
+ scrollFrame.Parent = frame
3760
+
3761
+ scrollUp.Parent = frame
3762
+ scrollUp.Visible = true
3763
+ scrollUp.Position = UDim2.new(1,-19,0,0)
3764
+
3765
+ scrollDown.Parent = frame
3766
+ scrollDown.Visible = true
3767
+ scrollDown.Position = UDim2.new(1,-19,1,-17)
3768
+
3769
+ local function goToNewMaterial(buttonWrap, materialName)
3770
+ updateMaterialChoice(materialName)
3771
+ buttonWrap.BackgroundTransparency = 0
3772
+ selectedButton.BackgroundTransparency = 1
3773
+ selectedButton = buttonWrap
3774
+ end
3775
+
3776
+ local function createMaterialButton(name)
3777
+ local buttonWrap = Instance.new("TextButton")
3778
+ buttonWrap.Text = ""
3779
+ buttonWrap.Size = UDim2.new(0,32,0,32)
3780
+ buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
3781
+ buttonWrap.BorderSizePixel = 0
3782
+ buttonWrap.BackgroundTransparency = 1
3783
+ buttonWrap.AutoButtonColor = false
3784
+ buttonWrap.Name = tostring(name)
3785
+
3786
+ local imageButton = Instance.new("ImageButton")
3787
+ imageButton.AutoButtonColor = false
3788
+ imageButton.BackgroundTransparency = 1
3789
+ imageButton.Size = UDim2.new(0,30,0,30)
3790
+ imageButton.Position = UDim2.new(0,1,0,1)
3791
+ imageButton.Name = tostring(name)
3792
+ imageButton.Parent = buttonWrap
3793
+ imageButton.Image = materialToImageMap[name].Regular
3794
+
3795
+ local enumType = Instance.new("NumberValue")
3796
+ enumType.Name = "EnumType"
3797
+ enumType.Parent = buttonWrap
3798
+ enumType.Value = 0
3799
+
3800
+ imageButton.MouseEnter:Connect(function()
3801
+ buttonWrap.BackgroundTransparency = 0
3802
+ end)
3803
+ imageButton.MouseLeave:Connect(function()
3804
+ if selectedButton ~= buttonWrap then
3805
+ buttonWrap.BackgroundTransparency = 1
3806
+ end
3807
+ end)
3808
+ imageButton.MouseButton1Click:Connect(function()
3809
+ if selectedButton ~= buttonWrap then
3810
+ goToNewMaterial(buttonWrap, tostring(name))
3811
+ end
3812
+ end)
3813
+
3814
+ return buttonWrap
3815
+ end
3816
+
3817
+ for i = 1, #materialNames do
3818
+ local imageButton = createMaterialButton(materialNames[i])
3819
+
3820
+ if materialNames[i] == "Grass" then -- always start with grass as the default
3821
+ selectedButton = imageButton
3822
+ imageButton.BackgroundTransparency = 0
3823
+ end
3824
+
3825
+ imageButton.Parent = scrollFrame
3826
+ end
3827
+
3828
+ local forceTerrainMaterialSelection = function(newMaterialType)
3829
+ if not newMaterialType then return end
3830
+ if currentMaterial == newMaterialType then return end
3831
+
3832
+ local matName = getNameFromEnum(newMaterialType)
3833
+ local buttons = scrollFrame:GetChildren()
3834
+ for i = 1, #buttons do
3835
+ if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
3836
+ if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
3837
+ if string.find(buttons[i].Name, matName) then
3838
+ goToNewMaterial(buttons[i],matName)
3839
+ return
3840
+ end
3841
+ end
3842
+ end
3843
+
3844
+ frame.Changed:Connect(function ( prop )
3845
+ if prop == "AbsoluteSize" then
3846
+ recalculateScroll()
3847
+ end
3848
+ end)
3849
+
3850
+ recalculateScroll()
3851
+ return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
3852
+ end
3853
+
3854
+ t.CreateLoadingFrame = function(name,size,position)
3855
+ game:GetService("ContentProvider"):Preload("https://www.roblox.com/asset/?id=35238053")
3856
+
3857
+ local loadingFrame = Instance.new("Frame")
3858
+ loadingFrame.Name = "LoadingFrame"
3859
+ loadingFrame.Style = Enum.FrameStyle.RobloxRound
3860
+
3861
+ if size then loadingFrame.Size = size
3862
+ else loadingFrame.Size = UDim2.new(0,300,0,160) end
3863
+ if position then loadingFrame.Position = position
3864
+ else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
3865
+
3866
+ local loadingBar = Instance.new("Frame")
3867
+ loadingBar.Name = "LoadingBar"
3868
+ loadingBar.BackgroundColor3 = Color3.new(0,0,0)
3869
+ loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
3870
+ loadingBar.Position = UDim2.new(0,0,0,41)
3871
+ loadingBar.Size = UDim2.new(1,0,0,30)
3872
+ loadingBar.Parent = loadingFrame
3873
+
3874
+ local loadingGreenBar = Instance.new("ImageLabel")
3875
+ loadingGreenBar.Name = "LoadingGreenBar"
3876
+ loadingGreenBar.Image = "https://www.roblox.com/asset/?id=35238053"
3877
+ loadingGreenBar.Position = UDim2.new(0,0,0,0)
3878
+ loadingGreenBar.Size = UDim2.new(0,0,1,0)
3879
+ loadingGreenBar.Visible = false
3880
+ loadingGreenBar.Parent = loadingBar
3881
+
3882
+ local loadingPercent = Instance.new("TextLabel")
3883
+ loadingPercent.Name = "LoadingPercent"
3884
+ loadingPercent.BackgroundTransparency = 1
3885
+ loadingPercent.Position = UDim2.new(0,0,1,0)
3886
+ loadingPercent.Size = UDim2.new(1,0,0,14)
3887
+ loadingPercent.Font = Enum.Font.Arial
3888
+ loadingPercent.Text = "0%"
3889
+ loadingPercent.FontSize = Enum.FontSize.Size14
3890
+ loadingPercent.TextColor3 = Color3.new(1,1,1)
3891
+ loadingPercent.Parent = loadingBar
3892
+
3893
+ local cancelButton = Instance.new("TextButton")
3894
+ cancelButton.Name = "CancelButton"
3895
+ cancelButton.Position = UDim2.new(0.5,-60,1,-40)
3896
+ cancelButton.Size = UDim2.new(0,120,0,40)
3897
+ cancelButton.Font = Enum.Font.Arial
3898
+ cancelButton.FontSize = Enum.FontSize.Size18
3899
+ cancelButton.TextColor3 = Color3.new(1,1,1)
3900
+ cancelButton.Text = "Cancel"
3901
+ cancelButton.Style = Enum.ButtonStyle.RobloxButton
3902
+ cancelButton.Parent = loadingFrame
3903
+
3904
+ local loadingName = Instance.new("TextLabel")
3905
+ loadingName.Name = "loadingName"
3906
+ loadingName.BackgroundTransparency = 1
3907
+ loadingName.Size = UDim2.new(1,0,0,18)
3908
+ loadingName.Position = UDim2.new(0,0,0,2)
3909
+ loadingName.Font = Enum.Font.Arial
3910
+ loadingName.Text = name
3911
+ loadingName.TextColor3 = Color3.new(1,1,1)
3912
+ loadingName.TextStrokeTransparency = 1
3913
+ loadingName.FontSize = Enum.FontSize.Size18
3914
+ loadingName.Parent = loadingFrame
3915
+
3916
+ local cancelButtonClicked = Instance.new("BindableEvent")
3917
+ cancelButtonClicked.Name = "CancelButtonClicked"
3918
+ cancelButtonClicked.Parent = cancelButton
3919
+ cancelButton.MouseButton1Click:Connect(function()
3920
+ cancelButtonClicked:Fire()
3921
+ end)
3922
+
3923
+ local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
3924
+ if percent and type(percent) ~= "number" then
3925
+ error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
3926
+ end
3927
+
3928
+ local newSize = nil
3929
+ if percent < 0 then
3930
+ newSize = UDim2.new(0,0,1,0)
3931
+ elseif percent > 1 then
3932
+ newSize = UDim2.new(1,0,1,0)
3933
+ else
3934
+ newSize = UDim2.new(percent,0,1,0)
3935
+ end
3936
+
3937
+ if tweenAction then
3938
+ if not tweenLength then
3939
+ error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
3940
+ end
3941
+
3942
+ if (newSize.X.Scale > 0) then
3943
+ loadingGreenBar.Visible = true
3944
+ loadingGreenBar:TweenSize( newSize,
3945
+ Enum.EasingDirection.Out,
3946
+ Enum.EasingStyle.Quad,
3947
+ tweenLength,
3948
+ true)
3949
+ else
3950
+ loadingGreenBar:TweenSize( newSize,
3951
+ Enum.EasingDirection.Out,
3952
+ Enum.EasingStyle.Quad,
3953
+ tweenLength,
3954
+ true,
3955
+ function()
3956
+ if (newSize.X.Scale < 0) then
3957
+ loadingGreenBar.Visible = false
3958
+ end
3959
+ end)
3960
+ end
3961
+
3962
+ else
3963
+ loadingGreenBar.Size = newSize
3964
+ loadingGreenBar.Visible = (newSize.X.Scale > 0)
3965
+ end
3966
+ end
3967
+
3968
+ loadingGreenBar.Changed:Connect(function(prop)
3969
+ if prop == "Size" then
3970
+ loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
3971
+ end
3972
+ end)
3973
+
3974
+ return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
3975
+ end
3976
+
3977
+ t.CreatePluginFrame = function (name,size,position,scrollable,parent)
3978
+ local function createMenuButton(size,position,text,fontsize,name,parent)
3979
+ local button = Instance.new("TextButton")
3980
+ button.AutoButtonColor = false
3981
+ button.Name = name
3982
+ button.BackgroundTransparency = 1
3983
+ button.Position = position
3984
+ button.Size = size
3985
+ button.Font = Enum.Font.ArialBold
3986
+ button.FontSize = fontsize
3987
+ button.Text = text
3988
+ button.TextColor3 = Color3.new(1,1,1)
3989
+ button.BorderSizePixel = 0
3990
+ button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
3991
+ button.Parent = parent
3992
+
3993
+ button.MouseEnter:Connect(function ( )
3994
+ if button.Selected then return end
3995
+ button.BackgroundTransparency = 0
3996
+ end)
3997
+ button.MouseLeave:Connect(function ( )
3998
+ if button.Selected then return end
3999
+ button.BackgroundTransparency = 1
4000
+ end)
4001
+
4002
+ return button
4003
+
4004
+ end
4005
+
4006
+ local dragBar = Instance.new("Frame")
4007
+ dragBar.Name = tostring(name) .. "DragBar"
4008
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
4009
+ dragBar.BorderColor3 = Color3.new(0,0,0)
4010
+ if size then
4011
+ dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
4012
+ else
4013
+ dragBar.Size = UDim2.new(0,183,0,20)
4014
+ end
4015
+ if position then
4016
+ dragBar.Position = position
4017
+ end
4018
+ dragBar.Active = true
4019
+ dragBar.Draggable = true
4020
+ dragBar.Parent = parent
4021
+
4022
+ dragBar.MouseEnter:Connect(function ( )
4023
+ dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
4024
+ end)
4025
+ dragBar.MouseLeave:Connect(function ( )
4026
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
4027
+ end)
4028
+
4029
+ -- plugin name label
4030
+ local pluginNameLabel = Instance.new("TextLabel")
4031
+ pluginNameLabel.Name = "BarNameLabel"
4032
+ pluginNameLabel.Text = " " .. tostring(name)
4033
+ pluginNameLabel.TextColor3 = Color3.new(1,1,1)
4034
+ pluginNameLabel.TextStrokeTransparency = 0
4035
+ pluginNameLabel.Size = UDim2.new(1,0,1,0)
4036
+ pluginNameLabel.Font = Enum.Font.ArialBold
4037
+ pluginNameLabel.FontSize = Enum.FontSize.Size18
4038
+ pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
4039
+ pluginNameLabel.BackgroundTransparency = 1
4040
+ pluginNameLabel.Parent = dragBar
4041
+
4042
+ -- close button
4043
+ local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
4044
+ local closeEvent = Instance.new("BindableEvent")
4045
+ closeEvent.Name = "CloseEvent"
4046
+ closeEvent.Parent = closeButton
4047
+ closeButton.MouseButton1Click:Connect(function ()
4048
+ closeEvent:Fire()
4049
+ closeButton.BackgroundTransparency = 1
4050
+ end)
4051
+
4052
+ -- help button
4053
+ local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
4054
+ local helpFrame = Instance.new("Frame")
4055
+ helpFrame.Name = "HelpFrame"
4056
+ helpFrame.BackgroundColor3 = Color3.new(0,0,0)
4057
+ helpFrame.Size = UDim2.new(0,300,0,552)
4058
+ helpFrame.Position = UDim2.new(1,5,0,0)
4059
+ helpFrame.Active = true
4060
+ helpFrame.BorderSizePixel = 0
4061
+ helpFrame.Visible = false
4062
+ helpFrame.Parent = dragBar
4063
+
4064
+ helpButton.MouseButton1Click:Connect(function( )
4065
+ helpFrame.Visible = not helpFrame.Visible
4066
+ if helpFrame.Visible then
4067
+ helpButton.Selected = true
4068
+ helpButton.BackgroundTransparency = 0
4069
+ local screenGui = getLayerCollectorAncestor(helpFrame)
4070
+ if screenGui then
4071
+ if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
4072
+ helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
4073
+ else -- position on right hand side
4074
+ helpFrame.Position = UDim2.new(1,5,0,0)
4075
+ end
4076
+ else
4077
+ helpFrame.Position = UDim2.new(1,5,0,0)
4078
+ end
4079
+ else
4080
+ helpButton.Selected = false
4081
+ helpButton.BackgroundTransparency = 1
4082
+ end
4083
+ end)
4084
+
4085
+ local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
4086
+ minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
4087
+
4088
+ local minimizeFrame = Instance.new("Frame")
4089
+ minimizeFrame.Name = "MinimizeFrame"
4090
+ minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
4091
+ minimizeFrame.BorderColor3 = Color3.new(0,0,0)
4092
+ minimizeFrame.Position = UDim2.new(0,0,1,0)
4093
+ if size then
4094
+ minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
4095
+ else
4096
+ minimizeFrame.Size = UDim2.new(0,183,0,50)
4097
+ end
4098
+ minimizeFrame.Visible = false
4099
+ minimizeFrame.Parent = dragBar
4100
+
4101
+ local minimizeBigButton = Instance.new("TextButton")
4102
+ minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
4103
+ minimizeBigButton.Name = "MinimizeButton"
4104
+ minimizeBigButton.Size = UDim2.new(0,100,0,40)
4105
+ minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
4106
+ minimizeBigButton.Font = Enum.Font.ArialBold
4107
+ minimizeBigButton.FontSize = Enum.FontSize.Size18
4108
+ minimizeBigButton.TextColor3 = Color3.new(1,1,1)
4109
+ minimizeBigButton.Text = "Show"
4110
+ minimizeBigButton.Parent = minimizeFrame
4111
+
4112
+ local separatingLine = Instance.new("Frame")
4113
+ separatingLine.Name = "SeparatingLine"
4114
+ separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
4115
+ separatingLine.BorderSizePixel = 0
4116
+ separatingLine.Position = UDim2.new(1,-18,0.5,-7)
4117
+ separatingLine.Size = UDim2.new(0,1,0,14)
4118
+ separatingLine.Parent = dragBar
4119
+
4120
+ local otherSeparatingLine = separatingLine:clone()
4121
+ otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
4122
+ otherSeparatingLine.Parent = dragBar
4123
+
4124
+ local widgetContainer = Instance.new("Frame")
4125
+ widgetContainer.Name = "WidgetContainer"
4126
+ widgetContainer.BackgroundTransparency = 1
4127
+ widgetContainer.Position = UDim2.new(0,0,1,0)
4128
+ widgetContainer.BorderColor3 = Color3.new(0,0,0)
4129
+ if not scrollable then
4130
+ widgetContainer.BackgroundTransparency = 0
4131
+ widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
4132
+ end
4133
+ widgetContainer.Parent = dragBar
4134
+
4135
+ if size then
4136
+ if scrollable then
4137
+ widgetContainer.Size = size
4138
+ else
4139
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
4140
+ end
4141
+ else
4142
+ if scrollable then
4143
+ widgetContainer.Size = UDim2.new(0,163,0,400)
4144
+ else
4145
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
4146
+ end
4147
+ end
4148
+ if position then
4149
+ widgetContainer.Position = position + UDim2.new(0,0,0,20)
4150
+ end
4151
+
4152
+ local frame,control,verticalDragger = nil
4153
+ if scrollable then
4154
+ --frame for widgets
4155
+ frame,control = t.CreateTrueScrollingFrame()
4156
+ frame.Size = UDim2.new(1, 0, 1, 0)
4157
+ frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
4158
+ frame.BorderColor3 = Color3.new(0,0,0)
4159
+ frame.Active = true
4160
+ frame.Parent = widgetContainer
4161
+ control.Parent = dragBar
4162
+ control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
4163
+ control.BorderSizePixel = 0
4164
+ control.BackgroundTransparency = 0
4165
+ control.Position = UDim2.new(1,-21,1,1)
4166
+ if size then
4167
+ control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
4168
+ else
4169
+ control.Size = UDim2.new(0,21,0,400)
4170
+ end
4171
+ control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
4172
+
4173
+ local fakeLine = Instance.new("Frame")
4174
+ fakeLine.Name = "FakeLine"
4175
+ fakeLine.BorderSizePixel = 0
4176
+ fakeLine.BackgroundColor3 = Color3.new(0,0,0)
4177
+ fakeLine.Size = UDim2.new(0,1,1,1)
4178
+ fakeLine.Position = UDim2.new(1,0,0,0)
4179
+ fakeLine.Parent = control
4180
+
4181
+ verticalDragger = Instance.new("TextButton")
4182
+ verticalDragger.ZIndex = 2
4183
+ verticalDragger.AutoButtonColor = false
4184
+ verticalDragger.Name = "VerticalDragger"
4185
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
4186
+ verticalDragger.BorderColor3 = Color3.new(0,0,0)
4187
+ verticalDragger.Size = UDim2.new(1,20,0,20)
4188
+ verticalDragger.Position = UDim2.new(0,0,1,0)
4189
+ verticalDragger.Active = true
4190
+ verticalDragger.Text = ""
4191
+ verticalDragger.Parent = widgetContainer
4192
+
4193
+ local scrubFrame = Instance.new("Frame")
4194
+ scrubFrame.Name = "ScrubFrame"
4195
+ scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
4196
+ scrubFrame.BorderSizePixel = 0
4197
+ scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
4198
+ scrubFrame.Size = UDim2.new(0,10,0,1)
4199
+ scrubFrame.ZIndex = 5
4200
+ scrubFrame.Parent = verticalDragger
4201
+ local scrubTwo = scrubFrame:clone()
4202
+ scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
4203
+ scrubTwo.Parent = verticalDragger
4204
+ local scrubThree = scrubFrame:clone()
4205
+ scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
4206
+ scrubThree.Parent = verticalDragger
4207
+
4208
+ local areaSoak = Instance.new("TextButton",getLayerCollectorAncestor(parent))
4209
+ areaSoak.Name = "AreaSoak"
4210
+ areaSoak.Size = UDim2.new(1,0,1,0)
4211
+ areaSoak.BackgroundTransparency = 1
4212
+ areaSoak.BorderSizePixel = 0
4213
+ areaSoak.Text = ""
4214
+ areaSoak.ZIndex = 10
4215
+ areaSoak.Visible = false
4216
+ areaSoak.Active = true
4217
+
4218
+ local draggingVertical = false
4219
+ local startYPos = nil
4220
+ verticalDragger.MouseEnter:Connect(function ()
4221
+ verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
4222
+ end)
4223
+ verticalDragger.MouseLeave:Connect(function ()
4224
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
4225
+ end)
4226
+ verticalDragger.MouseButton1Down:Connect(function(x,y)
4227
+ draggingVertical = true
4228
+ areaSoak.Visible = true
4229
+ startYPos = y
4230
+ end)
4231
+ areaSoak.MouseButton1Up:Connect(function ( )
4232
+ draggingVertical = false
4233
+ areaSoak.Visible = false
4234
+ end)
4235
+ areaSoak.MouseMoved:Connect(function(x,y)
4236
+ if not draggingVertical then return end
4237
+
4238
+ local yDelta = y - startYPos
4239
+ if not control.ScrollDownButton.Visible and yDelta > 0 then
4240
+ return
4241
+ end
4242
+
4243
+ if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
4244
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
4245
+ control.Size = UDim2.new (0,21,0,150)
4246
+ return
4247
+ end
4248
+
4249
+ startYPos = y
4250
+
4251
+ if widgetContainer.Size.Y.Offset + yDelta >= 0 then
4252
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
4253
+ control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
4254
+ end
4255
+ end)
4256
+ end
4257
+
4258
+ local function switchMinimize()
4259
+ minimizeFrame.Visible = not minimizeFrame.Visible
4260
+ if scrollable then
4261
+ frame.Visible = not frame.Visible
4262
+ verticalDragger.Visible = not verticalDragger.Visible
4263
+ control.Visible = not control.Visible
4264
+ else
4265
+ widgetContainer.Visible = not widgetContainer.Visible
4266
+ end
4267
+
4268
+ if minimizeFrame.Visible then
4269
+ minimizeButton.Text = "+"
4270
+ else
4271
+ minimizeButton.Text = "-"
4272
+ end
4273
+ end
4274
+
4275
+ minimizeBigButton.MouseButton1Click:Connect(function ( )
4276
+ switchMinimize()
4277
+ end)
4278
+
4279
+ minimizeButton.MouseButton1Click:Connect(function( )
4280
+ switchMinimize()
4281
+ end)
4282
+
4283
+ if scrollable then
4284
+ return dragBar, frame, helpFrame, closeEvent
4285
+ else
4286
+ return dragBar, widgetContainer, helpFrame, closeEvent
4287
+ end
4288
+ end
4289
+
4290
+ t.Help =
4291
+ function(funcNameOrFunc)
4292
+ --input argument can be a string or a function. Should return a description (of arguments and expected side effects)
4293
+ if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
4294
+ return "Function CreatePropertyDropDownMenu. " ..
4295
+ "Arguments: (instance, propertyName, enumType). " ..
4296
+ "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
4297
+ end
4298
+ if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
4299
+ return "Function CreateDropDownMenu. " ..
4300
+ "Arguments: (items, onItemSelected). " ..
4301
+ "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
4302
+ end
4303
+ if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
4304
+ return "Function CreateMessageDialog. " ..
4305
+ "Arguments: (title, message, buttons). " ..
4306
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
4307
+ end
4308
+ if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
4309
+ return "Function CreateStyledMessageDialog. " ..
4310
+ "Arguments: (title, message, style, buttons). " ..
4311
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
4312
+ end
4313
+ if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
4314
+ return "Function GetFontHeight. " ..
4315
+ "Arguments: (font, fontSize). " ..
4316
+ "Side effect: returns the size in pixels of the given font + fontSize"
4317
+ end
4318
+ if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
4319
+
4320
+ end
4321
+ if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
4322
+ return "Function CreateScrollingFrame. " ..
4323
+ "Arguments: (orderList, style) " ..
4324
+ "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
4325
+ end
4326
+ if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
4327
+ return "Function CreateTrueScrollingFrame. " ..
4328
+ "Arguments: (nil) " ..
4329
+ "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
4330
+ end
4331
+ if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
4332
+ return "Function AutoTruncateTextObject. " ..
4333
+ "Arguments: (textLabel) " ..
4334
+ "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
4335
+ end
4336
+ if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
4337
+ return "Function CreateSlider. " ..
4338
+ "Arguments: (steps, width, position) " ..
4339
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
4340
+ end
4341
+ if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then
4342
+ return "Function CreateSliderNew. " ..
4343
+ "Arguments: (steps, width, position) " ..
4344
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
4345
+ end
4346
+ if funcNameOrFunc == "CreateSliderNewest" or funcNameOrFunc == t.CreateSliderNewest then
4347
+ return "Function CreateSliderNewest. " ..
4348
+ "Arguments: (minValue, maxValue, width, position) " ..
4349
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'minValue' argument specifies the minimum value of the slider. The 'maxValue' argument specifies the maximum value the slider can accept. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
4350
+ end
4351
+ if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
4352
+ return "Function CreateLoadingFrame. " ..
4353
+ "Arguments: (name, size, position) " ..
4354
+ "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
4355
+ end
4356
+ if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
4357
+ return "Function CreateTerrainMaterialSelector. " ..
4358
+ "Arguments: (size, position) " ..
4359
+ "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
4360
+ end
4361
+ end
4362
+
4363
+ return t