· 5 months ago · Apr 13, 2025, 06:31 PM
1local ReGui = {
2 --// Package data
3 Version = "1.4.1",
4 Author = "Depso",
5 License = "MIT",
6 Repository = "https://github.com/depthso/Dear-ReGui/",
7
8 --// Configuration
9 Debug = false,
10 PrefabsId = 71968920594655,
11 DefaultTitle = "ReGui",
12 ContainerName = "ReGui",
13 DoubleClickThreshold = 0.3,
14 TooltipOffset = 15,
15 IniToSave = {
16 "Value"
17 },
18
19 --// Objects
20 Container = nil,
21 Prefabs = nil,
22 FocusedWindow = nil,
23
24 --// Classes
25 ThemeConfigs = {},
26 Elements = {},
27 Signaling = {},
28 Animation = {
29 DefaultTweenInfo = TweenInfo.new(0.08),
30 },
31
32 --// Collections
33 _FlagCache = {},
34 _ErrorCache = {},
35 Windows = {},
36 ActiveTooltips = {},
37 IniSettings = {},
38 AnimationConnections = {}
39}
40
41ReGui.Icons = {
42 Dot = "rbxasset://textures/whiteCircle.png",
43 Arrow = "rbxasset://textures/DeveloperFramework/button_arrow_right.png",
44 Close = "rbxasset://textures/AnimationEditor/icon_close.png",
45 Checkmark = "rbxasset://textures/AnimationEditor/icon_checkmark.png",
46 Cat = "rbxassetid://16211812161",
47 Script = "rbxassetid://11570895459",
48 Settings = "rbxassetid://9743465390",
49 Info = "rbxassetid://18754976792",
50 Move = "rbxassetid://6710235139",
51 Roblox = "rbxassetid://7414445494",
52 Warning = "rbxassetid://11745872910",
53 Audio = "rbxassetid://302250236",
54 Shop = "rbxassetid://6473525198",
55 CharacterDance = "rbxassetid://11932783331",
56 Pants = "rbxassetid://10098755331",
57 Home = "rbxassetid://4034483344",
58 Robux = "rbxassetid://5986143282",
59 Badge = "rbxassetid://16170504068",
60 SpawnLocation = "rbxassetid://6400507398",
61 Sword = "rbxassetid://7485051715",
62 Clover = "rbxassetid://11999300014",
63 Star = "rbxassetid://3057073083",
64 Code = "rbxassetid://11348555035",
65 Paw = "rbxassetid://13001190533",
66 Shield = "rbxassetid://7461510428",
67 Shield2 = "rbxassetid://7169354142",
68 File = "rbxassetid://7276823330",
69 Book = "rbxassetid://16061686835",
70 Location = "rbxassetid://13549782519",
71 Puzzle = "rbxassetid://8898417863",
72 Discord = "rbxassetid://84828491431270",
73 Premium = "rbxassetid://6487178625",
74 Friend = "rbxassetid://10885655986",
75 User = "rbxassetid://18854794412",
76 Duplicate = "rbxassetid://11833749507",
77 ChatBox = "rbxassetid://15839118471",
78 ChatBox2 = "rbxassetid://15839116089",
79 Devices = "rbxassetid://4458812712",
80 Weight = "rbxassetid://9855685269",
81 Image = "rbxassetid://123311808092347",
82 Profile = "rbxassetid://13585614795",
83 Admin = "rbxassetid://11656483170",
84 PaintBrush = "rbxassetid://12111879608",
85 Speed = "rbxassetid://12641434961",
86 NoConnection = "rbxassetid://9795340967",
87 Connection = "rbxassetid://119759670842477",
88 Globe = "rbxassetid://18870359747",
89 Box = "rbxassetid://140217940575618",
90 Crown = "rbxassetid://18826490498",
91 Control = "rbxassetid://18979524646",
92 Send = "rbxassetid://18940312887",
93 FastForward = "rbxassetid://112963221295680",
94 Pause = "rbxassetid://109949100737970",
95 Reload = "rbxassetid://11570018242",
96 Joystick = "rbxassetid://18749336354",
97 Controller = "rbxassetid://11894535915",
98 Lock = "rbxassetid://17783082088",
99 Calculator = "rbxassetid://85861816563977",
100 Sun = "rbxassetid://13492317832",
101 Moon = "rbxassetid://8498174594",
102 Prohibited = "rbxassetid://5248916036",
103 Flag = "rbxassetid://251346532",
104 Website = "rbxassetid://98455290625865",
105 Telegram = "rbxassetid://115860270107061",
106 MusicNote = "rbxassetid://18187351229",
107 Music = "rbxassetid://253830398",
108 Headphones = "rbxassetid://1311321471",
109 Phone = "rbxassetid://8411963035",
110 Smartphone = "rbxassetid://14040313879",
111 Desktop = "rbxassetid://3120635703",
112 Desktop2 = "rbxassetid://4728059490",
113 Laptop = "rbxassetid://4728059725",
114 Server = "rbxassetid://9692125126",
115 Wedge = "rbxassetid://9086583059",
116 Drill = "rbxassetid://11959189471",
117 Character = "rbxassetid://13285102351",
118}
119
120ReGui.Accent = {
121 --// ReGui acent colors
122 Light = Color3.fromRGB(50, 150, 250),
123 Dark = Color3.fromRGB(30, 66, 115),
124 ExtraDark = Color3.fromRGB(28, 39, 53),
125 White = Color3.fromRGB(240, 240, 240),
126 Gray = Color3.fromRGB(172, 171, 175),
127 Black = Color3.fromRGB(15, 19, 24),
128 Yellow = Color3.fromRGB(230, 180, 0),
129 Orange = Color3.fromRGB(230, 150, 0),
130 Green = Color3.fromRGB(130, 188, 91),
131 Red = Color3.fromRGB(255, 69, 69),
132
133 --// ImGui acent colors
134 ImGui = {
135 Light = Color3.fromRGB(66, 150, 250),
136 Dark = Color3.fromRGB(41, 74, 122),
137 Black = Color3.fromRGB(15, 15, 15),
138 Gray = Color3.fromRGB(36, 36, 36)
139 }
140}
141
142type ThemeData = {
143 [string]: any
144}
145-- If you are forking just to edit this, please use ReGui:DefineTheme instead
146local ThemeConfigs = ReGui.ThemeConfigs
147ThemeConfigs.DarkTheme = {
148 Values = {
149 AnimationTweenInfo = TweenInfo.new(0.08),
150 TextFont = Font.fromName("Inconsolata"),
151 TextSize = 16,
152 Text = ReGui.Accent.White,
153 TextDisabled = ReGui.Accent.Gray,
154 ErrorText = ReGui.Accent.Red,
155
156 FrameBg = ReGui.Accent.Dark,
157 FrameBgTransparency = 0.4,
158 FrameBgActive = ReGui.Accent.Light,
159 FrameBgTransparencyActive = 0.4,
160 FrameRounding = UDim.new(0, 2),
161
162 --// Elements
163 SliderGrab = ReGui.Accent.Light,
164 ButtonsBg = ReGui.Accent.Light,
165 CollapsingHeaderBg = ReGui.Accent.Light,
166 CollapsingHeaderText = ReGui.Accent.White,
167 CheckMark = ReGui.Accent.Light,
168 ResizeGrab = ReGui.Accent.Light,
169 HeaderBg = ReGui.Accent.Gray,
170 HeaderBgTransparency = 0.7,
171 HistogramBar = ReGui.Accent.Yellow,
172 ProgressBar = ReGui.Accent.Yellow,
173 RegionBg = ReGui.Accent.Dark,
174 RegionBgTransparency = 0.1,
175 Separator = ReGui.Accent.Gray,
176 SeparatorTransparency = 0.5,
177 ConsoleLineNumbers = ReGui.Accent.White,
178 LabelPaddingTop = UDim.new(0, 0),
179 LabelPaddingBottom = UDim.new(0, 0),
180 MenuBar = ReGui.Accent.ExtraDark,
181 MenuBarTransparency = 0.1,
182 PopupCanvas = ReGui.Accent.Black,
183
184 --// TabSelector
185 TabTextPaddingTop = UDim.new(0, 3),
186 TabTextPaddingBottom = UDim.new(0, 8),
187 TabText = ReGui.Accent.Gray,
188 TabBg = ReGui.Accent.Dark,
189 TabTextActive = ReGui.Accent.White,
190 TabBgActive = ReGui.Accent.Light,
191 TabsBarBg = Color3.fromRGB(36, 36, 36),
192 TabsBarBgTransparency = 1,
193 TabPagePadding = UDim.new(0, 8),
194
195 --// Window
196 ModalWindowDimBg = Color3.fromRGB(230, 230, 230),
197 ModalWindowDimTweenInfo = TweenInfo.new(0.2),
198
199 WindowBg = ReGui.Accent.Black,
200 WindowBgTransparency = 0.05,
201
202 Border = ReGui.Accent.Gray,
203 BorderTransparency = 0.8,
204 BorderTransparencyActive = 0.5,
205
206 Title = ReGui.Accent.White,
207 TitleAlign = Enum.TextXAlignment.Left,
208 TitleBarBg = ReGui.Accent.Black,
209 TitleBarTransparency = 0,
210 TitleActive = ReGui.Accent.White,
211 TitleBarBgActive = ReGui.Accent.Dark,
212 TitleBarTransparencyActive = 0.05,
213 TitleBarBgCollapsed = Color3.fromRGB(0, 0, 0),
214 TitleBarTransparencyCollapsed = 0.6,
215 }
216}
217ThemeConfigs.LightTheme = {
218 BaseTheme = ThemeConfigs.DarkTheme,
219 Values = {
220 Text = ReGui.Accent.Black,
221 TextFont = Font.fromName("Ubuntu"),
222 TextSize = 16,
223
224 FrameBg = ReGui.Accent.Gray,
225 FrameBgTransparency = 0.4,
226 FrameBgActive = ReGui.Accent.Light,
227 FrameBgTransparencyActive = 0.6,
228
229 SliderGrab = ReGui.Accent.Light,
230 ButtonsBg = ReGui.Accent.Light,
231 CollapsingHeaderText = ReGui.Accent.Black,
232 Separator = ReGui.Accent.Black,
233 ConsoleLineNumbers = ReGui.Accent.Yellow,
234 MenuBar = Color3.fromRGB(219, 219, 219),
235 PopupCanvas = ReGui.Accent.White,
236
237 TabText = ReGui.Accent.Black,
238 TabTextActive = ReGui.Accent.Black,
239
240 WindowBg = ReGui.Accent.White,
241 Border = ReGui.Accent.Gray,
242 ResizeGrab = ReGui.Accent.Gray,
243
244 Title = ReGui.Accent.Black,
245 TitleAlign = Enum.TextXAlignment.Center,
246 TitleBarBg = ReGui.Accent.Gray,
247 TitleActive = ReGui.Accent.Black,
248 TitleBarBgActive = Color3.fromRGB(186, 186, 186),
249 TitleBarBgCollapsed = ReGui.Accent.Gray
250 }
251}
252ThemeConfigs.ImGui = {
253 BaseTheme = ThemeConfigs.DarkTheme,
254 Values = {
255 AnimationTweenInfo = TweenInfo.new(0),
256 Text = Color3.fromRGB(255, 255, 255),
257
258 FrameBg = ReGui.Accent.ImGui.Dark,
259 FrameBgTransparency = 0.4,
260 FrameBgActive = ReGui.Accent.ImGui.Light,
261 FrameBgTransparencyActive = 0.5,
262 FrameRounding = UDim.new(0, 0),
263
264 ButtonsBg = ReGui.Accent.ImGui.Light,
265 CollapsingHeaderBg = ReGui.Accent.ImGui.Light,
266 CollapsingHeaderText = ReGui.Accent.White,
267 CheckMark = ReGui.Accent.ImGui.Light,
268 ResizeGrab = ReGui.Accent.ImGui.Light,
269 MenuBar = ReGui.Accent.ImGui.Gray,
270 MenuBarTransparency = 0,
271 PopupCanvas = ReGui.Accent.ImGui.Black,
272
273 TabText = ReGui.Accent.Gray,
274 TabBg = ReGui.Accent.ImGui.Dark,
275 TabTextActive = ReGui.Accent.White,
276 TabBgActive = ReGui.Accent.ImGui.Light,
277
278 WindowBg = ReGui.Accent.ImGui.Black,
279 WindowBgTransparency = 0.05,
280 Border = ReGui.Accent.Gray,
281 BorderTransparency = 0.7,
282 BorderTransparencyActive = 0.4,
283
284 Title = ReGui.Accent.White,
285 TitleBarBg = ReGui.Accent.ImGui.Black,
286 TitleBarTransparency = 0,
287 TitleBarBgActive = ReGui.Accent.ImGui.Dark,
288 TitleBarTransparencyActive = 0,
289 }
290}
291
292ReGui.ElementColors = {
293 ["MenuBar"] = {
294 BackgroundColor3 = "MenuBar",
295 BackgroundTransparency = "MenuBarTransparency",
296 },
297 ["FrameRounding"] = {
298 CornerRadius = "FrameRounding"
299 },
300 ["PopupCanvas"] = {
301 BackgroundColor3 = "PopupCanvas"
302 },
303 ["ModalWindowDim"] = {
304 BackgroundColor3 = "ModalWindowDimBg"
305 },
306 ["Selectable"] = "Button",
307 ["MenuButton"] = "Button",
308 ["Separator"] = {
309 BackgroundColor3 = "Separator",
310 BackgroundTransparency = "SeparatorTransparency",
311 },
312 ["Region"] = {
313 BackgroundColor3 = "RegionBg",
314 BackgroundTransparency = "RegionBgTransparency",
315 },
316 ["Label"] = {
317 TextColor3 = "Text",
318 FontFace = "TextFont",
319 TextSize = "TextSize",
320 },
321 ["ConsoleLineNumbers"] = {
322 TextColor3 = "ConsoleLineNumbers",
323 FontFace = "TextFont",
324 TextSize = "TextSize",
325 },
326 ["ConsoleText"] = "Label",
327 ["LabelDisabled"] = {
328 TextColor3 = "TextDisabled",
329 FontFace = "TextFont",
330 TextSize = "TextSize",
331 },
332 ["Plot"] = {
333 BackgroundColor3 = "HistogramBar",
334 },
335 ["Header"] = {
336 BackgroundColor3 = "HeaderBg",
337 BackgroundTransparency = "HeaderBgTransparency",
338 },
339 ["WindowTitle"] = {
340 TextXAlignment = "TitleAlign",
341 FontFace = "TextFont",
342 TextSize = "TextSize",
343 },
344 ["TitleBar"] = {
345 BackgroundColor3 = "TitleBarBgActive"
346 },
347 ["Window"] = {
348 BackgroundColor3 = "WindowBg",
349 BackgroundTransparency = "WindowBgTransparency"
350 },
351 ["TitleBarBgCollapsed"] = {
352 BackgroundColor3 = "TitleBarBgCollapsed",
353 BackgroundTransparency = "TitleBarTransparencyCollapsed"
354 },
355 ["TitleBarBgActive"] = {
356 BackgroundColor3 = "TitleBarBgActive",
357 BackgroundTransparency = "TitleBarTransparencyActive"
358 },
359 ["TitleBarBg"] = {
360 BackgroundColor3 = "TitleBarBg",
361 BackgroundTransparency = "TitleBarTransparency"
362 },
363 ["TabsBar"] = {
364 BackgroundColor3 = "TabsBarBg",
365 BackgroundTransparency = "TabsBarBgTransparency",
366 },
367 ["Border"] = {
368 Color = "Border",
369 Transparency = "BorderTransparency"
370 },
371 ["ResizeGrab"] = {
372 TextColor3 = "ResizeGrab"
373 },
374 ["BorderActive"] = {
375 Transparency = "BorderTransparencyActive"
376 },
377 ["Frame"] = {
378 BackgroundColor3 = "FrameBg",
379 BackgroundTransparency = "FrameBgTransparency",
380 TextColor3 = "Text",
381 FontFace = "TextFont",
382 TextSize = "TextSize",
383 },
384 ["FrameActive"] = {
385 BackgroundColor3 = "FrameBgActive",
386 BackgroundTransparency = "FrameBgTransparencyActive"
387 },
388 ["SliderGrab"] = {
389 BackgroundColor3 = "SliderGrab"
390 },
391 ["Button"] = {
392 BackgroundColor3 = "ButtonsBg",
393 TextColor3 = "Text",
394 FontFace = "TextFont",
395 TextSize = "TextSize",
396 },
397 ["CollapsingHeader"] = {
398 FontFace = "TextFont",
399 TextSize = "TextSize",
400 TextColor3 = "CollapsingHeaderText",
401 BackgroundColor3 = "CollapsingHeaderBg",
402 },
403 ["Checkbox"] = {
404 BackgroundColor3 = "FrameBg",
405 },
406 ["CheckMark"] = {
407 ImageColor3 = "CheckMark",
408 BackgroundColor3 = "CheckMark",
409 },
410 ["RadioButton"] = {
411 BackgroundColor3 = "ButtonsBg",
412 }
413}
414
415ReGui.Styles = {
416 RadioButton = {
417 Animation = "RadioButtons",
418 CornerRadius = UDim.new(1, 0),
419 },
420 Button = {
421 Animation = "Buttons"
422 },
423 CollapsingHeader = {
424 Animation = "Buttons"
425 },
426 TreeNode = {
427 Animation = "TransparentButtons"
428 },
429 TransparentButton = {
430 Animation = "TransparentButtons"
431 }
432}
433
434ReGui.Animations = {
435 ["Invisible"] = {
436 Connections = {
437 MouseEnter = {
438 Visible = true,
439 },
440 MouseLeave = {
441 Visible = false,
442 }
443 },
444 Init = "MouseLeave"
445 },
446 ["Buttons"] = {
447 Connections = {
448 MouseEnter = {
449 BackgroundTransparency = 0.3,
450 },
451 MouseLeave = {
452 BackgroundTransparency = 0.7,
453 }
454 },
455 Init = "MouseLeave"
456 },
457 ["TextButtons"] = {
458 Connections = {
459 MouseEnter = {
460 TextTransparency = 0.3,
461 },
462 MouseLeave = {
463 TextTransparency = 0.7,
464 }
465 },
466 Init = "MouseLeave"
467 },
468 ["TransparentButtons"] = {
469 Connections = {
470 MouseEnter = {
471 BackgroundTransparency = 0.3,
472 },
473 MouseLeave = {
474 BackgroundTransparency = 1,
475 }
476 },
477 Init = "MouseLeave"
478 },
479 ["RadioButtons"] = {
480 Connections = {
481 MouseEnter = {
482 BackgroundTransparency = 0.5,
483 },
484 MouseLeave = {
485 BackgroundTransparency = 1,
486 }
487 },
488 Init = "MouseLeave"
489 },
490 ["Inputs"] = {
491 Connections = {
492 MouseEnter = {
493 BackgroundTransparency = 0,
494 },
495 MouseLeave = {
496 BackgroundTransparency = 0.5,
497 },
498 },
499 Init = "MouseLeave"
500 },
501 ["Plots"] = {
502 Connections = {
503 MouseEnter = {
504 BackgroundTransparency = 0.3,
505 },
506 MouseLeave = {
507 BackgroundTransparency = 0,
508 },
509 },
510 Init = "MouseLeave"
511 },
512 ["Border"] = {
513 Connections = {
514 Selected = {
515 Transparency = 0,
516 Thickness = 1
517 },
518 Deselected = {
519 Transparency = 0.7,
520 Thickness = 1
521 }
522 },
523 Init = "Selected"
524 },
525}
526
527--// Global flags for styling
528type FlagFunc = {
529 Data: {
530 Class: {},
531 WindowClass: table?
532 },
533 Object: GuiObject
534}
535ReGui.ElementFlags = {
536 {
537 Properties = {"Center"},
538 Callback = function<FlagFunc>(Data, Object, Value)
539 local Position = Object.Position
540 ReGui:SetProperties(Object, {
541 Position = UDim2.new(
542 Value:find("X") and 0.5 or Position.X.Scale,
543 Position.X.Offset,
544 Value:find("Y") and 0.5 or Position.Y.Scale,
545 Position.Y.Offset
546 ),
547 AnchorPoint = Vector2.new(
548 Value:find("X") and 0.5 or 0,
549 Value:find("Y") and 0.5 or 0
550 )
551 })
552 end,
553 },
554 {
555 Properties = {"ElementStyle"},
556 Callback = function<StyleFunc>(Data, Object, Value)
557 ReGui:ApplyStyle(Object, Value)
558 end,
559 },
560 {
561 Properties = {"ColorTag"},
562 Callback = function<StyleFunc>(Data, Object, Value)
563 local Class = Data.Class
564 local WindowClass = Data.WindowClass
565 local NoAutoTheme = Class.NoAutoTheme
566
567 --// Check if theming is enabled
568 if not WindowClass then return end
569 if NoAutoTheme then return end
570
571 ReGui:UpdateColors({
572 Object = Object,
573 Tag = Value,
574 NoAnimation = true,
575 Theme = WindowClass.Theme,
576 })
577 end,
578 },
579 {
580 Properties = {"Animation"},
581 Callback = function<StyleFunc>(Data, Object, Value)
582 --// Check if animations are disabled
583 local NoAnimation = Data.Class.NoAnimation
584 if NoAnimation then return end
585
586 ReGui:SetAnimation(Object, Value)
587 end,
588 },
589 {
590 Properties = {"Icon", "IconSize", "IconRotation", "IconPadding"},
591 Callback = function<StyleFunc>(Data, Object, Value)
592 --// Locate icon element
593 local Icon = Object:FindFirstChild("Icon", true)
594 if not Icon then
595 return ReGui:Warn("No icon for", Object)
596 end
597
598 --// Check class data for missing values
599 local Class = Data.Class
600 ReGui:CheckConfig(Class, {
601 Icon = "",
602 IconSize = UDim2.fromScale(1,1),
603 IconRotation = 0,
604 IconPadding = UDim2.new(0, 2)
605 })
606
607 --// Apply icon padding
608 local Padding = Icon.Parent:FindFirstChild("UIPadding")
609 ReGui:SetPadding(Padding, Class.IconPadding)
610
611 --// Check image asset url
612 local Image = Class.Icon
613 Image = ReGui:CheckAssetUrl(Image)
614
615 ReGui:SetProperties(Icon, {
616 Visible = Icon ~= "",
617 Image = ReGui:CheckAssetUrl(Image),
618 Size = Class.IconSize,
619 Rotation = Class.IconRotation
620 })
621 end,
622 },
623 {
624 Properties = {"BorderThickness", "Border", "BorderColor"},
625 Callback = function<StyleFunc>(Data, Object, Value)
626 local Class = Data.Class
627 local WindowClass = Data.WindowClass
628 local Enabled = Class.Border == true
629
630 ReGui:CheckConfig(Class, {
631 BorderTransparency = Data:GetThemeKey("BorderTransparencyActive"),
632 BorderColor = Data:GetThemeKey("Border"),
633 BorderThickness = 1,
634 BorderStrokeMode = Enum.ApplyStrokeMode.Border,
635 })
636
637 --// Apply properties to UIStroke
638 local Stroke = ReGui:GetChildOfClass(Object, "UIStroke")
639 ReGui:SetProperties(Stroke, {
640 Transparency = Class.BorderTransparency,
641 Thickness = Class.BorderThickness,
642 Color = Class.BorderColor,
643 ApplyStrokeMode = Class.BorderStrokeMode,
644 Enabled = Enabled
645 })
646 end,
647 },
648 {
649 Properties = {"Ratio"},
650 Callback = function<StyleFunc>(Data, Object, Value)
651 local Class = Data.Class
652
653 ReGui:CheckConfig(Class, {
654 Ratio = 4/3,
655 RatioAxis = Enum.DominantAxis.Height,
656 RatioAspectType = Enum.AspectType.ScaleWithParentSize
657 })
658
659 --// Unpack data
660 local AspectRatio = Class.Ratio
661 local Axis = Class.RatioAxis
662 local AspectType = Class.RatioAspectType
663
664 local Ratio = ReGui:GetChildOfClass(Object, "UIAspectRatioConstraint")
665 ReGui:SetProperties(Ratio, {
666 DominantAxis = Axis,
667 AspectType = AspectType,
668 AspectRatio = AspectRatio
669 })
670 end,
671 },
672 {
673 Properties = {"FlexMode"},
674 Callback = function<StyleFunc>(Data, Object, Value)
675 local FlexItem = ReGui:GetChildOfClass(Object, "UIFlexItem")
676 FlexItem.FlexMode = Value
677 end,
678 },
679 {
680 --Recursive = true,
681 Properties = {"CornerRadius"},
682 Callback = function<StyleFunc>(Data, Object, Value)
683 local UICorner = ReGui:GetChildOfClass(Object, "UICorner")
684 UICorner.CornerRadius = Value
685 end,
686 },
687 {
688 Properties = {"Fill"},
689 Callback = function<StyleFunc>(Data, Object, Value)
690 if Value ~= true then return end
691
692 local Class = Data.Class
693
694 ReGui:CheckConfig(Class, {
695 Size = UDim2.fromScale(1, 1),
696 UIFlexMode = Enum.UIFlexMode.Fill,
697 AutomaticSize = Enum.AutomaticSize.None
698 })
699
700 --// Create FlexLayout property
701 local Flex = ReGui:GetChildOfClass(Object, "UIFlexItem")
702 Flex.FlexMode = Class.UIFlexMode
703
704 Object.Size = Class.Size
705 Object.AutomaticSize = Class.AutomaticSize
706 end,
707 },
708 {
709 Properties = {"Label"},
710 Callback = function<StyleFunc>(Data, Object, Value)
711 local Label = Object:FindFirstChild("Label")
712 if not Label then return end
713
714 local Class = Data.Class
715 function Class:SetLabel(Text)
716 Label.Text = Text
717 return self
718 end
719
720 Label.Text = tostring(Value)
721 end,
722 },
723 {
724 Properties = {"NoGradient"},
725 WindowProperties = {"NoGradients"},
726 Callback = function<StyleFunc>(Data, Object, Value)
727 local UIGradient = Object:FindFirstChildOfClass("UIGradient")
728 if not UIGradient then return end
729
730 UIGradient.Enabled = Value
731 end,
732 },
733 {
734 Properties = {
735 "UiPadding",
736 "PaddingBottom",
737 "PaddingTop",
738 "PaddingRight",
739 "PaddingTop"
740 },
741 Callback = function<StyleFunc>(Data, Object, Value)
742 Value = Value or 0
743
744 --// Convert number value into a UDim
745 if typeof(Value) == "number" then
746 Value = UDim.new(0, Value)
747 end
748
749 local Class = Data.Class
750
751 local IsUiPadding = Class.UiPadding
752 if IsUiPadding then
753 ReGui:CheckConfig(Class, {
754 PaddingBottom = Value,
755 PaddingLeft = Value,
756 PaddingRight = Value,
757 PaddingTop = Value,
758 })
759 end
760
761 local UIPadding = ReGui:GetChildOfClass(Object, "UIPadding")
762 ReGui:SetProperties(UIPadding, {
763 PaddingBottom = Class.PaddingBottom,
764 PaddingLeft = Class.PaddingLeft,
765 PaddingRight = Class.PaddingRight,
766 PaddingTop = Class.PaddingTop,
767 })
768 end,
769 },
770 {
771 Properties = {"Callback"},
772 Callback = function<StyleFunc>(Data, Object)
773 local Class = Data.Class
774
775 function Class:SetCallback(NewCallback)
776 self.Callback = NewCallback
777 return self
778 end
779 function Class:FireCallback(NewCallback)
780 self.Callback(Object)
781 return self
782 end
783 end,
784 },
785 {
786 Properties = {"Value"},
787 Callback = function<StyleFunc>(Data, Object)
788 local Class = Data.Class
789 ReGui:CheckConfig(Class, {
790 GetValue = function(self)
791 return Class.Value
792 end,
793 })
794 end,
795 }
796}
797
798type table = {
799 [any]: any
800}
801type ObjectTable = {
802 [GuiObject]: any
803}
804type TagsList = {
805 [GuiObject]: string
806}
807
808--// Compatibility
809local EmptyFunction = function() end
810local GetHiddenUI = get_hidden_gui or gethui
811local NewReference = cloneref or function(Ins): Instance
812 return Ins
813end
814
815--// Service handlers
816local Services = setmetatable({}, {
817 __index = function(self, Name: string)
818 local Service = game:GetService(Name)
819 return NewReference(Service)
820 end,
821})
822
823--// Core functions
824--// Services
825local HttpService = game:GetService("HttpService")
826local Players: Players = Services.Players
827local CoreGui = Services.CoreGui
828local UserInputService = Services.UserInputService
829local TweenService = Services.TweenService
830local RunService = Services.RunService
831
832--// Local player
833local LocalPlayer = Players.LocalPlayer
834ReGui.PlayerGui = LocalPlayer.PlayerGui
835ReGui.Mouse = LocalPlayer:GetMouse()
836
837--// Animation class
838local Animation = ReGui.Animation
839
840type AnimationTween = {
841 Object: Instance,
842 NoAnimation: boolean?,
843 Tweeninfo: TweenInfo?,
844 EndProperties: {},
845 Completed: (() -> any?)?
846}
847function Animation:Tween(Data: AnimationTween): Tween?
848 local DefaultTweenInfo = self.DefaultTweenInfo
849
850 --// Unpack animation data for the Tween
851 local Object = Data.Object
852 local NoAnimation = Data.NoAnimation
853 local Tweeninfo = Data.Tweeninfo or DefaultTweenInfo
854 local EndProperties = Data.EndProperties
855 local StartProperties = Data.StartProperties
856 local Completed = Data.Completed
857
858 --// Apply Start Properties to the object
859 if StartProperties then
860 ReGui:SetProperties(Object, StartProperties)
861 end
862
863 --// Set properties without a tween for NoAnimation flag
864 if NoAnimation then
865 ReGui:SetProperties(Object, EndProperties)
866
867 --// Invoke Completed event
868 if Completed then
869 Completed()
870 end
871 return
872 end
873
874 --// Create the tween animation
875 local MasterTween = nil
876 for Key, Value in next, EndProperties do
877 local Properties = {
878 [Key] = Value
879 }
880
881 --// Create the tween for the property
882 local Success, Tween = pcall(function()
883 return TweenService:Create(Object, Tweeninfo, Properties)
884 end)
885
886 --// Set Properties instead of tweening
887 if not Success then
888 ReGui:SetProperties(Object, Properties)
889 continue
890 end
891
892 --// Set the MasterTween if it does not exist
893 if not MasterTween then
894 MasterTween = Tween
895 end
896
897 Tween:Play()
898 end
899
900 --// Connect the TweenCompleted event
901 if Completed then
902 if MasterTween then
903 MasterTween.Completed:Connect(Completed)
904 else
905 Completed()
906 end
907 end
908
909 return MasterTween
910end
911
912type Animate = {
913 NoAnimation: boolean?,
914 Objects: ObjectTable,
915 Tweeninfo: TweenInfo?,
916 Completed: () -> any,
917}
918function Animation:Animate(Data: Animate): Tween
919 local NoAnimation = Data.NoAnimation
920 local Objects = Data.Objects
921 local Tweeninfo = Data.Tweeninfo
922 local Completed = Data.Completed
923
924 local BaseTween = nil
925
926 --// Create tweens
927 for Object, EndProperties in next, Objects do
928 local Tween = self:Tween({
929 NoAnimation = NoAnimation,
930 Object = Object,
931 Tweeninfo = Tweeninfo,
932 EndProperties = EndProperties
933 })
934
935 if not BaseTween then
936 BaseTween = Tween
937 end
938 end
939
940 --// Connect completed event call
941 if Completed then
942 BaseTween.Completed:Connect(Completed)
943 end
944
945 return BaseTween
946end
947
948type HeaderCollapseToggle = {
949 Rotations: {
950 Open: number?,
951 Closed: number?
952 },
953 Toggle: GuiObject,
954 NoAnimation: boolean?,
955 Collapsed: boolean,
956 Tweeninfo: TweenInfo?,
957}
958function Animation:HeaderCollapseToggle(Data: HeaderCollapseToggle)
959 --// Check configuration
960 ReGui:CheckConfig(Data, {
961 Rotations = {
962 Open = 90,
963 Closed = 0
964 }
965 })
966
967 --// Unpack configuration
968 local Toggle = Data.Toggle
969 local NoAnimation = Data.NoAnimation
970 local Rotations = Data.Rotations
971 local Collapsed = Data.Collapsed
972 local Tweeninfo = Data.Tweeninfo
973
974 local Rotation = Collapsed and Rotations.Closed or Rotations.Open
975
976 --// Animate toggle
977 self:Tween({
978 Tweeninfo = Tweeninfo,
979 NoAnimation = NoAnimation,
980 Object = Toggle,
981 EndProperties = {
982 Rotation = Rotation,
983 }
984 })
985end
986
987type HeaderCollapse = {
988 Collapsed: boolean,
989 ClosedSize: UDim2,
990 OpenSize: UDim2,
991 Toggle: Instance,
992 Resize: Instance?,
993 Hide: Instance?,
994 NoAnimation: boolean?,
995 NoAutomaticSize: boolean?,
996 IconOnly: boolean?,
997 Completed: (() -> any)?,
998 IconRotations: {
999 Open: number?,
1000 Closed: number?
1001 }
1002}
1003function Animation:HeaderCollapse(Data: HeaderCollapse): Tween
1004 --// Unpack config
1005 local Tweeninfo = Data.Tweeninfo
1006 local Collapsed = Data.Collapsed
1007 local ClosedSize = Data.ClosedSize
1008 local OpenSize: UDim2 = Data.OpenSize
1009 local Toggle = Data.Toggle
1010 local Resize = Data.Resize
1011 local Hide = Data.Hide
1012 local NoAnimation = Data.NoAnimation
1013 local NoAutomaticSize = Data.NoAutomaticSize
1014 local Rotations = Data.IconRotations
1015 local Completed = Data.Completed
1016
1017 --// Apply base properties
1018 if not NoAutomaticSize then
1019 Resize.AutomaticSize = Enum.AutomaticSize.None
1020 end
1021 if not Collapsed then
1022 Hide.Visible = true
1023 end
1024
1025 --// Build and play animation keyframes
1026 self:HeaderCollapseToggle({
1027 Tweeninfo = Tweeninfo,
1028 Collapsed = Collapsed,
1029 NoAnimation = NoAnimation,
1030 Toggle = Toggle,
1031 Rotations = Rotations
1032 })
1033
1034 local Tween = self:Tween({
1035 Tweeninfo = Tweeninfo,
1036 NoAnimation = NoAnimation,
1037 Object = Resize,
1038 StartProperties = {
1039 Size = Collapsed and OpenSize or ClosedSize
1040 },
1041 EndProperties = {
1042 Size = Collapsed and ClosedSize or OpenSize
1043 },
1044 Completed = function()
1045 Hide.Visible = not Collapsed
1046
1047 --// Invoke completed callback function
1048 if Completed then
1049 Completed()
1050 end
1051
1052 --// Reset AutomaticSize after animation
1053 if Collapsed then return end
1054 if NoAutomaticSize then return end
1055
1056 --// Reset sizes of the object
1057 Resize.Size = UDim2.fromScale(1, 0)
1058 Resize.AutomaticSize = Enum.AutomaticSize.Y
1059 end,
1060 })
1061
1062 return Tween
1063end
1064
1065--// Signal service
1066type SignalClass = {
1067 Connections: {
1068 [number]: (...any) -> nil
1069 },
1070 Fire: (SignalClass, ...any) -> nil,
1071 GetConnections: (SignalClass) -> table,
1072 Connect: (SignalClass, (...any) -> nil) -> table,
1073 DisconnectConnections: (SignalClass) -> nil,
1074}
1075
1076local Signaling = ReGui.Signaling
1077
1078local Signal: SignalClass = {}
1079Signal.__index = Signal
1080
1081function Signal:Fire(...)
1082 local Connections = self:GetConnections()
1083 if #Connections <= 0 then return end
1084
1085 for _, Connection in next, Connections do
1086 Connection(...)
1087 end
1088end
1089function Signal:GetConnections(): table
1090 local Connections = self.Connections
1091 return Connections
1092end
1093function Signal:Connect(Func: (...any) -> nil)
1094 local Connections = self:GetConnections()
1095 table.insert(Connections, Func)
1096end
1097function Signal:DisconnectConnections()
1098 local Connections = self:GetConnections()
1099 table.clear(Connections)
1100end
1101
1102function Signaling:NewSignal(): SignalClass
1103 return NewClass(Signal, {
1104 Connections = {}
1105 })
1106end
1107
1108function GetAndRemove(Key: string, Dict: table)
1109 local Value = Dict[Key]
1110 if Value then
1111 Dict[Key] = nil
1112 end
1113 return Value
1114end
1115
1116function MoveTableItem(Table: table, Item, NewPosition: number)
1117 local Index = table.find(Table, Item)
1118 if not Index then return end
1119
1120 local Value = table.remove(Table, Index)
1121 table.insert(Table, NewPosition, Value)
1122end
1123
1124function Merge(Base, New)
1125 for Key, Value in next, New do
1126 Base[Key] = Value
1127 end
1128end
1129
1130function Copy(Original: table, Insert: table?)
1131 local Table = table.clone(Original)
1132
1133 --// Merge Insert values
1134 if Insert then
1135 Merge(Table, Insert)
1136 end
1137
1138 return Table
1139end
1140
1141local function GetMatchPercentage(Value, Query: string): number
1142 Value = tostring(Value):lower()
1143 Query = Query:lower()
1144
1145 local Letters = Value:split("")
1146 local LetterCount = #Query
1147 local MatchedCount = 0
1148
1149 for Index, Letter in Letters do
1150 local Match = Query:sub(Index, Index)
1151
1152 --// Compare letters
1153 if Letter == Match then
1154 MatchedCount += 1
1155 end
1156 end
1157
1158 local Percentage = (MatchedCount/LetterCount) * 100
1159 return math.round(Percentage)
1160end
1161
1162local function SortByQuery(Table: table, Query: string): table
1163 local IsArray = Table[1]
1164 local Sorted = {}
1165
1166 for A, B in Table do
1167 local Value = IsArray and B or A
1168 local Percentage = GetMatchPercentage(Value, Query)
1169 local Position = 100 - Percentage
1170
1171 table.insert(Sorted, Position, Value)
1172 end
1173
1174 return Sorted
1175end
1176
1177function NewClass(Class, Merge)
1178 Merge = Merge or {}
1179 Class.__index = Class
1180 return setmetatable(Merge, Class)
1181end
1182
1183function ReGui:Warn(...: string?)
1184 warn("[ReGui]::", ...)
1185end
1186
1187function ReGui:IsDoubleClick(TickRange: number): boolean
1188 local ClickThreshold = self.DoubleClickThreshold
1189 return TickRange < ClickThreshold
1190end
1191
1192function ReGui:Init(Overwrites)
1193 Overwrites = Overwrites or {}
1194
1195 --// Check if the library has already initalised
1196 if self.Initialised then return end
1197
1198 --// Merge overwrites
1199 Merge(self, Overwrites)
1200 Merge(self, {
1201 Initialised = true,
1202 HasGamepad = self:IsConsoleDevice(),
1203 HasTouchScreen = self:IsMobileDevice(),
1204 })
1205
1206 --// Fetch folders
1207 self:CheckConfig(self, {
1208 ContainerParent = function()
1209 return self:ResolveUIParent()
1210 end,
1211 Prefabs = function()
1212 return self:LoadPrefabs()
1213 end,
1214 }, true)
1215
1216 --// Fetch required assets
1217 self:CheckConfig(self, {
1218 Container = function()
1219 return self:InsertPrefab("Container", {
1220 Parent = self.ContainerParent,
1221 Name = self.ContainerName
1222 })
1223 end,
1224 }, true)
1225
1226 --// Input events
1227 local Container = self.Container
1228 local TooltipOffset = self.TooltipOffset
1229 local ActiveTooltips = self.ActiveTooltips
1230 local Overlays = Container.Overlays
1231 local LastClick = 0
1232
1233 --// Create tooltips container
1234 self.TooltipsContainer = ReGui.Elements:Overlay({
1235 Parent = Overlays
1236 })
1237
1238 --// Key press
1239 UserInputService.InputBegan:Connect(function(Input: InputObject)
1240 if not self:IsMouseEvent(Input, true) then return end
1241
1242 local ClickTick = tick()
1243 local ClickRange = ClickTick - LastClick
1244 local IsDoubleClick = self:IsDoubleClick(ClickRange)
1245
1246 --// DoubleClick
1247 LastClick = IsDoubleClick and 0 or ClickTick
1248
1249 --// WindowActiveStates
1250 self:UpdateWindowFocuses()
1251 end)
1252
1253 local function InputUpdate()
1254 local Tooltips = self.TooltipsContainer
1255 local Visible = #ActiveTooltips > 0
1256 Tooltips.Visible = Visible
1257
1258 if not Visible then return end
1259
1260 --// Set frame position to mosue location
1261 local X, Y = ReGui:GetMouseLocation()
1262 local Position = Overlays.AbsolutePosition
1263
1264 Tooltips.Position = UDim2.fromOffset(
1265 X - Position.X + TooltipOffset,
1266 Y - Position.Y + TooltipOffset
1267 )
1268 end
1269
1270 --// Bind events
1271 RunService:BindToRenderStep("ReGui_InputUpdate", Enum.RenderPriority.Input.Value, InputUpdate)
1272end
1273
1274function ReGui:GetVersion(): string
1275 return self.Version
1276end
1277
1278function ReGui:IsMobileDevice(): boolean
1279 return UserInputService.TouchEnabled
1280end
1281
1282function ReGui:IsConsoleDevice(): boolean
1283 return UserInputService.GamepadEnabled
1284end
1285
1286function ReGui:GetScreenSize(): Vector2
1287 return workspace.CurrentCamera.ViewportSize
1288end
1289
1290function ReGui:LoadPrefabs(): Folder?
1291 local PlayerGui = self.PlayerGui
1292 local Name = "ReGui-Prefabs"
1293
1294 --// Check script for prefabs
1295 local ScriptUi = script:WaitForChild(Name, 2)
1296 if ScriptUi then return ScriptUi end
1297
1298 --// Check PlayerGui for prefabs (Studio Debug)
1299 local PlayerUI = PlayerGui:WaitForChild(Name, 2)
1300 if PlayerUI then return PlayerUI end
1301
1302 return nil
1303end
1304
1305function ReGui:ResolveUIParent(): GuiObject?
1306 local PlayerGui = self.PlayerGui
1307 local Debug = self.Debug
1308
1309 local Steps = {
1310 [1] = function()
1311 local Parent = GetHiddenUI()
1312 if Parent.Parent == CoreGui then return end
1313
1314 return Parent
1315 end,
1316 [2] = function()
1317 return CoreGui
1318 end,
1319 [3] = function()
1320 return PlayerGui
1321 end
1322 }
1323
1324 local Test = self:CreateInstance("ScreenGui")
1325
1326 --// Test each step for a successful parent
1327 for Step, Func in next, Steps do
1328 --// Test fetching the parent
1329 local Success, Parent = pcall(Func)
1330 if not Success or not Parent then continue end
1331
1332 --// Test parenting
1333 local CanParent = pcall(function()
1334 Test.Parent = Parent
1335 end)
1336 if not CanParent then continue end
1337
1338 if Debug then
1339 self:Warn(`Step: {Step} was chosen as the parent!: {Parent}`)
1340 end
1341
1342 return Parent
1343 end
1344
1345 --// Error message
1346 self:Warn("The ReGui container does not have a parent defined")
1347
1348 return nil
1349end
1350
1351function ReGui:CheckConfig(Source: table, Base: table, Call: boolean?, IgnoreKeys: table?)
1352 if not Source then return end
1353
1354 for Key: string?, Value in next, Base do
1355 if Source[Key] ~= nil then continue end
1356
1357 --// Check the key should be ignored
1358 if IgnoreKeys then
1359 if table.find(IgnoreKeys, Key) then continue end
1360 end
1361
1362 --// Call value function
1363 if Call then
1364 Value = Value()
1365 end
1366
1367 --// Set value
1368 Source[Key] = Value
1369 end
1370
1371 return Source
1372end
1373
1374function ReGui:CheckAssetUrl(Url: (string|number)): string
1375 --// Convert Id number to asset URL
1376 if tonumber(Url) then
1377 return `rbxassetid://{Url}`
1378 end
1379 return Url
1380end
1381
1382function ReGui:CreateInstance(Class, Parent, Properties): Instance
1383 local Object = Instance.new(Class, Parent)
1384
1385 --// Apply Properties
1386 if Properties then
1387 local UseProps = Properties.UsePropertiesList
1388
1389 if not UseProps then
1390 self:SetProperties(Object, Properties)
1391 else
1392 self:ApplyFlags({
1393 Object = Object,
1394 Class = Properties
1395 })
1396 end
1397 end
1398
1399 return Object
1400end
1401
1402function ReGui:ConnectMouseEvent(Object: GuiObject, Config)
1403 local Callback = Config.Callback
1404 local DoubleClick = Config.DoubleClick
1405 local OnlyMouseHovering = Config.OnlyMouseHovering
1406
1407 local LastClick = 0
1408 local HoverSignal = nil
1409
1410 if OnlyMouseHovering then
1411 HoverSignal = self:DetectHover(OnlyMouseHovering)
1412 end
1413
1414 Object.Activated:Connect(function(...)
1415 local ClickTick = tick()
1416 local ClickRange = ClickTick-LastClick
1417
1418 --// OnlyMouseHovering
1419 if HoverSignal and not HoverSignal.Hovering then return end
1420
1421 --// DoubleClick
1422 if DoubleClick then
1423 if not ReGui:IsDoubleClick(ClickRange) then
1424 LastClick = ClickTick
1425 return
1426 end
1427 LastClick = 0
1428 end
1429
1430 Callback(...)
1431 end)
1432end
1433
1434function ReGui:GetAnimation(Animate: boolean?)
1435 return Animate and self.Animation or TweenInfo.new(0)
1436end
1437
1438function ReGui:GetDictSize(Dict: table): number
1439 local Count = 0
1440 for Key, Value in Dict do
1441 Count += 1
1442 end
1443 return Count
1444end
1445
1446function ReGui:RemoveAnimations(Object: GuiObject)
1447 local Data = self:GetAnimationData(Object)
1448 local Connections = Data.Connections
1449
1450 --// Disconnect each connection
1451 for _, Connection in next, Connections do
1452 Connection:Disconnect()
1453 end
1454end
1455
1456function ReGui:GetAnimationData(Object: GuiObject): table
1457 local Connections = self.AnimationConnections
1458 local Existing = Connections[Object]
1459
1460 --// Check for existing
1461 if Existing then return Existing end
1462
1463 local Data = {
1464 Connections = {}
1465 }
1466
1467 Connections[Object] = Data
1468 return Data
1469end
1470
1471function ReGui:AddAnimationSignal(Object: GuiObject, Connection: RBXScriptSignal)
1472 local Data = self:GetAnimationData(Object)
1473 local Connections = Data.Connections
1474
1475 table.insert(Connections, Connection)
1476end
1477
1478function ReGui:SetAnimationsEnabled(Enabled: boolean)
1479 self.NoAnimations = not Enabled
1480end
1481
1482function ReGui:SetAnimation(Object: GuiObject, Reference: (string|table), Listener: GuiObject?)
1483 Listener = Listener or Object
1484
1485 local Animations = self.Animations
1486
1487 --// Get animation properties
1488 local Data = Reference
1489 if typeof(Reference) ~= "table" then
1490 Data = Animations[Reference]
1491 end
1492
1493 assert(Data, `No animation data for Class {Reference}!`)
1494
1495 --// Disconnect previous
1496 self:RemoveAnimations(Listener)
1497
1498 --// Unpack data
1499 local Init = Data.Init
1500 local Connections = Data.Connections
1501 local Tweeninfo = Data.Tweeninfo
1502 local NoAnimation = Data.NoAnimation
1503
1504 --// Get animation data
1505 local StateData = self:GetAnimationData(Object)
1506 local State = StateData.State
1507
1508 --// Connect signals
1509 local InitFunc = nil
1510 local AnimationEnabled = true
1511 local CurrentSignal = nil
1512 local Signals = {}
1513
1514 --// Interface for the animation
1515 local Module = {}
1516 function Module:Reset(NoAnimation: boolean?)
1517 if not InitFunc then return end
1518 InitFunc(NoAnimation)
1519 end
1520 function Module:FireSignal(SignalName: string, NoAnimation: boolean?)
1521 Signals[SignalName](NoAnimation)
1522 end
1523 function Module:Refresh(NoAnimation: boolean?)
1524 if not CurrentSignal then return end
1525 Signals[CurrentSignal](NoAnimation)
1526 end
1527 function Module:SetEnabled(Enabled: boolean)
1528 AnimationEnabled = Enabled
1529 end
1530
1531 for SignalName: string, Properties in next, Connections do
1532 local function OnSignal(NoAnim: boolean?)
1533 NoAnim = NoAnim == true --// Convert to boolean
1534 CurrentSignal = SignalName
1535
1536 --// Check if animations are enabled
1537 local NoAnimations = self.NoAnimations
1538 if NoAnimations then return end
1539
1540 --// Check if the animation is enabled
1541 if not AnimationEnabled then return end
1542
1543 StateData.State = SignalName
1544
1545 Animation:Tween({
1546 NoAnimation = NoAnim or NoAnimation,
1547 Object = Object,
1548 Tweeninfo = Tweeninfo,
1549 EndProperties = Properties
1550 })
1551 end
1552
1553 --// Connect animation to signal
1554 local Signal = Listener[SignalName]
1555 local Connection = Signal:Connect(OnSignal)
1556
1557 --// Collect signal into array
1558 self:AddAnimationSignal(Listener, Connection)
1559
1560 Signals[SignalName] = OnSignal
1561
1562 --// Call init connection
1563 if SignalName == Init then
1564 InitFunc = OnSignal
1565 end
1566 end
1567
1568 if State then
1569 --// Update the animation to the previous state, e.g MouseHover
1570 Module:FireSignal(State)
1571 else
1572 --// Update the animation state to default
1573 Module:Reset(true)
1574 end
1575
1576 return Module
1577end
1578
1579function ReGui:GetChildOfClass(Object: GuiObject, ClassName: string): GuiObject
1580 local Child = Object:FindFirstChildOfClass(ClassName)
1581
1582 --// Create missing child
1583 if not Child then
1584 Child = self:CreateInstance(ClassName, Object)
1585 end
1586
1587 return Child
1588end
1589
1590function ReGui:SetPadding(UiPadding: UIPadding, Padding: UDim)
1591 if not UiPadding then return end
1592
1593 self:SetProperties(UiPadding, {
1594 PaddingBottom = Padding,
1595 PaddingLeft = Padding,
1596 PaddingRight = Padding,
1597 PaddingTop = Padding
1598 })
1599end
1600
1601export type ConnectDrag = {
1602 DragStart: () -> nil,
1603 DragEnd: () -> nil,
1604 DragMovement: () -> nil,
1605}
1606function ReGui:ConnectDrag(Frame: GuiObject, Data)
1607 self:CheckConfig(Data, {
1608 DragStart = EmptyFunction,
1609 DragEnd = EmptyFunction,
1610 DragMovement = EmptyFunction,
1611 OnDragStateChange = EmptyFunction,
1612 })
1613
1614 --// Unpack Configuration
1615 local DragStart = Data.DragStart
1616 local DragEnd = Data.DragEnd
1617 local DragMovement = Data.DragMovement
1618 local OnDragStateChange = Data.OnDragStateChange
1619
1620 --// Whitelist
1621 local UserInputTypes = {
1622 StartAndEnd = {
1623 Enum.UserInputType.MouseButton1,
1624 Enum.UserInputType.Touch
1625 },
1626 Movement = {
1627 Enum.UserInputType.MouseMovement,
1628 Enum.UserInputType.Touch
1629 }
1630 }
1631
1632 local IsDragging = false
1633
1634 local function InputTypeAllowed(Key, Type: string)
1635 local InputType = Key.UserInputType
1636 return table.find(UserInputTypes[Type], InputType)
1637 end
1638 local function KeyToVector(Key): Vector2
1639 local InputPosition = Key.Position
1640 return Vector2.new(InputPosition.X, InputPosition.Y)
1641 end
1642 local function SetIsDragging(DraggingState: boolean)
1643 --// Globally disable drag on other objects
1644 self._DraggingDisabled = DraggingState
1645
1646 IsDragging = DraggingState
1647 OnDragStateChange(DraggingState)
1648 end
1649 local function MakeSignal(Data)
1650 local IsDraggingState = Data.IsDragging
1651 local InputType = Data.InputType
1652 local Callback = Data.Callback
1653
1654 return function(Key)
1655 if Data.DraggingRequired ~= IsDragging then return end
1656 if Data.CheckDraggingDisabled and self._DraggingDisabled then return end
1657 if not InputTypeAllowed(Key, InputType) then return end
1658
1659 --// Update drag state
1660 if Data.UpdateState then
1661 SetIsDragging(IsDraggingState)
1662 end
1663
1664 local InputVector = KeyToVector(Key)
1665 Callback(InputVector)
1666 end
1667 end
1668
1669 --// Connect movement events
1670 Frame.InputBegan:Connect(MakeSignal({
1671 CheckDraggingDisabled = true,
1672 DraggingRequired = false,
1673 UpdateState = true,
1674 IsDragging = true,
1675 InputType = "StartAndEnd",
1676 Callback = DragStart,
1677 }))
1678 UserInputService.InputEnded:Connect(MakeSignal({
1679 DraggingRequired = true,
1680 UpdateState = true,
1681 IsDragging = false,
1682 InputType = "StartAndEnd",
1683 Callback = DragEnd,
1684 }))
1685 UserInputService.InputChanged:Connect(MakeSignal({
1686 DraggingRequired = true,
1687 InputType = "Movement",
1688 Callback = DragMovement,
1689 }))
1690end
1691
1692type MakeDraggableFlags = {
1693 Move: Instance,
1694 Grab: Instance,
1695 Enabled: boolean?,
1696 OnUpdate: ((Vector2) -> ...any)?,
1697 DragBegin: ((InputObject) -> ...any)?,
1698 StateChanged: ((MakeDraggableFlags) -> any)?
1699}
1700function ReGui:MakeDraggable(Config: MakeDraggableFlags)
1701 --// Unpack config
1702 local Move = Config.Move
1703 local Grab = Config.Grab
1704 local OnDragStateChange = Config.OnDragStateChange
1705
1706 local PositionOrgin = nil
1707 local InputOrgin = nil
1708
1709 --// Interface
1710 local Interface = {}
1711 function Interface:SetEnabled(State: boolean)
1712 local StateChanged = Config.StateChanged
1713 self.Enabled = State
1714 --DragDetector.Enabled = State
1715
1716 --// Invoke the state changed callback function
1717 if StateChanged then
1718 StateChanged(self)
1719 end
1720 end
1721 function Interface:CanDrag(Key)
1722 if not self.Enabled then return end
1723 return true
1724 end
1725
1726 --// Movement event functions
1727 local function DragStart(InputVector)
1728 if not Interface:CanDrag() then return end
1729 local DragBegin = Config.DragBegin
1730
1731 InputOrgin = InputVector
1732 DragBegin(InputOrgin)
1733 end
1734
1735 local function DragMovement(InputVector)
1736 if not Interface:CanDrag() then return end
1737
1738 local Delta = InputVector - InputOrgin
1739 local OnUpdate = Config.OnUpdate
1740
1741 OnUpdate(Delta)
1742 end
1743
1744 --// Movement functions
1745 local function PositionBegan(Key)
1746 PositionOrgin = Move.Position
1747 end
1748 local function UpdatePosition(Delta: number)
1749 local Position = UDim2.new(
1750 PositionOrgin.X.Scale,
1751 PositionOrgin.X.Offset + Delta.X,
1752 PositionOrgin.Y.Scale,
1753 PositionOrgin.Y.Offset + Delta.Y
1754 )
1755 Config:SetPosition(Position)
1756 end
1757 local function SetPosition(self, Position: UDim2)
1758 --// Tween frame element to the new size
1759 Animation:Tween({
1760 Object = Move,
1761 EndProperties = {
1762 Position = Position
1763 }
1764 })
1765 end
1766
1767 --// Check configuration
1768 self:CheckConfig(Config, {
1769 Enabled = true,
1770 OnUpdate = UpdatePosition,
1771 SetPosition = SetPosition,
1772 DragBegin = PositionBegan
1773 })
1774
1775 --// Connect movement events
1776 self:ConnectDrag(Grab, {
1777 DragStart = DragStart,
1778 DragMovement = DragMovement,
1779 OnDragStateChange = OnDragStateChange
1780 })
1781
1782 --// Set enabled state
1783 local Enabled = Config.Enabled
1784 Interface:SetEnabled(Enabled)
1785
1786 return Interface
1787end
1788
1789export type MakeResizableFlags = {
1790 MinimumSize: Vector2,
1791 MaximumSize: Vector2?,
1792 --Grab: Instance,
1793 Resize: Instance,
1794 OnUpdate: (UDim2) -> ...any
1795}
1796function ReGui:MakeResizable(Config: MakeResizableFlags)
1797 ReGui:CheckConfig(Config, {
1798 MinimumSize = Vector2.new(160, 90),
1799 MaximumSize = Vector2.new(math.huge, math.huge)
1800 })
1801
1802 --// Unpack config
1803 local MaximumSize = Config.MaximumSize
1804 local MinimumSize = Config.MinimumSize
1805 local Resize = Config.Resize
1806 local OnUpdate = Config.OnUpdate
1807
1808 local SizeOrgin = nil
1809
1810 --// Create grab element
1811 local Grab = ReGui:InsertPrefab("ResizeGrab", {
1812 Parent = Resize
1813 })
1814
1815 local function StateChanged(Interface)
1816 Grab.Visible = Interface.Enabled
1817 end
1818
1819 --// Resize functions
1820 local function UpdateSize(Delta)
1821 local NewSize = SizeOrgin + Delta
1822
1823 --// Clamp size
1824 local Size = UDim2.fromOffset(
1825 math.clamp(NewSize.X, MinimumSize.X, MaximumSize.X),
1826 math.clamp(NewSize.Y, MinimumSize.Y, MaximumSize.Y)
1827 )
1828
1829 --// Call update function instead of tweening
1830 if OnUpdate then
1831 OnUpdate(Size)
1832 return
1833 end
1834
1835 --// Tween frame element to the new size
1836 Animation:Tween({
1837 Object = Resize,
1838 EndProperties = {
1839 Size = Size
1840 }
1841 })
1842 end
1843 local function ResizeBegin(InputPosition)
1844 SizeOrgin = Resize.AbsoluteSize
1845 end
1846
1847 --// Connect movement events
1848 local DragDetection = self:MakeDraggable({
1849 Grab = Grab,
1850 OnUpdate = UpdateSize,
1851 DragBegin = ResizeBegin,
1852 StateChanged = StateChanged
1853 })
1854
1855 DragDetection.Grab = Grab
1856
1857 return DragDetection
1858end
1859
1860function ReGui:IsMouseEvent(Input: InputObject, IgnoreMovement: boolean)
1861 local Name = Input.UserInputType.Name
1862
1863 --// IgnoreMovement
1864 if IgnoreMovement and Name:find("Movement") then return end
1865
1866 return Name:find("Touch") or Name:find("Mouse")
1867end
1868
1869export type DetectHover = {
1870 OnInput: ((boolean, InputObject?) -> ...any?)?,
1871 Anykey: boolean?,
1872 MouseMove: boolean?,
1873 MouseOnly: boolean?,
1874 MouseEnter: boolean?,
1875 Hovering: boolean?,
1876}
1877function ReGui:DetectHover(Object: GuiObject, Config: DetectHover)
1878 Config = Config or {}
1879
1880 --// Unpack configuration
1881 local OnInput = Config.OnInput
1882 local OnHoverChange = Config.OnHoverChange
1883 local Anykey = Config.Anykey
1884 local MouseMove = Config.MouseMove
1885 local MouseEnter = Config.MouseEnter
1886 local MouseOnly = Config.MouseOnly
1887
1888 Config.Hovering = false
1889
1890 local function Update(Input, IsHovering: boolean?, IsMouseEvent: boolean?)
1891 --// Check if the input is mouse or touch
1892 if Input and MouseOnly then
1893 if not ReGui:IsMouseEvent(Input, true) then return end
1894 end
1895
1896 --// Set new IsHovering state
1897 if IsHovering ~= nil then
1898 local Previous = Config.Hovering
1899 Config.Hovering = IsHovering
1900
1901 --// Invoke OnHoverChange
1902 if IsHovering ~= Previous and OnHoverChange then
1903 OnHoverChange(IsHovering)
1904 end
1905 end
1906
1907 --// Mouse Enter events
1908 if not MouseEnter and IsMouseEvent then return end
1909
1910 --// Call OnInput function
1911 if OnInput then
1912 local Value = Config.Hovering
1913 return OnInput(Value, Input)
1914 end
1915 end
1916
1917 --// Connect Events
1918 local Connections = {
1919 Object.MouseEnter:Connect(function()
1920 Update(nil, true, true)
1921 end),
1922 Object.MouseLeave:Connect(function()
1923 Update(nil, false, true)
1924 end)
1925 }
1926
1927 --// Update on keyboard events or Mouse eveents
1928 if Anykey or MouseOnly then
1929 table.insert(Connections, UserInputService.InputBegan:Connect(function(Input)
1930 Update(Input)
1931 end))
1932 end
1933
1934 --// Update on mouse move
1935 if MouseMove then
1936 local Connection = Object.MouseMoved:Connect(function()
1937 Update()
1938 end)
1939 table.insert(Connections, Connection)
1940 end
1941
1942 function Config:Disconnect()
1943 for _, Connection in next, Connections do
1944 Connection:Disconnect()
1945 end
1946 end
1947
1948 return Config
1949end
1950
1951function ReGui:StackWindows()
1952 local Windows = self.Windows
1953 local Offset = 20
1954
1955 for Index, Class in next, Windows do
1956 local Window = Class.WindowFrame
1957
1958 local Position = UDim2.fromOffset(Offset*Index, Offset*Index)
1959
1960 Class:Center()
1961 Window.Position += Position
1962 end
1963end
1964
1965function ReGui:GetElementFlags(Object: GuiObject): table?
1966 local Cache = self._FlagCache
1967 return Cache[Object]
1968end
1969
1970type UpdateColors = {
1971 Object: GuiObject,
1972 Tag: (string|table),
1973 NoAnimation: boolean?,
1974 Theme: string?,
1975 TagsList: TagsList?,
1976 Tweeninfo: TweenInfo?
1977}
1978function ReGui:UpdateColors(Config: UpdateColors)
1979 --// Unpack config
1980 local Object = Config.Object
1981 local Tag = Config.Tag
1982 local NoAnimation = Config.NoAnimation
1983 local Elements = Config.TagsList
1984 local Theme = Config.Theme
1985 local Tweeninfo = Config.Tweeninfo
1986
1987 --// Unpack global configuration
1988 local ElementColors = self.ElementColors
1989 local Themes = self.ThemeConfigs
1990 local Debug = self.Debug
1991 local Flags = self:GetElementFlags(Object)
1992
1993 local Coloring = ElementColors[Tag]
1994
1995 --// Resolve string into color data
1996 if typeof(Coloring) == "string" then
1997 Coloring = ElementColors[Coloring]
1998 end
1999
2000 if typeof(Tag) == "table" then
2001 Coloring = Tag
2002 elseif Elements then
2003 Elements[Object] = Tag --// Update the element's tag in the dict
2004 end
2005
2006 --// Check if coloring data exists
2007 if not Coloring then return end
2008
2009 --// Add coloring data to properties
2010 local Properties = {}
2011 for Key: string, Name: string in next, Coloring do
2012 local Color = self:GetThemeKey(Theme, Name)
2013
2014 --// Ignore if flags has a overwrite
2015 if Flags and Flags[Key] then
2016 continue
2017 end
2018
2019 --// Color not found debug
2020 if not Color then
2021 if Debug then
2022 self:Warn(`Color: '{Name}' does not exist!`)
2023 end
2024 continue
2025 end
2026
2027 Properties[Key] = Color
2028 end
2029
2030 --// Tween new properties
2031 Animation:Tween({
2032 Tweeninfo = Tweeninfo,
2033 Object = Object,
2034 NoAnimation = NoAnimation,
2035 EndProperties = Properties
2036 })
2037end
2038
2039export type MultiUpdateColorsConfig = {
2040 Objects: ObjectsTable,
2041 TagsList: TagsList?,
2042 Theme: string?,
2043 Animate: boolean?,
2044 Tweeninfo: TweenInfo?
2045}
2046function ReGui:MultiUpdateColors(Config: MultiUpdateColorsConfig)
2047 local Objects = Config.Objects
2048
2049 for Object: GuiObject, Tag: string? in next, Objects do
2050 self:UpdateColors({
2051 TagsList = Config.TagsList,
2052 Theme = Config.Theme,
2053 NoAnimation = not Config.Animate,
2054 Tweeninfo = Config.Tweeninfo,
2055
2056 Object = Object,
2057 Tag = Tag,
2058 })
2059 end
2060end
2061
2062function ReGui:ApplyStyle(Object: GuiObject, StyleName: string)
2063 local Styles = self.Styles
2064
2065 local Style = Styles[StyleName]
2066 if not Style then return end
2067
2068 --// Apply style properties
2069 self:ApplyFlags({
2070 Object = Object,
2071 Class = Style
2072 })
2073end
2074
2075function ReGui:MergeMetatables(Class, Object: GuiObject)
2076 local Debug = self.Debug
2077 local Metadata = {}
2078
2079 Metadata.__index = function(_, Key: string)
2080 --// Fetch value from class
2081 local Value = Class[Key]
2082 if Value ~= nil then return Value end
2083
2084 --// Fetch value from Object
2085 local Success, Value = pcall(function()
2086 local Value = Object[Key]
2087 return self:PatchSelf(Object, Value)
2088 end)
2089
2090 return Success and Value or nil
2091 end
2092
2093 Metadata.__newindex = function(_, Key: string, Value)
2094 local IsClassValue = Class[Key] ~= nil or typeof(Value) == "function"
2095
2096 if IsClassValue then
2097 Class[Key] = Value
2098 return
2099 end
2100
2101 xpcall(function()
2102 Object[Key] = Value
2103 end, function(err)
2104 if Debug then
2105 self:Warn(`Newindex Error: {Object}.{Key} = {Value}\n{err}`)
2106 end
2107
2108 Class[Key] = Value
2109 end)
2110 end
2111
2112 return setmetatable({}, Metadata)
2113end
2114
2115function ReGui:Concat(Table, Separator: " ")
2116 local Concatenated = ""
2117 for Index, String in next, Table do
2118 Concatenated ..= tostring(String) .. (Index ~= #Table and Separator or "")
2119 end
2120 return Concatenated
2121end
2122
2123function ReGui:GetValueFromAliases(Aliases, Table)
2124 for _, Alias: string in Aliases do
2125 local Value = Table[Alias]
2126 if Value ~= nil then
2127 return Value
2128 end
2129 end
2130
2131 return nil
2132end
2133
2134function ReGui:RecursiveCall(Object: GuiObject, Func: (GuiObject)->...any)
2135 for _, Child in next, Object:GetDescendants() do
2136 Func(Child)
2137 end
2138end
2139
2140export type ApplyFlags = {
2141 Object: Instance,
2142 Class: table,
2143 WindowClass: table?
2144}
2145function ReGui:ApplyFlags(Config: ApplyFlags)
2146 local Properties = self.ElementFlags
2147
2148 --// Unpack config
2149 local Object = Config.Object
2150 local Class = Config.Class
2151 local WindowClass = Config.WindowClass
2152
2153 function Config:GetThemeKey(Tag: string)
2154 if WindowClass then
2155 return WindowClass:GetThemeKey(Tag)
2156 else
2157 return ReGui:GetThemeKey(nil, Tag)
2158 end
2159 end
2160
2161 --// Set base properties
2162 self:SetProperties(Object, Class)
2163
2164 --// Check for callbacks
2165 for _, Flag in next, Properties do
2166 local Aliases = Flag.Properties
2167 local Callback = Flag.Callback
2168 local Recursive = Flag.Recursive
2169 local WindowFlags = Flag.WindowProperties
2170
2171 --// Find value from element class
2172 local Value = self:GetValueFromAliases(Aliases, Class)
2173
2174 --// Find value from window class
2175 if WindowClass and WindowFlags and Value == nil then
2176 Value = self:GetValueFromAliases(WindowFlags, WindowClass)
2177 end
2178
2179 if Value == nil then continue end
2180
2181 --// Apply flag
2182 Callback(Config, Object, Value)
2183
2184 --// Recursively apply flag
2185 if Recursive then
2186 self:RecursiveCall(Object, function(Child)
2187 Callback(Config, Child, Value)
2188 end)
2189 end
2190 end
2191end
2192
2193function ReGui:SetProperties(Object: Instance, Properties: table)
2194 for Key: string, Value in next, Properties do
2195 pcall(function()
2196 Object[Key] = Value
2197 end)
2198 end
2199end
2200
2201function ReGui:InsertPrefab(Name: string, Properties): GuiObject
2202 local Folder = self.Prefabs
2203 local Prefabs = Folder.Prefabs
2204
2205 local Prefab = Prefabs:WaitForChild(Name)
2206 local Object = Prefab:Clone()
2207
2208 --// Apply properties
2209 if Properties then
2210 local UseProps = Properties.UsePropertiesList
2211
2212 if not UseProps then
2213 self:SetProperties(Object, Properties)
2214 else
2215 self:ApplyFlags({
2216 Object = Object,
2217 Class = Properties
2218 })
2219 end
2220 end
2221
2222 return Object
2223end
2224
2225function ReGui:GetContentSize(Object: GuiObject, IngoreUIList: boolean?): Vector2
2226 local UIListLayout = Object:FindFirstChildOfClass("UIListLayout")
2227 local UIPadding = Object:FindFirstChildOfClass("UIPadding")
2228 local UIStroke = Object:FindFirstChildOfClass("UIStroke")
2229
2230 local ContentSize: Vector2
2231
2232 --// Fetch absolute size
2233 if UIListLayout and not IngoreUIList then
2234 ContentSize = UIListLayout.AbsoluteContentSize
2235 else
2236 ContentSize = Object.AbsoluteSize
2237 end
2238
2239 --// Apply padding
2240 if UIPadding then
2241 local Top = UIPadding.PaddingTop.Offset
2242 local Bottom = UIPadding.PaddingBottom.Offset
2243 local Left = UIPadding.PaddingLeft.Offset
2244 local Right = UIPadding.PaddingRight.Offset
2245
2246 ContentSize += Vector2.new(Left+Right, Top+Bottom)
2247 end
2248
2249 if UIStroke then
2250 local Thickness = UIStroke.Thickness
2251 ContentSize += Vector2.new(Thickness/2, Thickness/2)
2252 end
2253
2254 return ContentSize
2255end
2256
2257function ReGui:PatchSelf(Self, Func)
2258 --// Check if the passed value is a function
2259 if typeof(Func) ~= "function" then
2260 return Func
2261 end
2262
2263 return function(_, ...)
2264 return Func(Self, ...)
2265 end
2266end
2267
2268type MakeCanvas = {
2269 Element: Instance,
2270 WindowClass: WindowClass?,
2271 Class: {}?
2272}
2273function ReGui:MakeCanvas(Config: MakeCanvas)
2274 --// Unpack ReGui data
2275 local ElementsClass = self.Elements
2276 local Debug = self.Debug
2277 local Signaling = self.Signaling
2278
2279 --// Unpack configuration
2280 local Element = Config.Element
2281 local WindowClass = Config.WindowClass
2282 local Class = Config.Class
2283 local OnChildChange = Config.OnChildChange
2284
2285 local ChildChangeSignal = Signaling:NewSignal()
2286
2287 --// Connect OnChildChange argument
2288 if OnChildChange then
2289 ChildChangeSignal:Connect(OnChildChange)
2290 end
2291
2292 --// Debug report
2293 if not WindowClass and Debug then
2294 self:Warn(`No WindowClass for {Element}`)
2295 self:Warn(Config)
2296 end
2297
2298 --// Create new canvas class
2299 local Canvas = NewClass(ElementsClass, {
2300 Class = Class,
2301 RawObject = Element,
2302 WindowClass = WindowClass or false,
2303 OnChildChange = ChildChangeSignal,
2304 Elements = {}
2305 })
2306
2307 --// Create metatable merge
2308 local Meta = {
2309 __index = function(_, Key: string)
2310 --// Check Canvas class for value
2311 local CanvasValue = Canvas[Key]
2312 if CanvasValue ~= nil then
2313 return self:PatchSelf(Canvas, CanvasValue)
2314 end
2315
2316 --// Check class for value
2317 local ClassValue = Class[Key]
2318 if ClassValue ~= nil then
2319 return self:PatchSelf(Class, ClassValue)
2320 end
2321
2322 --// Fetch value from Element
2323 local ElementValue = Element[Key]
2324 return self:PatchSelf(Element, ElementValue)
2325 end,
2326 __newindex = function(self, Key: string, Value)
2327 local IsClassValue = Class[Key] ~= nil
2328
2329 --// Update key value
2330 if IsClassValue then
2331 Class[Key] = Value
2332 else
2333 Element[Key] = Value
2334 end
2335 end,
2336 }
2337
2338 return setmetatable({}, Meta)
2339end
2340
2341--// Ini service
2342function ReGui:GetIniData(Class): table
2343 local IniToSave = self.IniToSave
2344 local Ini = {}
2345
2346 for _, Name in next, IniToSave do
2347 Ini[Name] = Class[Name]
2348 end
2349
2350 return Ini
2351end
2352
2353function ReGui:DumpIni(JsonEncode: boolean?): table
2354 local IniSettings = self.IniSettings
2355 local Parsed = {}
2356
2357 for Flag, Element in next, IniSettings do
2358 Parsed[Flag] = self:GetIniData(Element)
2359 end
2360
2361 --// Parse into Json string
2362 if JsonEncode then
2363 return HttpService:JSONEncode(Parsed)
2364 end
2365
2366 return Parsed
2367end
2368
2369function ReGui:LoadIniIntoElement(Element, Values: table)
2370 local ValueFunctions = {
2371 ["Value"] = function(Value)
2372 Element:SetValue(Value)
2373 end,
2374 }
2375
2376 for Name, Value in next, Values do
2377 --// Check if setting the value requires a function call
2378 local SetValue = ValueFunctions[Name]
2379 if SetValue then
2380 SetValue(Value)
2381 continue
2382 end
2383
2384 Element[Name] = Value
2385 end
2386end
2387
2388function ReGui:LoadIni(NewSettings: (table|string), JsonEncoded: boolean?)
2389 local IniSettings = self.IniSettings
2390 assert(NewSettings, "No Ini configuration was passed")
2391
2392 --// Decode Json into a dict table
2393 if JsonEncoded then
2394 NewSettings = HttpService:JSONDecode(NewSettings)
2395 end
2396
2397 for Flag, Values in next, NewSettings do
2398 local Element = IniSettings[Flag]
2399 self:LoadIniIntoElement(Element, Values)
2400 end
2401end
2402
2403function ReGui:AddIniFlag(Flag: string, Element: table)
2404 local IniSettings = self.IniSettings
2405 IniSettings[Flag] = Element
2406end
2407
2408type OnElementCreateData = {
2409 Flags: table,
2410 Object: GuiObject,
2411 Canvas: table
2412}
2413function ReGui:OnElementCreate(Data: OnElementCreateData)
2414 local FlagCache = self._FlagCache
2415
2416 local Flags = Data.Flags
2417 local Object = Data.Object
2418 local Canvas = Data.Canvas
2419 local Class = Data.Class
2420
2421 local WindowClass = Canvas.WindowClass
2422
2423 local NoAutoTag = Flags.NoAutoTag
2424 local NoAutoFlags = Flags.NoAutoFlags
2425 local ColorTag = Flags.ColorTag
2426 local NoStyle = Flags.NoStyle
2427 local IniFlag = Flags.IniFlag
2428
2429 --// Cache element flags
2430 FlagCache[Object] = Flags
2431
2432 --// Registor element into IniSettings
2433 if IniFlag then
2434 self:AddIniFlag(IniFlag, Class)
2435 end
2436
2437 --// NoStyle
2438 if NoStyle then return end
2439
2440 --// Registor element into WindowClass
2441 if not NoAutoTag and WindowClass then
2442 WindowClass:TagElements({
2443 [Object] = ColorTag
2444 })
2445 end
2446
2447 --// Apply style functions to the element
2448 if WindowClass then
2449 WindowClass:LoadStylesIntoElement(Data)
2450 end
2451
2452 if not NoAutoFlags then
2453 --// Apply flags to the element
2454 self:ApplyFlags({
2455 Object = Object,
2456 Class = Flags,
2457 WindowClass = WindowClass
2458 })
2459 end
2460end
2461
2462function ReGui:WrapGeneration(Function, Data: table)
2463 local ErrorCache = self._ErrorCache
2464
2465 local Base = Data.Base
2466 local IgnoreDefaults = Data.IgnoreDefaults
2467
2468 return function(Canvas, Flags, ...)
2469 Flags = Flags or {}
2470
2471 --// Check Flags with Base flags from the Element
2472 self:CheckConfig(Flags, Base)
2473
2474 --// Get generation flags
2475 local CloneTable = Flags.CloneTable
2476
2477 --// Clone configuration table flag
2478 if CloneTable then
2479 Flags = table.clone(Flags)
2480 end
2481
2482 local Parent = Canvas.RawObject
2483 local Elements = Canvas.Elements
2484 local OnChildChange = Canvas.OnChildChange
2485
2486 --// Check flags again as the element generation may have modified
2487 self:CheckConfig(Flags, {
2488 Parent = Parent,
2489 Name = Flags.ColorTag
2490 }, nil, IgnoreDefaults)
2491
2492 --// Convert self from 'ReGui' to 'Elements'
2493 if Canvas == self then
2494 Canvas = self.Elements
2495 end
2496
2497 --// Create element and apply properties
2498 --local Class, Element = Function(Canvas, Flags, ...)
2499 local Success, Class, Element = pcall(Function, Canvas, Flags, ...)
2500
2501 --// Check for errors
2502 if Success == false then
2503 if Parent then
2504 if ErrorCache[Parent] then return end
2505 ErrorCache[Parent] = Class
2506 end
2507
2508 --// Create visual error message
2509 if Canvas.Error then
2510 Canvas:Error({
2511 Parent = Parent,
2512 Text = Class
2513 })
2514 end
2515
2516 self:Warn("Class:", Class)
2517 self:Warn(debug.traceback())
2518 end
2519
2520 --// Some elements may return the instance without a class
2521 if Element == nil then
2522 Element = Class
2523 end
2524
2525 --// Invoke OnChildChange
2526 if OnChildChange then
2527 OnChildChange:Fire(Class)
2528 end
2529
2530 --// Add element into the flag Cache
2531 if Element then
2532 if Elements then
2533 table.insert(Elements, Element)
2534 end
2535
2536 self:OnElementCreate({
2537 Object = Element,
2538 Flags = Flags,
2539 Class = Class,
2540 Canvas = Canvas
2541 })
2542 end
2543
2544 return Class, Element
2545 end
2546end
2547
2548function ReGui:DefineElement(Name: string, Data)
2549 local Elements = self.Elements
2550 local Themes = self.ThemeConfigs
2551 local ElementColors = self.ElementColors
2552
2553 local BaseTheme = Themes.DarkTheme
2554
2555 --// Element data
2556 local Base = Data.Base
2557 local Create = Data.Create
2558 local Export = Data.Export
2559 local ThemeTags = Data.ThemeTags
2560 local ColorData = Data.ColorData
2561
2562 --// Add missing keys to base config
2563 self:CheckConfig(Base, {
2564 ColorTag = Name,
2565 ElementStyle = Name
2566 })
2567
2568 --// Declare new coloring variables into theme
2569 if ThemeTags then
2570 Merge(BaseTheme, ThemeTags)
2571 end
2572
2573 --// Declare new ColorData
2574 if ColorData then
2575 Merge(ElementColors, ColorData)
2576 end
2577
2578 --// Create element function wrap
2579 local Generate = self:WrapGeneration(Create, Data)
2580
2581 --// Export creation function into ReGui dict
2582 if Export then
2583 self[Name] = Generate
2584 end
2585
2586 --// Add element into the Elements class
2587 Elements[Name] = Generate
2588
2589 return Generate
2590end
2591
2592function ReGui:DefineGlobalFlag(Flag)
2593 local Flags = self.ElementFlags
2594 table.insert(Flags, Flag)
2595end
2596
2597function ReGui:DefineTheme(Name: string, ThemeData: ThemeData)
2598 local Themes = self.ThemeConfigs
2599
2600 --// Check theme configuration for missing data
2601 self:CheckConfig(ThemeData, {
2602 BaseTheme = Themes.DarkTheme
2603 })
2604
2605 local BaseTheme = GetAndRemove("BaseTheme", ThemeData)
2606 local Theme = {
2607 BaseTheme = BaseTheme,
2608 Values = ThemeData
2609 }
2610
2611 --// Push theme into the ThemeConfigs dict
2612 Themes[Name] = Theme
2613
2614 return Theme
2615end
2616
2617function ReGui:GetMouseLocation(): (number, number)
2618 local Mouse = self.Mouse
2619 return Mouse.X, Mouse.Y
2620end
2621
2622function ReGui:SetWindowFocusesEnabled(Enabled: boolean)
2623 self.WindowFocusesEnabled = Enabled
2624end
2625
2626function ReGui:UpdateWindowFocuses()
2627 local Windows = self.Windows
2628 local FocusesEnabled = self.WindowFocusesEnabled
2629
2630 if not FocusesEnabled then return end
2631
2632 --// Update each window state
2633 for _, Class in Windows do
2634 local Connection = Class.HoverConnection
2635 if not Connection then continue end
2636
2637 --// Check hover state
2638 local Hovering = Connection.Hovering
2639 if Hovering then
2640 self:SetFocusedWindow(Class)
2641 return
2642 end
2643 end
2644
2645 self:SetFocusedWindow(nil)
2646end
2647
2648function ReGui:WindowCanFocus(WindowClass: table): boolean
2649 if WindowClass.NoSelect then return false end
2650 if WindowClass.Collapsed then return false end
2651 if WindowClass._SelectDisabled then return false end
2652
2653 return true
2654end
2655
2656function ReGui:GetFocusedWindow(): table?
2657 return self.FocusedWindow
2658end
2659
2660function ReGui:BringWindowToFront(WindowClass: table)
2661 local Windows = self.Windows
2662
2663 --// Check if the NoBringToFrontOnFocus flag is enabled
2664 local NoBringToFront = WindowClass.NoBringToFrontOnFocus
2665 if NoBringToFront then return end
2666
2667 --// Change position of window in the Windows array to 1
2668 MoveTableItem(Windows, WindowClass, 1)
2669end
2670
2671function ReGui:SetFocusedWindow(ActiveClass: table?)
2672 local Previous = self:GetFocusedWindow()
2673 local Windows = self.Windows
2674
2675 --// Check if the Active window is the same as previous
2676 if Previous == ActiveClass then return end
2677 self.FocusedWindow = ActiveClass
2678
2679 --// Only update the window if the NoSelect flag is enabled
2680 if ActiveClass then
2681 local CanSelect = self:WindowCanFocus(ActiveClass)
2682 if not CanSelect then return end
2683
2684 --// Bring Window to the front
2685 self:BringWindowToFront(ActiveClass)
2686 end
2687
2688 --// Update active state for each window
2689 local ZIndex = #Windows
2690 for _, Class in Windows do
2691 local CanSelect = self:WindowCanFocus(Class)
2692 local Window = Class.WindowFrame
2693
2694 --// Ignore NoSelect windows with NoSelect flag
2695 if not CanSelect then continue end
2696
2697 ZIndex -= 1
2698
2699 --// Set Window ZIndex
2700 if ZIndex then
2701 Window.ZIndex = ZIndex
2702 end
2703
2704 --// Update Window focus state
2705 local Active = Class == ActiveClass
2706 Class:SetFocused(Active, ZIndex)
2707 end
2708end
2709
2710function ReGui:SetItemTooltip(Parent: GuiObject, Render: (Elements) -> ...any)
2711 local Elements = self.Elements
2712 local Tooltips = self.TooltipsContainer
2713 local ActiveTooltips = self.ActiveTooltips
2714
2715 --// Create canvas object
2716 local Canvas, Object = Tooltips:Canvas({
2717 Visible = false,
2718 UiPadding = UDim.new()
2719 })
2720
2721 --// Create content
2722 task.spawn(Render, Canvas)
2723
2724 --// Connect events
2725 ReGui:DetectHover(Parent, {
2726 MouseMove = true,
2727 MouseEnter = true,
2728 OnHoverChange = function(Hovering: boolean)
2729 --// Registor tooltip into ActiveTooltips
2730 if Hovering then
2731 table.insert(ActiveTooltips, Canvas)
2732 return
2733 end
2734
2735 --// Remove from ActiveTooltips
2736 local Index = table.find(ActiveTooltips, Canvas)
2737 table.remove(ActiveTooltips, Index)
2738 end,
2739 OnInput = function(Hovering: boolean, Input)
2740 Object.Visible = Hovering
2741 end,
2742 })
2743end
2744
2745function ReGui:CheckFlags(Flags, Config)
2746 for Name: string, Func in next, Flags do
2747 local Value = Config[Name]
2748 if not Value then continue end
2749
2750 Func(Value)
2751 end
2752end
2753
2754function ReGui:GetThemeKey(Theme: (string|table), Key: string)
2755 local Themes = self.ThemeConfigs
2756
2757 --// Fetch theme data from the name
2758 if typeof(Theme) == "string" then
2759 Theme = Themes[Theme]
2760 end
2761
2762 local BaseTheme = Themes.DarkTheme
2763 Theme = Theme or BaseTheme
2764
2765 local BaseTheme = Theme.BaseTheme
2766 local Values = Theme.Values
2767
2768 --// Test for a direct value
2769 local Value = Values[Key]
2770 if Value then return Value end
2771
2772 --// Fetch value from the base theme
2773 if BaseTheme then
2774 return self:GetThemeKey(BaseTheme, Key)
2775 end
2776end
2777
2778function ReGui:SelectionGroup(Elements)
2779 local Previous = nil
2780 local Debounce = false
2781
2782 local function ForEach(Func, Ignore)
2783 for _, Element in next, Elements do
2784 if typeof(Element) == "Instance" then continue end
2785 if Element == Ignore then continue end
2786
2787 Func(Element)
2788 end
2789 end
2790
2791 local function Callback(self)
2792 if Debounce then return end
2793 Debounce = true
2794
2795 local Value = Previous
2796 Previous = self:GetValue()
2797
2798 if not Value then
2799 Value = Previous
2800 end
2801
2802 ForEach(function(Element)
2803 Element:SetValue(Value)
2804 end, self)
2805
2806 Debounce = false
2807 end
2808
2809 ForEach(function(Element)
2810 Element.Callback = Callback
2811 end)
2812end
2813
2814--// Container class
2815local Elements = ReGui.Elements
2816Elements.__index = Elements
2817
2818function Elements:GetObject()
2819 return self.RawObject
2820end
2821
2822function Elements:Remove()
2823 local OnChildChange = self.OnChildChange
2824 local Object = self:GetObject()
2825 local Class = self.Class
2826
2827 --// Check if the class has a remove function
2828 local ClassRemove = Class.Remove
2829 if ClassRemove then
2830 return ClassRemove(Class)
2831 end
2832
2833 --// Invoke OnChildChange
2834 if OnChildChange then
2835 OnChildChange:Fire(Class or self)
2836 end
2837
2838 if Class then
2839 table.clear(Class)
2840 end
2841
2842 Object:Destroy()
2843 table.clear(self)
2844end
2845
2846function Elements:GetChildElements(): table
2847 local Elements = self.Elements
2848 return Elements
2849end
2850
2851function Elements:ClearChildElements()
2852 local Elements = self:GetChildElements()
2853 for _, Object in next, Elements do
2854 Object:Destroy()
2855 end
2856end
2857
2858function Elements:TagElements(Objects: ObjectTable)
2859 local WindowClass = self.WindowClass
2860 local Debug = ReGui.Debug
2861
2862 --// Missing WindowClass
2863 if not WindowClass then
2864 if Debug then
2865 ReGui:Warn("No WindowClass for TagElements:", Objects)
2866 end
2867 return
2868 end
2869
2870 WindowClass:TagElements(Objects)
2871end
2872
2873function Elements:GetThemeKey(Key: string)
2874 local WindowClass = self.WindowClass
2875
2876 if WindowClass then
2877 return WindowClass:GetThemeKey(Key)
2878 end
2879
2880 return ReGui:GetThemeKey(nil, Key)
2881end
2882
2883function Elements:SetColorTags(Objects: ObjectTables, Animate: boolean?)
2884 local WindowClass = self.WindowClass
2885 if not WindowClass then return end
2886
2887 local Elements = WindowClass.TagsList
2888 local Theme = WindowClass.Theme
2889
2890 ReGui:MultiUpdateColors({
2891 Animate = Animate,
2892 Theme = Theme,
2893 TagsList = Elements,
2894 Objects = Objects,
2895 })
2896end
2897
2898function Elements:SetElementFocused(Object: GuiObject, Data)
2899 local WindowClass = self.WindowClass
2900 local IsMobileDevice = ReGui.HasTouchScreen
2901
2902 local Focused = Data.Focused
2903 local Animation = Data.Animation
2904
2905 --// Change global animation state
2906 ReGui:SetAnimationsEnabled(not Focused)
2907
2908 --// Reset animation state
2909 if not Focused and Animation then
2910 Animation:Refresh()
2911 end
2912
2913 --// Window modification
2914 if not WindowClass then return end
2915 if not IsMobileDevice then return end
2916 local ContentCanvas = WindowClass.ContentCanvas
2917
2918 --// Disable interaction with other elements for touchscreens
2919 ContentCanvas.Interactable = not Focused
2920end
2921
2922ReGui:DefineElement("Dropdown", {
2923 Base = {
2924 ColorTag = "PopupCanvas",
2925 Disabled = false,
2926 AutoClose = true,
2927 OnSelected = EmptyFunction
2928 },
2929 Create = function(Canvas, Config)
2930 Config.Parent = ReGui.Container.Overlays
2931
2932 --// Unpack configuration
2933 local Selected = Config.Selected
2934 local Items = Config.Items
2935 local OnSelected = Config.OnSelected
2936
2937 --// Create overlay object
2938 local Popup, Object = Canvas:PopupCanvas(Config)
2939 local Class = ReGui:MergeMetatables(Config, Popup)
2940
2941 local Entries = {}
2942
2943 local function SetValue(Value)
2944 OnSelected(Value) -- Invoke selected callback
2945 end
2946
2947 function Config:ClearEntries()
2948 for _, Entry in Entries do
2949 Entry:Remove()
2950 end
2951 end
2952
2953 function Config:SetItems(Items: table, Selected)
2954 local IsArray = Items[1]
2955
2956 --// Clear previous entries
2957 self:ClearEntries()
2958
2959 --// Append items
2960 for A, B in Items do
2961 local Value = IsArray and B or A
2962 local IsSelected = A == Selected or B == Selected
2963
2964 --// Create selectable
2965 local Entry = Popup:Selectable({
2966 Text = tostring(Value),
2967 Selected = IsSelected,
2968 ZIndex = 6,
2969 Callback = function()
2970 return SetValue(Value)
2971 end,
2972 })
2973
2974 table.insert(Entries, Entry)
2975 end
2976 end
2977
2978 --// Update object
2979 if Items then
2980 Config:SetItems(Items, Selected)
2981 end
2982
2983 return Class, Object
2984 end,
2985})
2986
2987ReGui:DefineElement("OverlayScroll", {
2988 Base = {
2989 ElementClass = "OverlayScroll",
2990 Spacing = UDim.new(0, 4),
2991 },
2992 Create = function(self, Config)
2993 local WindowClass = self.WindowClass
2994
2995 local ElementClass = Config.ElementClass
2996 local Spacing = Config.Spacing
2997
2998 --// Create overlay object
2999 local Object = ReGui:InsertPrefab(ElementClass, Config)
3000 local ContentFrame = Object:FindFirstChild("ContentFrame") or Object
3001 local ListLayout = Object:FindFirstChild("UIListLayout", true)
3002
3003 ListLayout.Padding = Spacing
3004
3005 local Class = ReGui:MergeMetatables(self, Config)
3006
3007 --// Content canvas
3008 local Canvas = ReGui:MakeCanvas({
3009 Element = ContentFrame,
3010 WindowClass = WindowClass,
3011 Class = Class
3012 })
3013
3014 function Config:GetCanvasSize()
3015 return ContentFrame.AbsoluteCanvasSize
3016 end
3017
3018 return Canvas, Object
3019 end,
3020})
3021
3022ReGui:DefineElement("Overlay", {
3023 Base = {
3024 ElementClass = "Overlay"
3025 },
3026 Create = Elements.OverlayScroll,
3027})
3028
3029export type Image = {
3030 Image: (string|number),
3031 Callback: ((...any) -> unknown)?
3032}
3033ReGui:DefineElement("Image", {
3034 Base = {
3035 Image = "",
3036 Callback = EmptyFunction
3037 },
3038 Create = function(self, Config: Image): ImageButton
3039 --// Correct configuration
3040 local Image = Config.Image
3041 Config.Image = ReGui:CheckAssetUrl(Image)
3042
3043 --// Create image object
3044 local Object = ReGui:InsertPrefab("Image", Config)
3045 Object.Activated:Connect(function(...)
3046 local Func = Config.Callback
3047 return Func(Object, ...)
3048 end)
3049
3050 return Object
3051 end,
3052})
3053
3054export type VideoPlayer = {
3055 Video: (string|number),
3056 Callback: ((...any) -> unknown)?
3057}
3058ReGui:DefineElement("VideoPlayer", {
3059 Base = {
3060 Video = "",
3061 Callback = EmptyFunction
3062 },
3063 Create = function(self, Config: VideoPlayer): VideoFrame
3064 --// Correct configuration
3065 local Video = Config.Video
3066 Config.Video = ReGui:CheckAssetUrl(Video)
3067
3068 --// Create object
3069 local Object = ReGui:InsertPrefab("VideoPlayer", Config)
3070 return Object
3071 end,
3072})
3073
3074export type Button = {
3075 Text: string?,
3076 DoubleClick: boolean?,
3077 Callback: ((...any) -> unknown)?,
3078}
3079ReGui:DefineElement("Button", {
3080 Base = {
3081 Text = "Button",
3082 DoubleClick = false,
3083 Callback = EmptyFunction
3084 },
3085 Create = function(self, Config: Button): TextButton
3086 --// Create button object
3087 local Object = ReGui:InsertPrefab("Button", Config)
3088
3089 local DoubleClick = Config.DoubleClick
3090
3091 --// MouseEvents
3092 ReGui:ConnectMouseEvent(Object, {
3093 DoubleClick = DoubleClick,
3094 Callback = function(...)
3095 local Func = Config.Callback
3096 return Func(Object, ...)
3097 end,
3098 })
3099
3100 return Object
3101 end,
3102})
3103
3104export type Selectable = {
3105 Text: string?,
3106 Selected: boolean?,
3107 Disabled: boolean?,
3108 Callback: ((...any) -> unknown)?,
3109}
3110ReGui:DefineElement("Selectable", {
3111 Base = {
3112 Text = "Selectable",
3113 Callback = EmptyFunction,
3114 Selected = false,
3115 Disabled = false,
3116 Size = UDim2.fromScale(1, 0),
3117 AutomaticSize = Enum.AutomaticSize.Y,
3118 TextXAlignment = Enum.TextXAlignment.Left,
3119 AnimationTags = {
3120 Selected = "Buttons",
3121 Unselected = "TransparentButtons"
3122 },
3123 },
3124 Create = function(self, Config: Selectable): (table, TextButton)
3125 local AfterClick = self.Class.AfterClick
3126
3127 local Selected = Config.Selected
3128 local Disabled = Config.Disabled
3129
3130 --// Create button object
3131 local Object = ReGui:InsertPrefab("Button", Config)
3132 local Class = ReGui:MergeMetatables(Config, Object)
3133
3134 Object.Activated:Connect(function(...)
3135 --// Invoke callback
3136 local Func = Config.Callback
3137 Func(Object, ...)
3138
3139 --// The canvas after click event
3140 if AfterClick then
3141 AfterClick(Object, ...)
3142 end
3143 end)
3144
3145 function Config:SetSelected(Selected: boolean?)
3146 local Animations = self.AnimationTags
3147 local Animation = Selected and Animations.Selected or Animations.Unselected
3148
3149 self.Selected = Selected
3150 ReGui:SetAnimation(Object, Animation)
3151 end
3152
3153 function Config:SetDisabled(Disabled: boolean?)
3154 self.Disabled = Disabled
3155 Object.Interactable = not Disabled
3156 end
3157
3158 --// Update object state
3159 Config:SetSelected(Selected)
3160 Config:SetDisabled(Disabled)
3161
3162 return Class, Object
3163 end,
3164})
3165
3166export type ImageButton = {
3167 Image: (string|number),
3168 Callback: ((...any) -> unknown)?
3169}
3170ReGui:DefineElement("ImageButton", {
3171 Base = {
3172 ElementStyle = "Button",
3173 Callback = EmptyFunction
3174 },
3175 Create = Elements.Image,
3176})
3177
3178ReGui:DefineElement("SmallButton", {
3179 Base = {
3180 Text = "Button",
3181 PaddingTop = UDim.new(),
3182 PaddingBottom = UDim.new(),
3183 PaddingLeft = UDim.new(0, 2),
3184 PaddingRight = UDim.new(0, 2),
3185 ColorTag = "Button",
3186 ElementStyle = "Button",
3187 Callback = EmptyFunction,
3188 },
3189 Create = Elements.Button
3190})
3191
3192type KeyId = (Enum.UserInputType | Enum.KeyCode)
3193export type Keybind = {
3194 Value: Enum.KeyCode?,
3195 DeleteKey: Enum.KeyCode?,
3196 Enabled: boolean?,
3197 IgnoreGameProcessed: boolean?,
3198 Callback: ((KeyId) -> any)?,
3199 OnKeybindSet: ((KeyId) -> any)?,
3200 OnBlacklistedKeybindSet: ((KeyId) -> any)?,
3201 KeyBlacklist: {
3202 [number]: KeyId
3203 },
3204
3205 SetValue: ((Keybind, New: Enum.KeyCode) -> any)?,
3206 WaitForNewKey: ((Keybind) -> any)?,
3207}
3208ReGui:DefineElement("Keybind", {
3209 Base = {
3210 Label = "Keybind",
3211 ColorTag = "Frame",
3212 Value = nil,
3213 DeleteKey = Enum.KeyCode.Backspace,
3214 IgnoreGameProcessed = true,
3215 Enabled = true,
3216 Disabled = false,
3217 Callback = EmptyFunction,
3218 OnKeybindSet = EmptyFunction,
3219 OnBlacklistedKeybindSet = EmptyFunction,
3220 KeyBlacklist = {},
3221 UiPadding = UDim.new(),
3222 AutomaticSize = Enum.AutomaticSize.None,
3223 Size = UDim2.new(0.3, 0, 0, 19)
3224 },
3225 Create = function(Canvas, Config: Keybind)
3226 local Value = Config.Value
3227 local LabelText = Config.Label
3228 local Disabled = Config.Disabled
3229 local KeyBlacklist = Config.KeyBlacklist
3230
3231 --// Create keybind object
3232 local Object = ReGui:InsertPrefab("Button", Config)
3233 local Class = ReGui:MergeMetatables(Config, Object)
3234
3235 local Label = Canvas:Label({
3236 Parent = Object,
3237 Text = LabelText,
3238 Position = UDim2.new(1, 4, 0.5),
3239 AnchorPoint = Vector2.new(0, 0.5)
3240 })
3241
3242 local function Callback(Func, ...)
3243 return Func(Object, ...)
3244 end
3245
3246 local function KeyIsBlacklisted(KeyId: KeyId)
3247 local Blacklisted = table.find(KeyBlacklist, KeyId)
3248 return Blacklisted
3249 end
3250
3251 function Config:SetDisabled(Disabled: boolean)
3252 self.Disabled = Disabled
3253 Object.Interactable = not Disabled
3254 Canvas:SetColorTags({
3255 [Label] = Disabled and "LabelDisabled" or "Label"
3256 }, true)
3257 end
3258
3259 function Config:SetValue(KeyId: KeyId)
3260 local OnKeybindSet = self.OnKeybindSet
3261 local DeleteKey = self.DeleteKey
3262
3263 --// Remove keybind
3264 if KeyId == DeleteKey then
3265 KeyId = nil
3266 end
3267
3268 self.Value = KeyId
3269 Object.Text = KeyId and KeyId.Name or "Not set"
3270
3271 --// Invoke OnKeybindSet callback
3272 Callback(OnKeybindSet, KeyId)
3273 end
3274
3275 function Config:WaitForNewKey()
3276 self._WaitingForNewKey = true
3277 Object.Text = "..."
3278 Object.Interactable = false
3279 end
3280
3281 local function GetKeyId(Input: InputObject)
3282 local KeyCode = Input.KeyCode
3283 local InputType = Input.UserInputType
3284
3285 --// Convert mouse input
3286 if InputType ~= Enum.UserInputType.Keyboard then
3287 return InputType
3288 end
3289
3290 return KeyCode
3291 end
3292
3293 local function CheckNewKey(Input: InputObject)
3294 local OnBlacklistedKeybindSet = Config.OnBlacklistedKeybindSet
3295 local Previous = Config.Value
3296
3297 local KeyId = GetKeyId(Input)
3298
3299 --// Check if window is focused
3300 if not UserInputService.WindowFocused then return end
3301
3302 --// Check if keycode is blacklisted
3303 if KeyIsBlacklisted(KeyId) then
3304 --// Invoke OnKeybindSet callback
3305 Callback(OnBlacklistedKeybindSet, KeyId)
3306 return
3307 end
3308
3309 Object.Interactable = true
3310 Config._WaitingForNewKey = false
3311
3312 --// Reset back to previous if new key is unknown
3313 if KeyId.Name == "Unknown" then
3314 return Config:SetValue(Previous)
3315 end
3316
3317 --// Set new keybind
3318 Config:SetValue(KeyId)
3319 end
3320
3321 local function InputBegan(Input: InputObject, GameProcessed: boolean)
3322 local IgnoreGameProcessed = Config.IgnoreGameProcessed
3323 local DeleteKey = Config.DeleteKey
3324 local Enabled = Config.Enabled
3325 local Value = Config.Value
3326 local Func = Config.Callback
3327
3328 local KeyId = GetKeyId(Input)
3329
3330 --// OnKeybindSet
3331 if Config._WaitingForNewKey then
3332 CheckNewKey(Input)
3333 return
3334 end
3335
3336 --// Check input state
3337 if not Enabled and Object.Interactable then return end
3338 if not IgnoreGameProcessed and GameProcessed then return end
3339
3340 --// Check KeyCode
3341 if not Value then return end
3342 if KeyId == DeleteKey then return end
3343 if KeyId.Name ~= Value.Name then return end
3344
3345 --// Invoke callback
3346 Callback(Func, KeyId)
3347 end
3348
3349 --// Update object state
3350 Config:SetValue(Value)
3351 Config:SetDisabled(Disabled)
3352
3353 --// Connect events
3354 Config.Connection = UserInputService.InputBegan:Connect(InputBegan)
3355 Object.Activated:Connect(function()
3356 Config:WaitForNewKey()
3357 end)
3358
3359 ReGui:SetAnimation(Object, "Inputs")
3360
3361 return Class, Object
3362 end
3363})
3364
3365ReGui:DefineElement("ArrowButton", {
3366 Base = {
3367 Direction = "Left",
3368 ColorTag = "Button",
3369 Icon = ReGui.Icons.Arrow,
3370 Size = UDim2.fromOffset(21, 21),
3371 IconSize = UDim2.fromScale(1, 1),
3372 IconPadding = UDim.new(0, 4),
3373 Rotations = {
3374 Left = 180,
3375 Right = 0,
3376 }
3377 },
3378 Create = function(self, Config): ScrollingFrame
3379 --// Unpack configuration
3380 local Direction = Config.Direction
3381 local Rotations = Config.Rotations
3382
3383 local Rotation = Rotations[Direction]
3384 Config.IconRotation = Rotation
3385
3386 --// Create object
3387 local Object = ReGui:InsertPrefab("ArrowButton", Config)
3388 Object.Activated:Connect(function(...)
3389 local Func = Config.Callback
3390 return Func(Object, ...)
3391 end)
3392
3393 return Object
3394 end,
3395})
3396
3397export type Label = {
3398 Text: string,
3399 Bold: boolean?,
3400 Italic: boolean?,
3401 Font: string?
3402}
3403ReGui:DefineElement("Label", {
3404 Base = {
3405 Font = "Inconsolata"
3406 },
3407 ColorData = {
3408 ["LabelPadding"] = {
3409 PaddingTop = "LabelPaddingTop",
3410 PaddingBottom = "LabelPaddingBottom"
3411 },
3412 },
3413 Create = function(self, Config: Label): TextLabel
3414 --// Unpack config
3415 local IsBold = Config.Bold
3416 local IsItalic = Config.Italic
3417 local FontName = Config.Font
3418 local FontFace = Config.FontFace
3419
3420 --// Weghts
3421 local Medium = Enum.FontWeight.Medium
3422 local Bold = Enum.FontWeight.Bold
3423
3424 --// Styles
3425 local Normal = Enum.FontStyle.Normal
3426 local Italic = Enum.FontStyle.Italic
3427
3428 local Weight = IsBold and Bold or Medium
3429 local Style = IsItalic and Italic or Normal
3430 local AddFlag = IsBold or IsItalic
3431
3432 if not FontFace and AddFlag then
3433 Config.FontFace = Font.fromName(FontName, Weight, Style)
3434 end
3435
3436 local Label = ReGui:InsertPrefab("Label", Config)
3437 local Padding = Label:FindFirstChildOfClass("UIPadding")
3438
3439 self:TagElements({
3440 [Padding] = "LabelPadding",
3441 })
3442
3443 --// Create label
3444 return Label
3445 end,
3446})
3447
3448ReGui:DefineElement("Error", {
3449 Base = {
3450 RichText = true,
3451 TextWrapped = true
3452 },
3453 ColorData = {
3454 ["Error"] = {
3455 TextColor3 = "ErrorText",
3456 FontFace = "TextFont",
3457 },
3458 },
3459 Create = function(self, Config: Label)
3460 local Message = Config.Text
3461 Config.Text = `<b>⛔ Error:</b> {Message}`
3462
3463 return self:Label(Config)
3464 end,
3465})
3466
3467------// MenuBar class
3468local MenuBar = {
3469 Engaged = false
3470}
3471MenuBar.__index = MenuBar
3472
3473function MenuBar:SetEngaged(Engaged: boolean)
3474 local Object = self.Object
3475 local Window = self.WindowClass
3476
3477 self.Engaged = Engaged
3478
3479 --// Set the Window interaction state based on the MenuBar enagement
3480 if Window then
3481 Window:SetCanvasInteractable(not Engaged)
3482 end
3483end
3484
3485function MenuBar:IsHovering(): boolean
3486 local Hovering = false
3487
3488 --// Check the hover state for each menu
3489 self:Foreach(function(Data)
3490 Hovering = Data.Popup:IsMouseHovering()
3491 return Hovering
3492 end)
3493
3494 return Hovering
3495end
3496
3497function MenuBar:Foreach(Func)
3498 local Menus = self.Menus
3499 for _, Data in next, Menus do
3500 --// Invoke callback
3501 local Break = Func(Data)
3502 if Break then break end
3503 end
3504end
3505
3506function MenuBar:SetFocusedMenu(Menu)
3507 self:Foreach(function(Data)
3508 --// Set active state based on if MenuItem is the requested
3509 local Active = Data == Menu
3510 Data:SetActiveState(Active)
3511 end)
3512end
3513
3514function MenuBar:Close()
3515 self:SetEngaged(false)
3516 self:SetFocusedMenu(nil)
3517end
3518
3519function MenuBar:MenuItem(Config)
3520 local Canvas = self.Canvas
3521 local Menus = self.Menus
3522
3523 --// Create elements
3524 local Selectable = Canvas:MenuButton(Config)
3525 local Popup = Canvas:PopupCanvas({
3526 RelativeTo = Selectable,
3527 MaxSizeX = 210,
3528 Visible = false,
3529 AutoClose = false,
3530 AfterClick = function()
3531 self:Close()
3532 end,
3533 })
3534
3535 --// Menu data for the array
3536 local MenuData = {
3537 Popup = Popup,
3538 Button = Selectable
3539 }
3540
3541 --// Connect mouse focus events
3542 ReGui:DetectHover(Selectable, {
3543 MouseEnter = true,
3544 OnInput = function()
3545 if not self.Engaged then return end
3546 self:SetFocusedMenu(MenuData)
3547 end,
3548 })
3549
3550 function MenuData:SetActiveState(Active: boolean)
3551 Popup:SetPopupVisible(Active)
3552 Selectable:SetSelected(Active)
3553 end
3554
3555 --// Engage button connections
3556 Selectable.Activated:Connect(function()
3557 self:SetFocusedMenu(MenuData)
3558 self:SetEngaged(true)
3559 end)
3560
3561 --// Add menu to the Menu array
3562 table.insert(Menus, MenuData)
3563
3564 return Popup, MenuData
3565end
3566
3567ReGui:DefineElement("MenuBar", {
3568 Base = {},
3569 Create = function(self, Config): Elements
3570 local WindowClass = self.WindowClass
3571
3572 --// Create object
3573 local Object = ReGui:InsertPrefab("MenuBar", Config)
3574
3575 --// Content canvas
3576 local Canvas = ReGui:MakeCanvas({
3577 Element = Object,
3578 WindowClass = WindowClass,
3579 Class = Config
3580 })
3581
3582 --// Make menu bar class
3583 local Class = NewClass(MenuBar, {
3584 WindowClass = WindowClass,
3585 Canvas = Canvas,
3586 Object = Object,
3587 Menus = {}
3588 })
3589 Merge(Class, Config)
3590
3591 --// Mouse click detection for closure
3592 ReGui:DetectHover(Object, {
3593 MouseOnly = true,
3594 OnInput = function()
3595 if not Class.Engaged then return end
3596 if Class:IsHovering() then return end
3597
3598 Class:Close()
3599 end,
3600 })
3601
3602 local Meta = ReGui:MergeMetatables(Class, Canvas)
3603 return Meta, Object
3604 end,
3605})
3606
3607ReGui:DefineElement("MenuButton", {
3608 Base = {
3609 Text = "MenuButton",
3610 PaddingLeft = UDim.new(0, 8),
3611 PaddingRight = UDim.new(0, 8),
3612 Size = UDim2.fromOffset(0, 19),
3613 AutomaticSize = Enum.AutomaticSize.XY
3614 },
3615 Create = Elements.Selectable
3616})
3617
3618----// TabsBar class
3619local TabBarClass = {
3620 ColorTags = {
3621 BGSelected = {
3622 [true] = "SelectedTab",
3623 [false] = "DeselectedTab"
3624 },
3625 LabelSelected = {
3626 [true] = "SelectedTabLabel",
3627 [false] = "DeselectedTabLabel"
3628 },
3629 }
3630}
3631function TabBarClass:SetButtonSelected(Tab: table, Selected: boolean)
3632 --// Ignore update if the value is identical
3633 if Tab.IsSelected == Selected then return end
3634 Tab.IsSelected = Selected
3635
3636 local NoAnimation = self.NoAnimation
3637 local WindowClass = self.WindowClass
3638 local ColorTags = self.ColorTags
3639
3640 --// Coloring dicts
3641 local Theme = WindowClass.Theme
3642 local Elements = WindowClass.TagsList
3643
3644 --// Colors tags
3645 local BGSelected = ColorTags.BGSelected
3646 local LabelSelected = ColorTags.LabelSelected
3647
3648 local TabButton = Tab.TabButton
3649 local Button = TabButton.Button
3650 local Label = Button.Label
3651
3652 ReGui:MultiUpdateColors({
3653 Animate = not NoAnimation,
3654 Theme = Theme,
3655 TagsList = Elements,
3656 Objects = {
3657 [Button] = BGSelected[Selected],
3658 [Label] = LabelSelected[Selected],
3659 },
3660 })
3661end
3662
3663function TabBarClass:CompareTabs(Tab, Match)
3664 if not Tab then return false end
3665 return Tab.MatchBy == Match or Tab == Match
3666end
3667
3668function TabBarClass:ForEachTab(Match: (Tab|string), Func: (Tab, IsMatch: boolean, Index: number) -> nil)
3669 local CompareName = typeof(Match) == "string"
3670 local Tabs = self.Tabs
3671
3672 for Index, Tab in Tabs do
3673 local Name = Tab.Name
3674 local IsMatch = false
3675
3676 --// Match for requested content type
3677 if CompareName then
3678 IsMatch = Name == Match
3679 else
3680 IsMatch = self:CompareTabs(Tab, Match)
3681 end
3682
3683 --// Invoke callback
3684 Func(Tab, IsMatch, Index)
3685 end
3686end
3687
3688function TabBarClass:RemoveTab(Target: (Tab|string))
3689 local OnTabRemove = self.OnTabRemove
3690 local Tabs = self.Tabs
3691
3692 self:ForEachTab(Target, function(Tab, IsMatch, Index)
3693 if not IsMatch then return end
3694 local TabButton = Tab.TabButton
3695 local OnClosure = Tab.OnClosure
3696
3697 --// Remove
3698 table.remove(Tabs, Index)
3699 TabButton:Destroy()
3700
3701 --// Invoke OnClosure
3702 OnTabRemove(self, Tab)
3703 OnClosure(Tab)
3704 end)
3705
3706 return self
3707end
3708
3709export type Tab = {
3710 Name: string,
3711 Focused: boolean?,
3712 TabButton: boolean?,
3713 Closeable: boolean?,
3714 OnClosure: (Tab) -> nil,
3715 Icon: (string|number)?
3716}
3717function TabBarClass:CreateTab(Config: Tab): Elements
3718 Config = Config or {}
3719 ReGui:CheckConfig(Config, {
3720 Name = "Tab",
3721 AutoSize = "Y",
3722 Focused = false,
3723 OnClosure = EmptyFunction
3724 })
3725
3726 --// Unpack class data
3727 local AutoSelectNewTabs = self.AutoSelectNewTabs
3728 local WindowClass = self.WindowClass
3729 local ParentCanvas = self.ParentCanvas
3730 local Tabs = self.Tabs
3731 local TabsFrame = self.TabsFrame
3732 local OnTabCreate = self.OnTabCreate
3733
3734 --// Unpack config
3735 local Focused = Config.Focused
3736 local Name = Config.Name
3737 local Icon = Config.Icon
3738 local IsFocused = Focused or #Tabs <= 0 and AutoSelectNewTabs
3739
3740 --// Template sources
3741 local TabButton = ReGui:InsertPrefab("TabButton", Config)
3742 TabButton.Parent = TabsFrame
3743
3744 --// Create new tab button
3745 local Button = TabButton.Button
3746 local TextPadding = Button:FindFirstChildOfClass("UIPadding")
3747 local Label = Button.Label
3748 Label.Text = tostring(Name)
3749
3750 Merge(Config, {
3751 TabButton = TabButton
3752 })
3753
3754 local function SetActive()
3755 self:SetActiveTab(Config)
3756 end
3757
3758 --// Addional flags
3759 local ExtraFlags = {
3760 ["Closeable"] = function()
3761 local Button = ParentCanvas:RadioButton({
3762 Parent = Button,
3763 Visible = not self.NoClose,
3764 Icon = ReGui.Icons.Close,
3765 IconSize = UDim2.fromOffset(11,11),
3766 LayoutOrder = 3,
3767 ZIndex = 2,
3768 UsePropertiesList = true,
3769 Callback = function()
3770 self:RemoveTab(Config)
3771 end,
3772 })
3773
3774 --// Animate close icon on hover
3775 local Icon = Button.Icon
3776 ReGui:SetAnimation(Icon, {
3777 Connections = {
3778 MouseEnter = {
3779 ImageTransparency = 0,
3780 },
3781 MouseLeave = {
3782 ImageTransparency = 1,
3783 }
3784 },
3785 Init = "MouseLeave"
3786 }, TabButton)
3787 end,
3788 }
3789
3790 --// Connect events
3791 Button.Activated:Connect(SetActive)
3792
3793 --// Apply flags
3794 ReGui:CheckFlags(ExtraFlags, Config)
3795
3796 --// Add to tabs dict
3797 table.insert(Tabs, Config)
3798
3799 --// Add color infomation
3800 if WindowClass then
3801 WindowClass:TagElements({
3802 [TextPadding] = "TabPadding",
3803 })
3804 end
3805
3806 --// Set animation for tab button
3807 ReGui:SetAnimation(Button, "Buttons")
3808 self:SetButtonSelected(Config, IsFocused)
3809
3810 --// Apply flags
3811 ReGui:ApplyFlags({
3812 Object = TabButton,
3813 Class = Config
3814 })
3815
3816 local Responce = OnTabCreate(self, Config)
3817
3818 --// Change tab focus
3819 if IsFocused then
3820 self:SetActiveTab(Config)
3821 end
3822
3823 return Responce or Config
3824end
3825
3826function TabBarClass:SetActiveTab(Target: (table|string))
3827 --// Unpack class data
3828 local Tabs = self.Tabs
3829 local NoAnimation = self.NoAnimation
3830 local Previous = self.ActiveTab
3831 local OnActiveTabChange = self.OnActiveTabChange
3832
3833 local MatchName = typeof(Target) == "string"
3834 local MatchedTab = nil
3835 local IsVisible = false
3836
3837 self:ForEachTab(Target, function(Tab, IsMatch, Index)
3838 if IsMatch then
3839 MatchedTab = Tab
3840 end
3841 self:SetButtonSelected(Tab, IsMatch)
3842 end)
3843
3844 if not MatchedTab then return self end
3845 if self:CompareTabs(MatchedTab, Previous) then return self end
3846
3847 self.ActiveTab = MatchedTab
3848
3849 --// Invoke OnActiveTabChange
3850 OnActiveTabChange(self, MatchedTab, Previous)
3851
3852 return self
3853end
3854
3855export type TabBar = {
3856 AutoSelectNewTabs: boolean,
3857 OnActiveTabChange: ((TabBar, Tab: Tab, Previous: Tab) -> nil)?,
3858 OnTabCreate: ((TabBar, Tab: Tab) -> nil)?,
3859 OnTabRemove: ((TabBar, Tab: Tab) -> nil)?
3860}
3861ReGui:DefineElement("TabBar", {
3862 Base = {
3863 AutoSelectNewTabs = true,
3864 OnActiveTabChange = EmptyFunction,
3865 OnTabCreate = EmptyFunction,
3866 OnTabRemove = EmptyFunction,
3867 },
3868 ColorData = {
3869 ["DeselectedTab"] = {
3870 BackgroundColor3 = "TabBg"
3871 },
3872 ["SelectedTab"] = {
3873 BackgroundColor3 = "TabBgActive"
3874 },
3875 ["DeselectedTabLabel"] = {
3876 FontFace = "TextFont",
3877 TextColor3 = "TabText",
3878 },
3879 ["SelectedTabLabel"] = {
3880 FontFace = "TextFont",
3881 TextColor3 = "TabTextActive",
3882 },
3883 ["TabsBarSeparator"] = {
3884 BackgroundColor3 = "TabBgActive",
3885 },
3886 ["TabPadding"] = {
3887 PaddingTop = "TabTextPaddingTop",
3888 PaddingBottom = "TabTextPaddingBottom"
3889 },
3890 ["TabPagePadding"] = {
3891 PaddingBottom = "TabPagePadding",
3892 PaddingLeft = "TabPagePadding",
3893 PaddingRight = "TabPagePadding",
3894 PaddingTop = "TabPagePadding",
3895 }
3896 },
3897 Create = function(self, Config: TabBar)
3898 local WindowClass = self.WindowClass
3899
3900 --// Create object
3901 local Object = ReGui:InsertPrefab("TabsBar", Config)
3902 local Class = NewClass(TabBarClass)
3903
3904 local Separator = Object.Separator
3905 local TabsFrame = Object.TabsFrame
3906
3907 --// Create canvas
3908 local TabsRailCanvas = ReGui:MakeCanvas({
3909 Element = TabsFrame,
3910 WindowClass = WindowClass,
3911 Class = Class
3912 })
3913
3914 --// Merge configurations into the class
3915 Merge(Class, Config)
3916 Merge(Class, {
3917 ParentCanvas = self,
3918 Object = Object,
3919 TabsFrame = TabsFrame,
3920 WindowClass = WindowClass,
3921 Tabs = {}
3922 })
3923
3924 --// Tag elementss
3925 self:TagElements({
3926 [Object] = "TabsBar",
3927 [Separator] = "TabsBarSeparator",
3928 })
3929
3930 local Merged = ReGui:MergeMetatables(TabsRailCanvas, Object)
3931 return Merged, Object
3932 end,
3933})
3934
3935export type TabSelector = {
3936 NoTabsBar: boolean?,
3937 NoAnimation: boolean?,
3938} & TabBar
3939ReGui:DefineElement("TabSelector", {
3940 Base = {
3941 NoTabsBar = false,
3942 OnActiveTabChange = EmptyFunction,
3943 OnTabCreate = EmptyFunction,
3944 OnTabRemove = EmptyFunction,
3945 },
3946 Create = function(Canvas, Config: TabSelector): (TabSelector, GuiObject)
3947 local WindowClass = Canvas.WindowClass
3948
3949 local NoTabsBar = Config.NoTabsBar
3950 local NoAnimation = Config.NoAnimation
3951
3952 --// Create TabSelector object
3953 local Object = ReGui:InsertPrefab("TabSelector", Config)
3954
3955 local Body = Object.Body
3956 local PageTemplate = Body.PageTemplate
3957 PageTemplate.Visible = false
3958
3959 --// TabsBar functions
3960 local function OnTabCreate(self, Tab, ...)
3961 local AutoSize = Tab.AutoSize
3962 local Name = Tab.Name
3963
3964 --// Create page
3965 local Page = PageTemplate:Clone()
3966 local PagePadding = ReGui:GetChildOfClass(Page, "UIPadding")
3967
3968 ReGui:SetProperties(Page, {
3969 Parent = Body,
3970 Name = Name,
3971 AutomaticSize = Enum.AutomaticSize[AutoSize],
3972 Size = UDim2.fromScale(
3973 AutoSize == "Y" and 1 or 0,
3974 AutoSize == "X" and 1 or 0
3975 )
3976 })
3977
3978 --// Page padding
3979 Canvas:TagElements({
3980 [PagePadding] = "TabPagePadding",
3981 })
3982
3983 --// Create canvas
3984 local Canvas = ReGui:MakeCanvas({
3985 Element = Page,
3986 WindowClass = WindowClass,
3987 Class = Tab
3988 })
3989
3990 --// Invoke user callback
3991 Config.OnTabCreate(self, Tab, ...)
3992
3993 Merge(Tab, {
3994 Page = Page,
3995 MatchBy = Canvas
3996 })
3997
3998 return Canvas
3999 end
4000 local function OnActiveTabChange(self, Tab, ...)
4001 self:ForEachTab(Tab, function(Tab, IsMatch, Index)
4002 local Page = Tab.Page
4003 Page.Visible = IsMatch
4004
4005 if not IsMatch then return end
4006
4007 --// Slide in effect
4008 local Tweeninfo = Canvas:GetThemeKey("AnimationTweenInfo")
4009 Animation:Tween({
4010 Object = Page,
4011 Tweeninfo = Tweeninfo,
4012 NoAnimation = NoAnimation,
4013 StartProperties = {
4014 Position = UDim2.fromOffset(0, 4)
4015 },
4016 EndProperties = {
4017 Position = UDim2.fromOffset(0, 0)
4018 }
4019 })
4020 end)
4021
4022 --// Invoke user callback
4023 Config.OnActiveTabChange(self, Tab, ...)
4024 end
4025
4026 --// Create tabs bar
4027 local TabsBar = Canvas:TabBar({
4028 Parent = Object,
4029 Visible = not NoTabsBar,
4030 OnTabCreate = OnTabCreate,
4031 OnActiveTabChange = OnActiveTabChange,
4032 OnTabRemove = function(self, Tab, ...)
4033 Tab.Page:Remove()
4034 Config.OnTabRemove(...) --// Invoke user callback
4035 end,
4036 })
4037
4038 local Class = ReGui:MergeMetatables(TabsBar, Object)
4039 return Class, Object
4040 end,
4041})
4042
4043export type RadioButton = {
4044 Icon: string?,
4045 IconRotation: number?,
4046 Callback: ((...any) -> unknown)?,
4047}
4048ReGui:DefineElement("RadioButton", {
4049 Base = {
4050 Callback = EmptyFunction,
4051 },
4052 Create = function(self, Config: RadioButton): GuiButton
4053 local Object = ReGui:InsertPrefab("RadioButton", Config)
4054 Object.Activated:Connect(function(...)
4055 local Callback = Config.Callback
4056 return Callback(Object, ...)
4057 end)
4058
4059 return Object
4060 end,
4061})
4062
4063export type Checkbox = {
4064 Label: string?,
4065 IsRadio: boolean?,
4066 Value: boolean,
4067 NoAnimation: boolean?,
4068 Callback: ((...any) -> unknown)?,
4069 SetValue: (self: Checkbox, Value: boolean, NoAnimation: boolean) -> ...any,
4070 Toggle: (self: Checkbox) -> ...any,
4071 TickedImageSize: UDim2,
4072 UntickedImageSize: UDim2,
4073}
4074ReGui:DefineElement("Checkbox", {
4075 Base = {
4076 Label = "Checkbox",
4077 IsRadio = false,
4078 Value = false,
4079 NoAutoTag = true,
4080 TickedImageSize = UDim2.fromScale(1, 1),
4081 UntickedImageSize = UDim2.fromScale(0,0),
4082 Callback = EmptyFunction,
4083 Disabled = false
4084 },
4085 Create = function(Canvas, Config: Checkbox): Checkbox
4086 --// Unpack configuration
4087 local IsRadio = Config.IsRadio
4088 local Value = Config.Value
4089 local Text = Config.Label
4090 local TickedSize = Config.TickedImageSize
4091 local UntickedSize = Config.UntickedImageSize
4092 local Disabled = Config.Disabled
4093
4094 --// Check checkbox object
4095 local Object = ReGui:InsertPrefab("CheckBox", Config)
4096 local Class = ReGui:MergeMetatables(Config, Object)
4097
4098 local Tickbox = Object.Tickbox
4099 local Tick = Tickbox.Tick
4100 Tick.Image = ReGui.Icons.Checkmark
4101
4102 --// Styles
4103 local UIPadding = Tickbox:FindFirstChildOfClass("UIPadding")
4104 local UICorner = ReGui:GetChildOfClass(Tickbox, "UICorner")
4105
4106 --// Create label
4107 local Label = Canvas:Label({
4108 Text = Text,
4109 Parent = Object,
4110 LayoutOrder = 2
4111 })
4112
4113 --// Stylise to correct type
4114 local PaddingSize = UDim.new(0, 3)
4115 if IsRadio then
4116 Tick.ImageTransparency = 1
4117 Tick.BackgroundTransparency = 0
4118 UICorner.CornerRadius = UDim.new(1, 0)
4119 else
4120 PaddingSize = UDim.new(0, 2)
4121 end
4122
4123 --// Apply UIPadding sizes
4124 ReGui:SetProperties(UIPadding, {
4125 PaddingBottom = PaddingSize,
4126 PaddingLeft = PaddingSize,
4127 PaddingRight = PaddingSize,
4128 PaddingTop = PaddingSize,
4129 })
4130
4131 --// Callback
4132 local function Callback(...)
4133 local func = Config.Callback
4134 return func(Class, ...)
4135 end
4136
4137 local function SetStyle(Value: boolean, NoAnimation: boolean)
4138 local Tweeninfo = Canvas:GetThemeKey("AnimationTweenInfo")
4139
4140 --// Animate tick
4141 local Size = Value and TickedSize or UntickedSize
4142 Animation:Tween({
4143 Object = Tick,
4144 Tweeninfo = Tweeninfo,
4145 NoAnimation = NoAnimation,
4146 EndProperties = {
4147 Size = Size
4148 }
4149 })
4150 end
4151
4152 function Config:SetDisabled(Disabled: boolean)
4153 self.Disabled = Disabled
4154 Object.Interactable = not Disabled
4155
4156 Canvas:SetColorTags({
4157 [Label] = Disabled and "LabelDisabled" or "Label"
4158 }, true)
4159 end
4160
4161 function Config:SetValue(Value: boolean, NoAnimation: boolean)
4162 self.Value = Value
4163
4164 --// Animate
4165 SetStyle(Value, NoAnimation)
4166
4167 --// Fire callback
4168 Callback(Value)
4169
4170 return self
4171 end
4172
4173 function Config:SetTicked(...)
4174 ReGui:Warn("Checkbox:SetTicked is deprecated, please use :SetValue")
4175 return self:SetValue(...)
4176 end
4177
4178 function Config:Toggle()
4179 local Value = not self.Value
4180 self.Value = Value
4181 self:SetValue(Value)
4182
4183 return self
4184 end
4185
4186 --// Connect functions
4187 local function Clicked()
4188 Config:Toggle()
4189 end
4190
4191 --// Connect events
4192 Object.Activated:Connect(Clicked)
4193 Tickbox.Activated:Connect(Clicked)
4194
4195 --// Update object state
4196 Config:SetValue(Value, true)
4197 Config:SetDisabled(Disabled)
4198
4199 --// Style elements
4200 ReGui:SetAnimation(Tickbox, "Buttons", Object)
4201 Canvas:TagElements({
4202 [Tick] = "CheckMark",
4203 [Tickbox] = "Checkbox"
4204 })
4205
4206 return Class, Object
4207 end,
4208})
4209
4210ReGui:DefineElement("Radiobox", {
4211 Base = {
4212 IsRadio = true,
4213 CornerRadius = UDim.new(1,0),
4214 },
4215 Create = Elements.Checkbox,
4216})
4217
4218export type PlotHistogram = {
4219 Label: string?,
4220 Points: {
4221 [number]: number
4222 },
4223 Minimum: number?,
4224 Maximum: number?,
4225 GetBaseValues: (PlotHistogram) -> (number, number),
4226 UpdateGraph: (PlotHistogram) -> PlotHistogram,
4227 PlotGraph: (PlotHistogram, Points: {
4228 [number]: number
4229 }) -> PlotHistogram,
4230 Plot: (PlotHistogram, Value: number) -> {
4231 SetValue: (Plot, Value: number) -> nil,
4232 GetPointIndex: (Plot) -> number,
4233 Remove: (Plot, Value: number) -> nil,
4234 },
4235}
4236ReGui:DefineElement("PlotHistogram", {
4237 Base = {
4238 ColorTag = "Frame",
4239 Label = "Histogram"
4240 },
4241 Create = function(Canvas, Config: PlotHistogram)
4242 --// Unpack configuration
4243 local LabelText = Config.Label
4244 local Points = Config.Points
4245
4246 --// Create Object
4247 local Object = ReGui:InsertPrefab("Histogram", Config)
4248 local Class = ReGui:MergeMetatables(Config, Object)
4249
4250 local GraphCanvas = Object.Canvas
4251 local PointTemplate = GraphCanvas.PointTemplate
4252 PointTemplate.Visible = false --// Hide template
4253
4254 local Label = Canvas:Label({
4255 Text = LabelText,
4256 Parent = Object,
4257 Position = UDim2.new(1, 4)
4258 })
4259
4260 --// Create tooltip
4261 local ValueLabel = nil
4262 ReGui:SetItemTooltip(Object, function(Canvas)
4263 ValueLabel = Canvas:Label()
4264 end)
4265
4266 Merge(Config, {
4267 _Plots = {},
4268 _Cache = {}
4269 })
4270
4271 function Config:GetBaseValues(): (number, number)
4272 local Minimum = self.Minimum
4273 local Maximum = self.Maximum
4274
4275 --// User defined minimum
4276 if Minimum and Maximum then
4277 return Minimum, Maximum
4278 end
4279
4280 local Plots = self._Plots
4281
4282 for _, Data in Plots do
4283 local Value = Data.Value
4284
4285 --// Minimum
4286 if not Minimum or Value < Minimum then
4287 Minimum = Value
4288 end
4289
4290 --// Maximum
4291 if not Maximum or Value > Maximum then
4292 Maximum = Value
4293 end
4294 end
4295
4296 return Minimum, Maximum
4297 end
4298
4299 function Config:UpdateGraph()
4300 local Plots = self._Plots
4301
4302 local Minimum, Maximum = self:GetBaseValues()
4303 if not Minimum or not Maximum then return end
4304
4305 local Difference = Maximum - Minimum
4306
4307 --// Update each plot on the graph
4308 for _, Data in Plots do
4309 local Point = Data.Point
4310 local Value = Data.Value
4311
4312 local Scale = (Value - Minimum) / Difference
4313 Scale = math.clamp(Scale, 0.05, 1)
4314
4315 Point.Size = UDim2.fromScale(1, Scale)
4316 end
4317
4318 return self
4319 end
4320
4321 function Config:Plot(Value)
4322 local Plots = self._Plots
4323 local Module = {}
4324
4325 --// Create a new plot Object
4326 local Plot = PointTemplate:Clone()
4327 local Point = Plot.Bar
4328
4329 ReGui:SetProperties(Plot, {
4330 Parent = GraphCanvas,
4331 Visible = true
4332 })
4333
4334 local HoverConnection = ReGui:DetectHover(Plot, {
4335 MouseEnter = true,
4336 OnInput = function()
4337 Module:UpdateTooltip()
4338 end,
4339 })
4340
4341 local Data = {
4342 Object = Plot,
4343 Point = Point,
4344 Value = Value
4345 }
4346
4347 function Module:UpdateTooltip()
4348 local Index = Module:GetPointIndex()
4349 ValueLabel.Text = `{Index}: {Data.Value}`
4350 end
4351
4352 function Module:SetValue(Value)
4353 Data.Value = Value
4354 Config:UpdateGraph()
4355
4356 --// Update tooltip value if hovered
4357 if HoverConnection.Hovering then
4358 self:UpdateTooltip()
4359 end
4360 end
4361
4362 function Module:GetPointIndex(): number
4363 return table.find(Plots, Data)
4364 end
4365
4366 function Module:Remove(Value)
4367 table.remove(Plots, self:GetPointIndex())
4368 Plot:Remove()
4369 Config:UpdateGraph()
4370 end
4371
4372 --// Registor plot
4373 table.insert(Plots, Data)
4374
4375 --// Update the graph with new values
4376 self:UpdateGraph()
4377
4378 --// Style the plot object
4379 ReGui:SetAnimation(Point, "Plots", Plot)
4380 Canvas:TagElements({
4381 [Point] = "Plot"
4382 })
4383
4384 return Module
4385 end
4386
4387 function Config:PlotGraph(Points)
4388 local Cache = self._Cache
4389
4390 --// Remove unsused graph points
4391 local Extra = #Cache-#Points
4392 if Extra >= 1 then
4393 --// Remove unused graph points
4394 for Index = 1, Extra do
4395 local Point = table.remove(Cache, Index)
4396 if Point then
4397 Point:Remove()
4398 end
4399 end
4400 end
4401
4402 for Index, Value in Points do
4403 --// Use existing point
4404 local Point = Cache[Index]
4405 if Point then
4406 Point:SetValue(Value)
4407 continue
4408 end
4409
4410 --// Create new point
4411 Cache[Index] = self:Plot(Value)
4412 end
4413
4414 return self
4415 end
4416
4417 --// Display points
4418 if Points then
4419 Config:PlotGraph(Points)
4420 end
4421
4422 return Class, Object
4423 end,
4424})
4425
4426
4427export type Viewport = {
4428 Model: Instance,
4429 WorldModel: WorldModel?,
4430 Viewport: ViewportFrame?,
4431 Camera: Camera?,
4432 Clone: boolean?,
4433
4434 SetCamera: (self: Viewport, Camera: Camera) -> Viewport,
4435 SetModel: (self: Viewport, Model: Model, PivotTo: CFrame?) -> Model,
4436}
4437ReGui:DefineElement("Viewport", {
4438 Base = {
4439 IsRadio = true,
4440 },
4441 Create = function(self, Config: Viewport): Viewport
4442 --// Unpack configuration
4443 local Model = Config.Model
4444 local Camera = Config.Camera
4445
4446 --// Create viewport object
4447 local Object = ReGui:InsertPrefab("Viewport", Config)
4448 local Class = ReGui:MergeMetatables(Config, Object)
4449
4450 local Viewport = Object.Viewport
4451 local WorldModel = Viewport.WorldModel
4452
4453 if not Camera then
4454 Camera = ReGui:CreateInstance("Camera", Viewport)
4455 Camera.CFrame = CFrame.new(0,0,0)
4456 end
4457
4458 Merge(Config, {
4459 Camera = Camera,
4460 WorldModel = WorldModel,
4461 Viewport = Viewport
4462 })
4463
4464 function Config:SetCamera(Camera)
4465 self.Camera = Camera
4466 Viewport.CurrentCamera = Camera
4467 return self
4468 end
4469
4470 function Config:SetModel(Model: Model, PivotTo: CFrame?)
4471 local CreateClone = self.Clone
4472
4473 WorldModel:ClearAllChildren()
4474
4475 --// Set new model
4476 if CreateClone then
4477 Model = Model:Clone()
4478 end
4479
4480 if PivotTo then
4481 Model:PivotTo(PivotTo)
4482 end
4483
4484 Model.Parent = WorldModel
4485 self.Model = Model
4486
4487 return Model
4488 end
4489
4490 --// Set model
4491 if Model then
4492 Config:SetModel(Model)
4493 end
4494
4495 Config:SetCamera(Camera)
4496
4497 return Class, Object
4498 end,
4499})
4500
4501export type InputText = {
4502 Value: string,
4503 Placeholder: string?,
4504 MultiLine: boolean?,
4505 Label: string?,
4506 Disabled: boolean?,
4507
4508 Callback: ((string, ...any) -> unknown)?,
4509 Clear: (InputText) -> InputText,
4510 SetValue: (InputText, Value: string) -> InputText,
4511 SetDisabled: (InputText, Disabled: boolean) -> InputText,
4512}
4513ReGui:DefineElement("InputText", {
4514 Base = {
4515 Value = "",
4516 Placeholder = "",
4517 Label = "Input text",
4518 Callback = EmptyFunction,
4519 MultiLine = false,
4520 NoAutoTag = true,
4521 Disabled = false
4522 },
4523 Create = function(Canvas, Config: InputText): InputText
4524 --// Unpack configuration
4525 local MultiLine = Config.MultiLine
4526 local Placeholder = Config.Placeholder
4527 local Label = Config.Label
4528 local Disabled = Config.Disabled
4529 local Value = Config.Value
4530
4531 --// Create Text input object
4532 local Object = ReGui:InsertPrefab("InputBox", Config)
4533 local Frame = Object.Frame
4534 local TextBox = Frame.Input
4535
4536 local Class = ReGui:MergeMetatables(Config, Object)
4537
4538 Canvas:Label({
4539 Parent = Object,
4540 Text = Label,
4541 AutomaticSize = Enum.AutomaticSize.X,
4542 Size = UDim2.fromOffset(0, 19),
4543 Position = UDim2.new(1, 4),
4544 LayoutOrder = 2
4545 })
4546
4547 ReGui:SetProperties(TextBox, {
4548 PlaceholderText = Placeholder,
4549 MultiLine = MultiLine
4550 })
4551
4552 local function Callback(...)
4553 local Func = Config.Callback
4554 Func(Class, ...)
4555 end
4556
4557 function Config:SetValue(Value: string?)
4558 TextBox.Text = tostring(Value)
4559 self.Value = Value
4560 return self
4561 end
4562
4563 function Config:SetDisabled(Disabled: boolean)
4564 self.Disabled = Disabled
4565 Object.Interactable = not Disabled
4566 Canvas:SetColorTags({
4567 [Label] = Disabled and "LabelDisabled" or "Label"
4568 }, true)
4569 return self
4570 end
4571
4572 function Config:Clear()
4573 TextBox.Text = ""
4574 return self
4575 end
4576
4577 local function TextChanged()
4578 local Value = TextBox.Text
4579 Config.Value = Value
4580 Callback(Value)
4581 end
4582
4583 --// Connect events
4584 TextBox:GetPropertyChangedSignal("Text"):Connect(TextChanged)
4585
4586 --// Update object state
4587 Config:SetDisabled(Disabled)
4588 Config:SetValue(Value)
4589
4590 Canvas:TagElements({
4591 [TextBox] = "Frame"
4592 })
4593
4594 return Class, Object
4595 end,
4596})
4597
4598export type InputInt = {
4599 Value: number,
4600 Maximum: number?,
4601 Minimum: number?,
4602 Placeholder: string?,
4603 MultiLine: boolean?,
4604 NoButtons: boolean?,
4605 Label: string?,
4606 Increment: number?,
4607 Callback: ((string, ...any) -> unknown)?,
4608 SetValue: (InputInt, Value: number, NoTextUpdate: boolean?) -> InputInt,
4609 Decrease: (InputInt) -> nil,
4610 Increase: (InputInt) -> nil,
4611}
4612ReGui:DefineElement("InputInt", {
4613 Base = {
4614 Value = 0,
4615 Increment = 1,
4616 Placeholder = "",
4617 Label = "Input Int",
4618 Callback = EmptyFunction,
4619 },
4620 Create = function(Canvas, Config: InputInt): InputInt
4621 --// Unpack configuration
4622 local Value = Config.Value
4623 local Placeholder = Config.Placeholder
4624 local LabelText = Config.Label
4625 local Disabled = Config.Disabled
4626 local NoButtons = Config.NoButtons
4627
4628 --// Create Text input object
4629 local Object = ReGui:InsertPrefab("InputBox", Config)
4630 local Class = ReGui:MergeMetatables(Config, Object)
4631
4632 local Frame = Object.Frame
4633 local TextBox = Frame.Input
4634 TextBox.PlaceholderText = Placeholder
4635
4636 --// Decrease
4637 local Decrease = Canvas:Button({
4638 Text = "-",
4639 Parent = Frame,
4640 LayoutOrder = 2,
4641 Ratio = 1,
4642 AutomaticSize = Enum.AutomaticSize.None,
4643 FlexMode = Enum.UIFlexMode.None,
4644 Size = UDim2.fromScale(1,1),
4645 Visible = not NoButtons,
4646 Callback = function()
4647 Config:Decrease()
4648 end,
4649 })
4650
4651 --// Increase
4652 local Increase = Canvas:Button({
4653 Text = "+",
4654 Parent = Frame,
4655 LayoutOrder = 3,
4656 Ratio = 1,
4657 AutomaticSize = Enum.AutomaticSize.None,
4658 FlexMode = Enum.UIFlexMode.None,
4659 Size = UDim2.fromScale(1,1),
4660 Visible = not NoButtons,
4661 Callback = function()
4662 Config:Increase()
4663 end,
4664 })
4665
4666 local Label = Canvas:Label({
4667 Parent = Object,
4668 Text = LabelText,
4669 AutomaticSize = Enum.AutomaticSize.X,
4670 Size = UDim2.fromOffset(0, 19),
4671 Position = UDim2.new(1, 4),
4672 LayoutOrder = 4
4673 })
4674
4675 local function Callback(...)
4676 local Func = Config.Callback
4677 Func(Class, ...)
4678 end
4679
4680 function Config:Increase()
4681 local Value = self.Value
4682 local Increment = self.Increment
4683 Config:SetValue(Value + Increment)
4684 end
4685
4686 function Config:Decrease()
4687 local Value = self.Value
4688 local Increment = self.Increment
4689 Config:SetValue(Value - Increment)
4690 end
4691
4692 function Config:SetDisabled(Disabled: boolean)
4693 self.Disabled = Disabled
4694 Object.Interactable = not Disabled
4695 Canvas:SetColorTags({
4696 [Label] = Disabled and "LabelDisabled" or "Label"
4697 }, true)
4698 end
4699
4700 function Config:SetValue(Value: number?)
4701 local Previous = self.Value
4702 local Minimum = self.Minimum
4703 local Maximum = self.Maximum
4704
4705 --// Replace empty string value with 0
4706 Value = tonumber(Value)
4707
4708 --// Check if value is accepted
4709 if not Value then
4710 Value = Previous
4711 end
4712
4713 --// Clamp value into a limied range
4714 if Minimum and Maximum then
4715 Value = math.clamp(Value, Minimum, Maximum)
4716 end
4717
4718 --// Update values
4719 TextBox.Text = Value
4720 Config.Value = Value
4721 Callback(Value)
4722
4723 return self
4724 end
4725
4726 local function TextChanged()
4727 local New = TextBox.Text
4728 Config:SetValue(New)
4729 end
4730
4731 --// Update object state
4732 Config:SetValue(Value)
4733 Config:SetDisabled(Disabled)
4734
4735 --// Connect events
4736 TextBox.FocusLost:Connect(TextChanged)
4737
4738 --// Register elements
4739 Canvas:TagElements({
4740 [Increase] = "Button",
4741 [Decrease] = "Button",
4742 [TextBox] = "Frame",
4743 })
4744
4745 return Class, Object
4746 end,
4747})
4748
4749ReGui:DefineElement("InputTextMultiline", {
4750 Base = {
4751 Label = "",
4752 Size = UDim2.new(1, 0, 0, 39),
4753 Border = false,
4754 ColorTag = "Frame"
4755 },
4756 Create = function(self, Config)
4757 return self:Console(Config)
4758 end,
4759})
4760
4761export type Console = {
4762 Enabled: boolean?,
4763 ReadOnly: boolean?,
4764 Value: string?,
4765 RichText: boolean?,
4766 TextWrapped: boolean?,
4767 LineNumbers: boolean?,
4768 AutoScroll: boolean,
4769 LinesFormat: string,
4770 MaxLines: number,
4771
4772 UpdateLineNumbers: (Console) -> Console,
4773 UpdateScroll: (Console) -> Console,
4774 SetValue: (Console, Value: string) -> Console,
4775 GetValue: (Console) -> string,
4776 Clear: (Console) -> Console,
4777 AppendText: (Console, ...string) -> Console,
4778 CheckLineCount: (Console) -> Console
4779}
4780ReGui:DefineElement("Console", {
4781 Base = {
4782 Enabled = true,
4783 Value = "",
4784 TextWrapped = false,
4785 Border = true,
4786 MaxLines = 300,
4787 LinesFormat = "%s",
4788 Callback = EmptyFunction,
4789 },
4790 Create = function(self, Config: Console): Console
4791 --// Unpack configuration
4792 local ReadOnly = Config.ReadOnly
4793 local LineNumbers = Config.LineNumbers
4794 local Fill = Config.Fill
4795 local Value = Config.Value
4796 local Placeholder = Config.Placeholder
4797
4798 --// Create console object
4799 local Object = ReGui:InsertPrefab("Console", Config)
4800 local Class = ReGui:MergeMetatables(Config, Object)
4801
4802 local Source: TextBox = Object.Source
4803 local Lines = Object.Lines
4804
4805 ReGui:SetProperties(Source, Config)
4806 ReGui:SetProperties(Source, {
4807 TextEditable = not ReadOnly,
4808 Parent = Object,
4809 PlaceholderText = Placeholder
4810 })
4811
4812 Lines.Visible = LineNumbers
4813
4814 function Config:UpdateLineNumbers()
4815 --// configuration
4816 local LineNumbers = self.LineNumbers
4817 local Format = self.LinesFormat
4818
4819 --// If line counts are disabled
4820 if not LineNumbers then return end
4821
4822 local LinesCount = #Source.Text:split("\n")
4823
4824 --// Update lines text
4825 Lines.Text = ""
4826
4827 for Line = 1, LinesCount do
4828 local Text = Format:format(Line)
4829 local End = Line ~= LinesCount and '\n' or ''
4830 Lines.Text ..= `{Text}{End}`
4831 end
4832
4833 --// Update console size to fit line numbers
4834 local LinesWidth = Lines.AbsoluteSize.X
4835 Source.Size = UDim2.new(1, -LinesWidth, 0, 0)
4836
4837 return self
4838 end
4839
4840 function Config:CheckLineCount()
4841 --// configuration
4842 local MaxLines = Config.MaxLines
4843 if not MaxLines then return end
4844
4845 local Text = Source.Text
4846 local Lines = Text:split("\n")
4847
4848 --// Cut the first line
4849 if #Lines > MaxLines then
4850 local Line = `{Lines[1]}\\n`
4851 local Cropped = Text:sub(#Line)
4852 self:SetValue(Cropped)
4853 end
4854
4855 return self
4856 end
4857
4858 function Config:UpdateScroll()
4859 local CanvasSize = Object.AbsoluteCanvasSize
4860 Object.CanvasPosition = Vector2.new(0, CanvasSize.Y)
4861 return self
4862 end
4863
4864 function Config:SetValue(Text: string?)
4865 if not self.Enabled then return end
4866
4867 Source.Text = tostring(Text)
4868 self:Update()
4869
4870 return self
4871 end
4872
4873 function Config:GetValue()
4874 return Source.Text
4875 end
4876
4877 function Config:Clear()
4878 Source.Text = ""
4879 self:Update()
4880 return self
4881 end
4882
4883 function Config:AppendText(...)
4884 local NewString = "\n" .. ReGui:Concat({...}, " ")
4885
4886 --// Append string
4887 local Value = self:GetValue()
4888 self:SetValue(Value..NewString)
4889
4890 --// Check if content needs to be cut
4891 self:CheckLineCount()
4892
4893 return self
4894 end
4895
4896 function Config:Update()
4897 --// Configuration
4898 local AutoScroll = Config.AutoScroll
4899
4900 Config:UpdateLineNumbers()
4901
4902 --// Automatically scroll to bottom
4903 if AutoScroll then
4904 Config:UpdateScroll()
4905 end
4906 end
4907
4908 local function Changed()
4909 local Value = Config:GetValue()
4910 Config:Update()
4911 Config.Callback(Value)
4912 end
4913
4914 --// Update element
4915 Config:SetValue(Value)
4916
4917 self:TagElements({
4918 [Source] = "ConsoleText",
4919 [Lines] = "ConsoleLineNumbers",
4920 })
4921
4922 --// Connect events
4923 Source:GetPropertyChangedSignal("Text"):Connect(Changed)
4924
4925 return Class, Object
4926 end,
4927})
4928
4929export type Table = {
4930 Align: string?,
4931 Border: boolean?,
4932 RowBackground: boolean?,
4933 RowBgTransparency: number?,
4934 MaxColumns: number?,
4935
4936 Row: (Table) -> {
4937 Column: (Row) -> Elements
4938 },
4939 ClearRows: (Table) -> unknown,
4940}
4941ReGui:DefineElement("Table", {
4942 Base = {
4943 VerticalAlignment = Enum.VerticalAlignment.Top,
4944 RowBackground = false,
4945 RowBgTransparency = 0.87,
4946 Border = false,
4947 Spacing = UDim.new(0, 4)
4948 },
4949 Create = function(Canvas, Config: Table): Table
4950 local WindowClass = Canvas.WindowClass
4951
4952 --// Unpack configuration
4953 local RowTransparency = Config.RowBgTransparency
4954 local RowBackground = Config.RowBackground
4955 local Border = Config.Border
4956 local VerticalAlignment = Config.VerticalAlignment
4957 local MaxColumns = Config.MaxColumns
4958 local Spacing = Config.Spacing
4959
4960 --// Create table object
4961 local Object = ReGui:InsertPrefab("Table", Config)
4962 local Class = ReGui:MergeMetatables(Config, Object)
4963
4964 local RowTemplate = Object.RowTemp
4965 local RowsCount = 0
4966 local Rows = {}
4967 local HasStyling = Border and RowBackground
4968
4969 function Config:Row(Config)
4970 Config = Config or {}
4971
4972 local IsHeader = Config.IsHeader
4973
4974 local ColumnIndex = 0
4975 local Columns = {}
4976
4977 --// Create Row object (Different to :Row)
4978 local Row = RowTemplate:Clone()
4979 ReGui:SetProperties(Row, {
4980 Name = "Row",
4981 Visible = true,
4982 Parent = Object,
4983 })
4984
4985 --// Set alignment
4986 local UIListLayout = Row:FindFirstChildOfClass("UIListLayout")
4987 ReGui:SetProperties(UIListLayout, {
4988 VerticalAlignment = VerticalAlignment,
4989 Padding = not HasStyling and Spacing or UDim.new(0, 1)
4990 })
4991
4992 --// Apply header styles
4993 if IsHeader then
4994 Canvas:TagElements({
4995 [Row] = "Header"
4996 })
4997 else
4998 RowsCount += 1
4999 end
5000
5001 --// RowBackground background colors for rows
5002 if RowBackground and not IsHeader then
5003 local Transparency = RowsCount % 2 ~= 1 and RowTransparency or 1
5004 Row.BackgroundTransparency = Transparency
5005 end
5006
5007 --// Row class
5008 local RowClass = {}
5009 local Class = ReGui:MergeMetatables(RowClass, Row)
5010
5011 function RowClass:Column(Config)
5012 Config = Config or {}
5013
5014 ReGui:CheckConfig(Config, {
5015 HorizontalAlign = Enum.HorizontalAlignment.Left,
5016 VerticalAlignment = Enum.VerticalAlignment.Top,
5017 })
5018
5019 --// Create column object
5020 local Column = Row.ColumnTemp:Clone()
5021
5022 --// ListLayout Properties
5023 local ListLayout = Column:FindFirstChildOfClass("UIListLayout")
5024 ReGui:SetProperties(ListLayout, Config)
5025
5026 --// Set border enabled based on Flag
5027 local Stroke = Column:FindFirstChildOfClass("UIStroke")
5028 Stroke.Enabled = Border
5029
5030 --// Remove padding if there is no styling
5031 local UIPadding = Column:FindFirstChildOfClass("UIPadding")
5032 if not HasStyling then
5033 UIPadding:Destroy()
5034 end
5035
5036 --// Column Properties
5037 ReGui:SetProperties(Column, {
5038 Parent = Row,
5039 Visible = true,
5040 Name = "Column"
5041 })
5042
5043 --// Content canvas
5044 return ReGui:MakeCanvas({
5045 Element = Column,
5046 WindowClass = WindowClass,
5047 Class = Class
5048 })
5049 end
5050
5051 function RowClass:NextColumn()
5052 ColumnIndex += 1
5053
5054 local Index = ColumnIndex % MaxColumns + 1
5055 local Column = Columns[Index]
5056
5057 --// Create Column
5058 if not Column then
5059 Column = self:Column()
5060 Columns[Index] = Column
5061 end
5062
5063 return Column
5064 end
5065
5066 table.insert(Rows, RowClass)
5067
5068 --// Content canvas
5069 return Class
5070 end
5071
5072 --// TODO:
5073 function Config:NextRow()
5074 return self:Row()
5075 end
5076
5077 function Config:HeaderRow()
5078 return self:Row({
5079 IsHeader = true
5080 })
5081 end
5082
5083 function Config:ClearRows()
5084 RowsCount = 0
5085
5086 --// Destroy each row
5087 for _, Row: Frame in next, Object:GetChildren() do
5088 if not Row:IsA("Frame") then continue end
5089 if Row == RowTemplate then continue end
5090
5091 Row:Destroy()
5092 end
5093
5094 return Config
5095 end
5096
5097 return Class, Object
5098 end,
5099})
5100
5101export type List = {
5102 Spacing: number?
5103}
5104ReGui:DefineElement("List", {
5105 Base = {
5106 Spacing = 4,
5107 HorizontalFlex = Enum.UIFlexAlignment.None,
5108 VerticalFlex = Enum.UIFlexAlignment.None,
5109 HorizontalAlignment = Enum.HorizontalAlignment.Left,
5110 VerticalAlignment = Enum.VerticalAlignment.Top,
5111 FillDirection = Enum.FillDirection.Horizontal,
5112 },
5113 Create = function(self, Config)
5114 local WindowClass = self.WindowClass
5115
5116 --// Unpack configuration
5117 local Spacing = Config.Spacing
5118 local HorizontalFlex = Config.HorizontalFlex
5119 local VerticalFlex = Config.VerticalFlex
5120 local HorizontalAlignment = Config.HorizontalAlignment
5121 local VerticalAlignment = Config.VerticalAlignment
5122 local FillDirection = Config.FillDirection
5123
5124 --// Create object
5125 local Object = ReGui:InsertPrefab("List", Config)
5126 local Class = ReGui:MergeMetatables(Config, Object)
5127
5128 local ListLayout: UIListLayout = Object.UIListLayout
5129 ReGui:SetProperties(ListLayout, {
5130 Padding = UDim.new(0, Spacing),
5131 HorizontalFlex = HorizontalFlex,
5132 VerticalFlex = VerticalFlex,
5133 HorizontalAlignment = HorizontalAlignment,
5134 VerticalAlignment = VerticalAlignment,
5135 FillDirection = FillDirection,
5136 })
5137
5138 --// Content canvas
5139 local Canvas = ReGui:MakeCanvas({
5140 Element = Object,
5141 WindowClass = WindowClass,
5142 Class = Class
5143 })
5144
5145 return Canvas, Object
5146 end,
5147})
5148
5149export type CollapsingHeader = {
5150 Title: string,
5151 CollapseIcon: string?,
5152 Icon: string?,
5153 NoAnimation: boolean?,
5154 Collapsed: boolean?,
5155 Offset: number?,
5156 NoArrow: boolean?,
5157 OpenOnDoubleClick: boolean?, -- Need double-click to open node
5158 OpenOnArrow: boolean?, -- Only open when clicking on the arrow
5159 Activated: (CollapsingHeader) -> nil,
5160
5161 Remove: (CollapsingHeader) -> nil,
5162 SetArrowVisible: (CollapsingHeader, Visible: boolean) -> nil,
5163 SetTitle: (CollapsingHeader, Title: string) -> nil,
5164 SetIcon: (CollapsingHeader, Icon: string) -> nil,
5165 SetVisible: (CollapsingHeader, Visible: boolean) -> nil,
5166 SetCollapsed: (CollapsingHeader, Open: boolean) -> CollapsingHeader
5167}
5168ReGui:DefineElement("CollapsingHeader", {
5169 Base = {
5170 Title = "Collapsing Header",
5171 CollapseIcon = ReGui.Icons.Arrow,
5172 Collapsed = true,
5173 Offset = 0,
5174 NoAutoTag = true,
5175 NoAutoFlags = true,
5176 IconPadding = UDim.new(0, 4),
5177 Activated = EmptyFunction
5178 },
5179 Create = function(Canvas, Config: CollapsingHeader): CollapsingHeader
5180 --// Unpack config
5181 local Title = Config.Title
5182 local Collapsed = Config.Collapsed
5183 local Style = Config.ElementStyle
5184 local Offset = Config.Offset
5185 local TitleProperties = Config.TitleBarProperties
5186 local OpenOnDoubleClick = Config.OpenOnDoubleClick
5187 local OpenOnArrow = Config.OpenOnArrow
5188 local CollapseIcon = Config.CollapseIcon
5189 local IconPadding = Config.IconPadding
5190 local Icon = Config.Icon
5191 local NoArrow = Config.NoArrow
5192
5193 --// Create header object
5194 local Object = ReGui:InsertPrefab("CollapsingHeader", Config)
5195
5196 local Titlebar = Object.TitleBar
5197 local Collapse = Titlebar.Collapse
5198 local IconImage = Titlebar.Icon
5199
5200 local CollapseButton = Collapse.CollapseIcon
5201 local CollapsePadding = Collapse.UIPadding
5202 ReGui:SetPadding(CollapsePadding, IconPadding)
5203
5204 local TitleText = Canvas:Label({
5205 ColorTag = "CollapsingHeader",
5206 Parent = Titlebar,
5207 LayoutOrder = 2
5208 })
5209
5210 --// Content canvas
5211 local Canvas, ContentFrame = Canvas:Indent({
5212 Class = Config,
5213 Parent = Object,
5214 Offset = Offset,
5215 LayoutOrder = 2,
5216 Size = UDim2.fromScale(1, 0),
5217 AutomaticSize = Enum.AutomaticSize.None,
5218 PaddingTop = UDim.new(0, 4),
5219 PaddingBottom = UDim.new(0, 1),
5220 })
5221
5222 CollapseButton.Image = ReGui:CheckAssetUrl(CollapseIcon)
5223
5224 local function Activated()
5225 local Callback = Config.Activated
5226 Callback(Canvas)
5227 end
5228
5229 function Config:Remove()
5230 Object:Destroy()
5231 table.clear(self)
5232 end
5233 function Config:SetArrowVisible(Visible: boolean)
5234 CollapseButton.Visible = Visible
5235 end
5236 function Config:SetTitle(Title: string)
5237 TitleText.Text = Title
5238 end
5239 function Config:SetVisible(Visible: boolean)
5240 Object.Visible = Visible
5241 end
5242 function Config:SetIcon(Icon: (string|number)?)
5243 local Visible = Icon and Icon ~= ""
5244 IconImage.Visible = Visible
5245
5246 if Visible then
5247 IconImage.Image = ReGui:CheckAssetUrl(Icon)
5248 end
5249 end
5250
5251 --// Open Animations
5252 function Config:SetCollapsed(Collapsed)
5253 self.Collapsed = Collapsed
5254
5255 local ContentSize = ReGui:GetContentSize(ContentFrame)
5256 local Tweeninfo = Canvas:GetThemeKey("AnimationTweenInfo")
5257
5258 --// Sizes
5259 local ClosedSize = UDim2.fromScale(1, 0)
5260 local OpenSize = ClosedSize + UDim2.fromOffset(0, ContentSize.Y)
5261
5262 Animation:HeaderCollapse({
5263 Tweeninfo = Tweeninfo,
5264 Collapsed = Collapsed,
5265 Toggle = CollapseButton,
5266 Resize = ContentFrame,
5267 Hide = ContentFrame,
5268
5269 --// Sizes
5270 ClosedSize = ClosedSize,
5271 OpenSize = OpenSize,
5272 })
5273
5274 return self
5275 end
5276
5277 local function Toggle()
5278 Config:SetCollapsed(not Config.Collapsed)
5279 end
5280
5281 --// Apply flags
5282 if TitleProperties then
5283 ReGui:ApplyFlags({
5284 Object = Titlebar,
5285 Class = TitleProperties
5286 })
5287 end
5288
5289 --// Connect events
5290 if not OpenOnArrow then
5291 ReGui:ConnectMouseEvent(Titlebar, {
5292 DoubleClick = OpenOnDoubleClick,
5293 Callback = Toggle,
5294 })
5295 end
5296 CollapseButton.Activated:Connect(Toggle)
5297 Titlebar.Activated:Connect(Activated)
5298
5299 --// Update object state
5300 Config:SetCollapsed(Collapsed)
5301 Config:SetTitle(Title)
5302 Config:SetIcon(Icon)
5303 Config:SetArrowVisible(not NoArrow)
5304
5305 --// Style elements
5306 ReGui:ApplyStyle(Titlebar, Style)
5307 Canvas:TagElements({
5308 [Titlebar] = "CollapsingHeader",
5309 })
5310
5311 return Canvas, Object
5312 end,
5313})
5314
5315ReGui:DefineElement("TreeNode", {
5316 Base = {
5317 Offset = 21,
5318 IconPadding = UDim.new(0, 2),
5319 TitleBarProperties = {
5320 Size = UDim2.new(1, 0, 0, 13)
5321 }
5322 },
5323 Create = Elements.CollapsingHeader,
5324})
5325
5326export type Separator = {
5327 Text: string?
5328}
5329ReGui:DefineElement("Separator", {
5330 Base = {
5331 NoAutoTag = true,
5332 NoAutoTheme = true
5333 },
5334 Create = function(self, Config)
5335 local Text = Config.Text
5336
5337 --// Create septator object
5338 local Object = ReGui:InsertPrefab("SeparatorText", Config)
5339
5340 local Label = self:Label({
5341 Text = tostring(Text),
5342 Visible = Text ~= nil,
5343 Parent = Object,
5344 LayoutOrder = 2,
5345 Size = UDim2.new(),
5346 PaddingLeft = UDim.new(0, 4),
5347 PaddingRight = UDim.new(0, 4),
5348 })
5349
5350 self:TagElements({
5351 [Object.Left] = "Separator",
5352 [Object.Right] = "Separator",
5353 })
5354
5355 return Object
5356 end,
5357})
5358
5359export type Canvas = {
5360 Scroll: boolean?,
5361 Class: table?
5362}
5363ReGui:DefineElement("Canvas", {
5364 Base = {},
5365 Create = function(self, Config: Canvas)
5366 local WindowClass = self.WindowClass
5367
5368 local Scroll = Config.Scroll
5369 local Class = Config.Class or Config
5370
5371 --// Create object
5372 local ObjectClass = Scroll and "ScrollingCanvas" or "Canvas"
5373 local Object = ReGui:InsertPrefab(ObjectClass, Config)
5374
5375 --// Content canvas
5376 local Canvas = ReGui:MakeCanvas({
5377 Element = Object,
5378 WindowClass = WindowClass,
5379 Class = Class
5380 })
5381
5382 return Canvas, Object
5383 end,
5384})
5385
5386ReGui:DefineElement("ScrollingCanvas", {
5387 Base = {
5388 Scroll = true
5389 },
5390 Create = Elements.Canvas
5391})
5392
5393export type Region = {
5394 Scroll: boolean?
5395}
5396ReGui:DefineElement("Region", {
5397 Base = {
5398 Scroll = false,
5399 AutomaticSize = Enum.AutomaticSize.Y
5400 },
5401 Create = function(self, Config: Region)
5402 local WindowClass = self.WindowClass
5403
5404 local Scroll = Config.Scroll
5405 local Class = Scroll and "ScrollingCanvas" or "Canvas"
5406
5407 --// Create object
5408 local Object = ReGui:InsertPrefab(Class, Config)
5409
5410 --// Content canvas
5411 local Canvas = ReGui:MakeCanvas({
5412 Element = Object,
5413 WindowClass = WindowClass,
5414 Class = Config
5415 })
5416
5417 return Canvas, Object
5418 end,
5419})
5420
5421ReGui:DefineElement("Group", {
5422 Base = {
5423 Scroll = false,
5424 AutomaticSize = Enum.AutomaticSize.Y
5425 },
5426 Create = function(self, Config)
5427 local WindowClass = self.WindowClass
5428
5429 --// Create object
5430 local Object = ReGui:InsertPrefab("Group", Config)
5431
5432 --// Content canvas
5433 local Canvas = ReGui:MakeCanvas({
5434 Element = Object,
5435 WindowClass = WindowClass,
5436 Class = Config
5437 })
5438
5439 return Canvas, Object
5440 end,
5441})
5442
5443export type Indent = {
5444 Offset: number?
5445}
5446ReGui:DefineElement("Indent", {
5447 Base = {
5448 Offset = 15,
5449 PaddingTop = UDim.new(),
5450 PaddingBottom = UDim.new(),
5451 PaddingRight = UDim.new(),
5452 },
5453 Create = function(self, Config: Indent)
5454 local Offset = Config.Offset
5455 Config.PaddingLeft = UDim.new(0, Offset)
5456
5457 return self:Canvas(Config)
5458 end,
5459})
5460
5461export type BulletText = {
5462 Padding: number,
5463 Icon: (string|number)?,
5464 Rows: {
5465 [number]: string?,
5466 }
5467}
5468ReGui:DefineElement("BulletText", {
5469 Base = {},
5470 Create = function(self, Config: BulletText)
5471 local Rows = Config.Rows
5472
5473 --// Create each row
5474 for _, Text in next, Rows do
5475 local Object = self:Bullet(Config)
5476 Object:Label({
5477 Text = tostring(Text),
5478 LayoutOrder = 2,
5479 Size = UDim2.fromOffset(0,14),
5480 })
5481 end
5482 end,
5483})
5484
5485export type Bullet = {
5486 Padding: number?
5487}
5488ReGui:DefineElement("Bullet", {
5489 Base = {
5490 Padding = 3,
5491 Icon = ReGui.Icons.Dot,
5492 IconSize = UDim2.fromOffset(5,5)
5493 },
5494 Create = function(self, Config: Bullet)
5495 local WindowClass = self.WindowClass
5496
5497 --// Unpack configuration
5498 local Padding = Config.Padding
5499
5500 --// Create object
5501 local Object = ReGui:InsertPrefab("Bullet", Config)
5502
5503 --// Content canvas
5504 local Canvas = ReGui:MakeCanvas({
5505 Element = Object,
5506 WindowClass = WindowClass,
5507 Class = self
5508 })
5509
5510 --// Apply padding
5511 local ListLayout = Object.UIListLayout
5512 ListLayout.Padding = UDim.new(0, Padding)
5513
5514 return Canvas, Object
5515 end,
5516})
5517
5518export type Row = {
5519 Spacing: number?,
5520 Expanded: boolean?,
5521 HorizontalFlex: Enum.UIFlexAlignmen?,
5522 VerticalFlex: Enum.UIFlexAlignmen?,
5523 Expand: (Row) -> Row
5524}
5525ReGui:DefineElement("Row", {
5526 Base = {
5527 Spacing = 4,
5528 Expanded = false,
5529 HorizontalFlex = Enum.UIFlexAlignment.None,
5530 VerticalFlex = Enum.UIFlexAlignment.None,
5531 },
5532 Create = function(self, Config: Row)
5533 local WindowClass = self.WindowClass
5534
5535 --// Unpack configuration
5536 local Spacing = Config.Spacing
5537 local Expanded = Config.Expanded
5538 local HorizontalFlex = Config.HorizontalFlex
5539 local VerticalFlex = Config.VerticalFlex
5540
5541 --// Create row object
5542 local Object = ReGui:InsertPrefab("Row", Config)
5543 local Class = ReGui:MergeMetatables(Config, Object)
5544
5545 local UIListLayout = Object:FindFirstChildOfClass("UIListLayout")
5546 UIListLayout.Padding = UDim.new(0, Spacing)
5547 UIListLayout.HorizontalFlex = HorizontalFlex
5548 UIListLayout.VerticalFlex = VerticalFlex
5549
5550 --// Content canvas
5551 local Canvas = ReGui:MakeCanvas({
5552 Element = Object,
5553 WindowClass = WindowClass,
5554 Class = Class
5555 })
5556
5557 function Config:Expand()
5558 UIListLayout.HorizontalFlex = Enum.UIFlexAlignment.Fill
5559 return self
5560 end
5561
5562 --// Expand if Fill flag is enabled
5563 if Expanded then
5564 Config:Expand()
5565 end
5566
5567 return Canvas, Object
5568 end,
5569})
5570
5571--TODO
5572-- Vertical
5573export type SliderIntFlags = {
5574 Value: number?,
5575 Format: string?,
5576 Label: string?,
5577 Progress: boolean?,
5578 NoGrab: boolean?,
5579 Minimum: number,
5580 Maximum: number,
5581 NoAnimation: boolean?,
5582 Callback: (number) -> any?,
5583 ReadOnly: boolean?,
5584 SetValue: (SliderInt, Value: number, IsSlider: boolean?) -> SliderInt?,
5585 SetDisabled: (SliderInt, Disabled: boolean) -> SliderInt,
5586 MakeProgress: (SliderInt) -> nil?,
5587}
5588ReGui:DefineElement("SliderBase", {
5589 Base = {
5590 Format = "%.f", -- "%.f/%s",
5591 Label = "",
5592 Type = "Slider",
5593 Callback = EmptyFunction,
5594 NoGrab = false,
5595 NoClick = false,
5596 Minimum = 0,
5597 Maximum = 100,
5598 ColorTag = "Frame",
5599 Disabled = false,
5600 },
5601 Create = function(Canvas, Config)
5602 --// Unpack config
5603 local Value = Config.Value or Config.Minimum
5604 local Format = Config.Format
5605 local LabelText = Config.Label
5606 local NoAnimation = Config.NoAnimation
5607 local NoGrab = Config.NoGrab
5608 local NoClick = Config.NoClick
5609 local Type = Config.Type
5610 local Disabled = Config.Disabled
5611
5612 --// Create slider element
5613 local Object = ReGui:InsertPrefab("Slider")
5614 local Track = Object.Track
5615 local Grab = Track.Grab
5616 local ValueText = Track.ValueText
5617
5618 --local Drag = ReGui:GetChildOfClass(Track, "UIDragDetector")
5619 local UIPadding = Track:FindFirstChildOfClass("UIPadding")
5620
5621 local Class = ReGui:MergeMetatables(Config, Object)
5622 local GrabSize = Grab.AbsoluteSize
5623
5624 --// Set object animations
5625 local HoverAnimation = ReGui:SetAnimation(Object, "Inputs")
5626
5627 local Label = Canvas:Label({
5628 Parent = Object,
5629 Text = LabelText,
5630 Position = UDim2.new(1, 4),
5631 Size = UDim2.fromScale(0, 1)
5632 })
5633
5634 Merge(Config, {
5635 Grab = Grab,
5636 Name = LabelText,
5637 })
5638
5639 --// Temporary solution
5640 if Type == "Slider" then
5641 Track.Position = UDim2.fromOffset(GrabSize.X/2, 0)
5642 Track.Size = UDim2.new(1, -GrabSize.X, 1, 0)
5643 end
5644
5645 local Types = {
5646 ["Slider"] = function(Percentage)
5647 return {
5648 AnchorPoint = Vector2.new(0.5, 0.5),
5649 Position = UDim2.fromScale(Percentage, 0.5)
5650 }
5651 end,
5652 ["Progress"] = function(Percentage)
5653 return {
5654 Size = UDim2.fromScale(Percentage, 1)
5655 }
5656 end,
5657 ["Snap"] = function(Percentage, Value, Minimum, Maximum)
5658 local X = (math.round(Value) - Minimum) / Maximum
5659 return {
5660 Size = UDim2.fromScale(1 / Maximum, 1),
5661 Position = UDim2.fromScale(X, 0.5)
5662 }
5663 end,
5664 }
5665
5666 local function Callback(...)
5667 local func = Config.Callback
5668 return func(Class, ...)
5669 end
5670
5671 function Config:SetDisabled(Disabled: boolean)
5672 self.Disabled = Disabled
5673 Object.Interactable = not Disabled
5674 Canvas:SetColorTags({
5675 [Label] = Disabled and "LabelDisabled" or "Label"
5676 }, true)
5677 return self
5678 end
5679
5680 function Config:SetValueText(Text: string)
5681 ValueText.Text = tostring(Text)
5682 end
5683
5684 function Config:SetValue(Value, IsPercentage: boolean)
5685 local Tweeninfo = Canvas:GetThemeKey("AnimationTweenInfo")
5686
5687 local Minimum = Config.Minimum
5688 local Maximum = Config.Maximum
5689
5690 local Percentage = Value
5691 local Difference = Maximum - Minimum
5692
5693 --// Convert Value into a Percentage
5694 if not IsPercentage then
5695 Percentage = (Value - Minimum) / Difference
5696 else
5697 --// Convert Percentage into Value
5698 Value = Minimum + (Difference * Percentage)
5699 end
5700
5701 --// Clamp the percentage to ensure the grab stays within bounds
5702 Percentage = math.clamp(Percentage, 0, 1)
5703
5704 --// Get properties for the Grab
5705 local Props = Types[Type](Percentage, Value, Minimum, Maximum)
5706
5707 --// Animate
5708 Animation:Tween({
5709 Object = Grab,
5710 Tweeninfo = Tweeninfo,
5711 NoAnimation = NoAnimation,
5712 EndProperties = Props
5713 })
5714
5715 --// Update object state
5716 self.Value = Value
5717 self:SetValueText(Format:format(Value, Maximum))
5718
5719 --// Fire callback
5720 Callback(Value)
5721
5722 return self
5723 end
5724
5725 local function SetFocused(Focused: boolean)
5726 --// Update object colors from a style
5727 Canvas:SetColorTags({
5728 [Object] = Focused and "FrameActive" or "Frame"
5729 }, true)
5730 Canvas:SetElementFocused(Object, {
5731 Focused = Focused,
5732 Animation = HoverAnimation
5733 })
5734 end
5735
5736 ------// Move events
5737 local function CanDrag()
5738 if Config.Disabled then return end
5739 if Config.ReadOnly then return end
5740
5741 return true
5742 end
5743 local function DragMovement(InputPosition)
5744 if not CanDrag() then return end
5745
5746 --// Track Position and Size
5747 local TrackLeft = Track.AbsolutePosition.X
5748 local TrackWidth = Track.AbsoluteSize.X
5749
5750 --// Get the mouse position relative to the track
5751 local MouseX = InputPosition.X
5752 local RelativeX = MouseX - TrackLeft
5753
5754 --// Get the percentage based on the width of the track
5755 local Percentage = math.clamp(RelativeX / TrackWidth, 0, 1)
5756
5757 Config:SetValue(Percentage, true)
5758 end
5759 local function DragBegan(...)
5760 if not CanDrag() then return end
5761
5762 SetFocused(true)
5763
5764 if not NoClick then
5765 DragMovement(...)
5766 end
5767 end
5768 local function DragEnded()
5769 SetFocused(false)
5770 end
5771
5772 --// Update object state
5773 Grab.Visible = not NoGrab
5774 Config:SetValue(Value) -- Ensure the grab is positioned correctly on initialization
5775 Config:SetDisabled(Disabled)
5776
5777 Canvas:TagElements({
5778 [ValueText] = "Label",
5779 [Grab] = "SliderGrab"
5780 })
5781
5782 --// Connect movement events
5783 ReGui:ConnectDrag(Track, {
5784 DragStart = DragBegan,
5785 DragMovement = DragMovement,
5786 DragEnd = DragEnded,
5787 })
5788
5789 return Class, Object
5790 end,
5791})
5792
5793export type SliderEnumFlags = {
5794 Items: {
5795 [number]: any
5796 },
5797 Label: string,
5798 Value: number,
5799} & SliderIntFlags
5800ReGui:DefineElement("SliderEnum", {
5801 Base = {
5802 Items = {},
5803 Label = "Slider Enum",
5804 Type = "Snap",
5805 Minimum = 1,
5806 Maximum = 10,
5807 Value = 1,
5808 Callback = EmptyFunction,
5809 ColorTag = "Frame"
5810 },
5811 Create = function(self, Config: SliderEnumFlags)
5812 --// Unpack configuration
5813 local Callback = Config.Callback
5814 local Value = Config.Value
5815
5816 local function Calculate(self, Value: number)
5817 Value = math.round(Value)
5818
5819 --// Dymanic size
5820 local Items = self.Items
5821 self.Maximum = #Items
5822
5823 --// Get value from array
5824 return Items[Value]
5825 end
5826
5827 --// Custom callback for the Enum type
5828 Config.Callback = function(self, Index, NoCallback: boolean)
5829 local Value = Calculate(self, Index)
5830 self:SetValueText(Value)
5831
5832 Config.Value = Value
5833
5834 return Callback(self, Value)
5835 end
5836
5837 Calculate(Config, Value)
5838
5839 --// Create object
5840 return self:SliderBase(Config)
5841 end,
5842})
5843
5844ReGui:DefineElement("SliderInt", {
5845 Base = {
5846 Label = "Slider Int",
5847 ColorTag = "Frame",
5848 },
5849 Create = Elements.SliderBase,
5850})
5851
5852ReGui:DefineElement("SliderFloat", {
5853 Base = {
5854 Label = "Slider Float",
5855 Format = "%.3f", --"%.3f/%s",
5856 ColorTag = "Frame",
5857 },
5858 Create = Elements.SliderBase,
5859})
5860
5861export type DragIntFlags = {
5862 Format: string?,
5863 Label: string?,
5864 Callback: (DragIntFlags, number) -> any,
5865 Minimum: number?,
5866 Maximum: number?,
5867 Value: number?,
5868 ReadOnly: boolean?,
5869
5870 SetValue: (DragIntFlags, number) -> DragIntFlags,
5871}
5872ReGui:DefineElement("DragInt", {
5873 Base = {
5874 Format = "%.f",
5875 Label = "Drag Int",
5876 Callback = EmptyFunction,
5877 Minimum = 0,
5878 Maximum = 100,
5879 ColorTag = "Frame",
5880 Disabled = false
5881 },
5882 Create = function(Canvas, Config: DragIntFlags)
5883 --// Unpack config
5884 local Value = Config.Value or Config.Minimum
5885 local Format = Config.Format
5886 local LabelText = Config.Label
5887 local Disabled = Config.Disabled
5888
5889 --// Create slider element
5890 local Object = ReGui:InsertPrefab("Slider")
5891 local Class = ReGui:MergeMetatables(Config, Object)
5892
5893 local Track = Object.Track
5894 local ValueText = Track.ValueText
5895 local Grab = Track.Grab
5896 Grab.Visible = false
5897
5898 local Drag = ReGui:GetChildOfClass(Track, "UIDragDetector")
5899
5900 local Label = Canvas:Label({
5901 Parent = Object,
5902 Text = LabelText,
5903 Position = UDim2.new(1, 7),
5904 Size = UDim2.fromScale(0, 1)
5905 })
5906
5907 local InputBeganPosition = nil
5908 local Percentage = 0
5909 local BeganPercentage = 0
5910
5911 --// Set object animations
5912 local HoverAnimation = ReGui:SetAnimation(Object, "Inputs")
5913
5914 local function Callback(...)
5915 local Func = Config.Callback
5916 return Func(Class, ...)
5917 end
5918
5919 function Config:SetValue(Value: number, IsPercentage: boolean)
5920 local Minimum = self.Minimum
5921 local Maximum = self.Maximum
5922
5923 local Difference = Maximum - Minimum
5924
5925 --// Convert Value into a Percentage
5926 if not IsPercentage then
5927 Percentage = ((Value - Minimum) / Difference) * 100
5928 else
5929 --// Convert Percentage into Value
5930 Value = Minimum + (Difference * (Percentage / 100))
5931 end
5932
5933 Value = math.clamp(Value, Minimum, Maximum)
5934
5935 --// Update object state
5936 self.Value = Value
5937 ValueText.Text = Format:format(Value, Maximum)
5938
5939 --// Fire callback
5940 Callback(Value)
5941
5942 return self
5943 end
5944 function Config:SetDisabled(Disabled: boolean)
5945 self.Disabled = Disabled
5946
5947 Canvas:SetColorTags({
5948 [Label] = Disabled and "LabelDisabled" or "Label"
5949 }, true)
5950 end
5951
5952 local function SetFocused(Focused: boolean)
5953 --// Update object colors from a style
5954 Canvas:SetColorTags({
5955 [Object] = Focused and "FrameActive" or "Frame"
5956 }, true)
5957
5958 Canvas:SetElementFocused(Object, {
5959 Focused = Focused,
5960 Animation = HoverAnimation
5961 })
5962 end
5963
5964 ------// Move events
5965 local function CanDrag(): boolean
5966 if Config.Disabled then return end
5967 if Config.ReadOnly then return end
5968
5969 return true
5970 end
5971 local function DragStart(InputPosition)
5972 if not CanDrag() then return end
5973 SetFocused(true)
5974
5975 InputBeganPosition = InputPosition
5976 BeganPercentage = Percentage
5977 end
5978 local function DragMovement(InputPosition)
5979 if not CanDrag() then return end
5980
5981 local Delta = InputPosition.X - InputBeganPosition.X
5982 local New = BeganPercentage + (Delta/2)
5983
5984 Percentage = math.clamp(New, 0, 100)
5985 Config:SetValue(Percentage, true)
5986 end
5987 local function DragEnded()
5988 SetFocused(false)
5989 end
5990
5991 --// Update object state
5992 Config:SetValue(Value)
5993 Config:SetDisabled(Disabled)
5994
5995 --// Connect movement events
5996 ReGui:ConnectDrag(Track, {
5997 DragStart = DragStart,
5998 DragEnd = DragEnded,
5999 DragMovement = DragMovement,
6000 })
6001
6002 Canvas:TagElements({
6003 [ValueText] = "Label"
6004 })
6005
6006 return Class, Object
6007 end,
6008})
6009
6010ReGui:DefineElement("DragFloat", {
6011 Base = {
6012 Format = "%.3f", --"%.3f/%s",
6013 Label = "Drag Float",
6014 ColorTag = "Frame"
6015 },
6016 Create = Elements.DragInt,
6017})
6018
6019ReGui:DefineElement("MultiElement", {
6020 Base = {
6021 Callback = EmptyFunction,
6022 Label = "",
6023 Disabled = false,
6024 BaseInputConfig = {},
6025 InputConfigs = {},
6026 Value = {},
6027 Minimum = {},
6028 Maximum = {},
6029 MultiCallback = EmptyFunction,
6030 },
6031 Create = function(Canvas, Config)
6032 --// Unpack configuration
6033 local LabelText = Config.Label
6034 local BaseInputConfig = Config.BaseInputConfig
6035 local InputConfigs = Config.InputConfigs
6036 local InputType = Config.InputType
6037 local Disabled = Config.Disabled
6038 local Value = Config.Value
6039 local Minimum = Config.Minimum
6040 local Maximum = Config.Maximum
6041
6042 assert(InputType, "No input type provided for MultiElement")
6043 --assert(#Minimum ~= #InputConfigs, `Minimum does not match input count ({Minimum} != {#InputConfigs})`)
6044 --assert(#Maximum ~= #InputConfigs, `Maximum does not match input count ({Maximum} != {#InputConfigs})`)
6045
6046 --// Create container row
6047 local ContainerRow, Object = Canvas:Row({
6048 Spacing = 4
6049 })
6050
6051 local Row = ContainerRow:Row({
6052 Size = UDim2.fromScale(0.65, 0),
6053 Expanded = true,
6054 })
6055
6056 local Label = ContainerRow:Label({
6057 Size = UDim2.fromScale(0.35, 0),
6058 LayoutOrder = 2,
6059 Text = LabelText
6060 })
6061
6062 local Class = ReGui:MergeMetatables(Config, ContainerRow)
6063 local Inputs = {}
6064 local _CallbackEnabled = false
6065
6066 local function GetValue()
6067 local Value = {}
6068 for Index, Input in Inputs do
6069 Value[Index] = Input:GetValue()
6070 end
6071
6072 Config.Value = Value
6073 return Value
6074 end
6075
6076 local function Callback(...)
6077 local Callback = Config.MultiCallback
6078 Callback(Class, ...)
6079 end
6080
6081 local function InputChanged()
6082 --// Check if all the elements have loaded
6083 if #Inputs ~= #InputConfigs then return end
6084 if not _CallbackEnabled then return end
6085
6086 local Values = GetValue()
6087 Callback(Values)
6088 end
6089
6090 function Config:SetDisabled(Disabled: boolean)
6091 self.Disabled = Disabled
6092
6093 --// Chaneg the tag of the Label
6094 Canvas:SetColorTags({
6095 [Label] = Disabled and "LabelDisabled" or "Label"
6096 }, true)
6097
6098 --// Set state of each Drag element
6099 for _, Input in Inputs do
6100 Input:SetDisabled(Disabled)
6101 end
6102 end
6103
6104 function Config:SetValue(Values)
6105 _CallbackEnabled = false
6106
6107 --// Invoke :SetValue on each input object
6108 for Index, Value in Values do
6109 local Input = Inputs[Index]
6110 assert(Input, `No input object for index: {Index}`)
6111
6112 Input:SetValue(Value)
6113 end
6114
6115 _CallbackEnabled = true
6116 Callback(Values)
6117 end
6118
6119 --// BaseInputConfig
6120 BaseInputConfig = Copy(BaseInputConfig, {
6121 Size = UDim2.new(1, 0, 0, 19),
6122 Label = "",
6123 Callback = InputChanged,
6124 })
6125
6126 --// Create DragInt elements
6127 for Index, Overwrites in InputConfigs do
6128 local Config = Copy(BaseInputConfig, Overwrites)
6129 ReGui:CheckConfig(Config, {
6130 Minimum = Minimum[Index],
6131 Maximum = Maximum[Index],
6132 })
6133
6134 --// Create input object
6135 local Input = Row[InputType](Row, Config)
6136 table.insert(Inputs, Input)
6137 end
6138
6139 --// Merge properties into the configuration
6140 Merge(Config, {
6141 Row = Row,
6142 Inputs = Inputs
6143 })
6144
6145 _CallbackEnabled = true
6146
6147 --// Update object states
6148 Config:SetDisabled(Disabled)
6149 Config:SetValue(Value)
6150
6151 return Class, Object
6152 end,
6153})
6154
6155local function GenerateMultiInput(Name: string, Class: string, InputCount: number, Extra)
6156 ReGui:DefineElement(Name, {
6157 Base = {
6158 Label = Name,
6159 Callback = EmptyFunction,
6160 InputType = Class,
6161 InputConfigs = table.create(InputCount, {}),
6162 BaseInputConfig = {},
6163 },
6164 Create = function(self, Config)
6165 local BaseInputConfig = Config.BaseInputConfig
6166 local Object = nil
6167
6168 if Extra then
6169 Merge(BaseInputConfig, Extra)
6170 end
6171
6172 ReGui:CheckConfig(BaseInputConfig, {
6173 ReadOnly = Config.ReadOnly,
6174 Format = Config.Format,
6175 })
6176
6177 Config.MultiCallback = function(...)
6178 local Callback = Config.Callback
6179 Callback(...)
6180 end
6181
6182 return self:MultiElement(Config)
6183 end,
6184 })
6185end
6186
6187export type InputColor3Flags = {
6188 Label: string?,
6189 Value: Color3?,
6190 Callback: (InputColor3Flags, Value: Color3) -> any,
6191
6192 ValueChanged: (InputColor3Flags) -> nil,
6193 SetValue: (InputColor3Flags, Value: Color3) -> InputColor3Flags,
6194}
6195local function GenerateColor3Input(Name: string, InputType: string, InputCount: number, Extra)
6196 Extra = Extra or {}
6197 ReGui:DefineElement(Name, {
6198 Base = {
6199 Label = Name,
6200 Callback = EmptyFunction,
6201 Value = ReGui.Accent.Light,
6202 Disabled = false,
6203 Minimum = {0,0,0},
6204 Maximum = {255,255,255,100},
6205 BaseInputConfig = {},
6206 InputConfigs = {
6207 [1] = {Format = "R: %.f"},
6208 [2] = {Format = "G: %.f"},
6209 [3] = {Format = "B: %.f"},
6210 }
6211 },
6212 Create = function(self, Config: InputColor3Flags)
6213 --// Unpack configuration
6214 local BaseInputConfig = Config.BaseInputConfig
6215 local InputConfigs = Config.InputConfigs
6216 local Value = Config.Value
6217 local Disabled = Config.Disabled
6218
6219 --// Add alpha slider
6220 if Extra.Color4 then
6221 InputConfigs[4] = {Format = "A: %.f"}
6222 end
6223
6224 --// Create Object
6225 local InputConfig = Copy(Config, {
6226 Value = {1,1,1},
6227 Callback = function(self, ...)
6228 if Config.ValueChanged then
6229 Config:ValueChanged(...)
6230 end
6231 end,
6232 })
6233
6234 local Element, Object = self[InputType](self, InputConfig)
6235 local Class = ReGui:MergeMetatables(Config, Element)
6236 local Row = Element.Row
6237
6238 --// Preview frame
6239 local Preview = Row:Button({
6240 BackgroundTransparency = 0,
6241 Size = UDim2.fromOffset(19, 19),
6242 UiPadding = 0,
6243 Text = "",
6244 Ratio = 1,
6245 ColorTag = "",
6246 ElementStyle = ""
6247 })
6248
6249 local function Callback(...)
6250 local func = Config.Callback
6251 return func(Class, ...)
6252 end
6253
6254 local function SetPreview(Color: Color3)
6255 Preview.BackgroundColor3 = Color
6256 Callback(Color)
6257 end
6258
6259 function Config:ValueChanged(Value)
6260 local R, G, B = Value[1], Value[2], Value[3]
6261 local Color = Color3.fromRGB(R, G, B)
6262
6263 self.Value = Color
6264 SetPreview(Color)
6265 end
6266
6267 function Config:SetValue(Color: Color3)
6268 self.Value = Color
6269 SetPreview(Color)
6270
6271 --// Update Drag elements
6272 Element:SetValue({
6273 math.round(Color.R*255),
6274 math.round(Color.G*255),
6275 math.round(Color.B*255)
6276 })
6277 end
6278
6279 --// Update object state
6280 Config:SetValue(Value)
6281
6282 return Class, Object
6283 end,
6284 })
6285end
6286
6287export type InputCFrameFlags = {
6288 Label: string?,
6289 Value: CFrame?,
6290 Callback: (InputCFrameFlags, Value: CFrame) -> any,
6291
6292 ValueChanged: (InputCFrameFlags) -> nil,
6293 SetValue: (InputCFrameFlags, Value: CFrame) -> InputCFrameFlags,
6294}
6295local function GenerateCFrameInput(Name: string, InputType: string, InputCount: number, Extra)
6296 ReGui:DefineElement(Name, {
6297 Base = {
6298 Label = Name,
6299 Callback = EmptyFunction,
6300 Disabled = false,
6301 Value = CFrame.new(10,10,10),
6302 Minimum = CFrame.new(0,0,0),
6303 Maximum = CFrame.new(100,100,100),
6304 BaseInputConfig = {},
6305 InputConfigs = {
6306 [1] = {Format = "X: %.f"},
6307 [2] = {Format = "Y: %.f"},
6308 [3] = {Format = "Z: %.f"}
6309 }
6310 },
6311 Create = function(self, Config: InputCFrameFlags)
6312 --// Unpack configuration
6313 local BaseInputConfig = Config.BaseInputConfig
6314 local Value = Config.Value
6315 local Disabled = Config.Disabled
6316 local Maximum = Config.Maximum
6317 local Minimum = Config.Minimum
6318
6319 local InputConfig = Copy(Config, {
6320 Maximum = {Maximum.X, Maximum.Y, Maximum.Z},
6321 Minimum = {Minimum.X, Minimum.Y, Minimum.Z},
6322 Value = {Value.X, Value.Y, Value.Z},
6323 Callback = function(self, ...)
6324 if Config.ValueChanged then
6325 Config:ValueChanged(...)
6326 end
6327 end,
6328 })
6329
6330 --// Create Object
6331 local Element, Object = self[InputType](self, InputConfig)
6332 local Class = ReGui:MergeMetatables(Config, Element)
6333 local Row = Element.Row
6334
6335 local function Callback(...)
6336 local func = Config.Callback
6337 return func(Class, ...)
6338 end
6339
6340 function Config:ValueChanged(Values)
6341 local X, Y, Z = Values[1], Values[2], Values[3]
6342 local Value = CFrame.new(X, Y, Z)
6343 self.Value = Value
6344 Callback(Value)
6345 end
6346
6347 function Config:SetValue(Value: CFrame)
6348 self.Value = Value
6349
6350 --// Update Drag elements
6351 Element:SetValue({
6352 math.round(Value.X),
6353 math.round(Value.Y),
6354 math.round(Value.Z)
6355 })
6356 end
6357
6358 --// Update object state
6359 Config:SetValue(Value)
6360
6361 return Class, Object
6362 end,
6363 })
6364end
6365
6366GenerateMultiInput("InputInt2", "InputInt", 2, {NoButtons=true})
6367GenerateMultiInput("InputInt3", "InputInt", 3, {NoButtons=true})
6368GenerateMultiInput("InputInt4", "InputInt", 4, {NoButtons=true})
6369GenerateMultiInput("SliderInt2", "SliderInt", 2)
6370GenerateMultiInput("SliderInt3", "SliderInt", 3)
6371GenerateMultiInput("SliderInt4", "SliderInt", 4)
6372GenerateMultiInput("SliderFloat2", "SliderFloat", 2)
6373GenerateMultiInput("SliderFloat3", "SliderFloat", 3)
6374GenerateMultiInput("SliderFloat4", "SliderFloat", 4)
6375GenerateMultiInput("DragInt2", "DragInt", 2)
6376GenerateMultiInput("DragInt3", "DragInt", 3)
6377GenerateMultiInput("DragInt4", "DragInt", 4)
6378GenerateMultiInput("DragFloat2", "DragFloat", 2)
6379GenerateMultiInput("DragFloat3", "DragFloat", 3)
6380GenerateMultiInput("DragFloat4", "DragFloat", 4)
6381
6382GenerateColor3Input("InputColor3", "InputInt3")
6383GenerateColor3Input("SliderColor3", "SliderInt3")
6384GenerateColor3Input("DragColor3", "DragInt3")
6385
6386GenerateCFrameInput("InputCFrame", "InputInt3")
6387GenerateCFrameInput("SliderCFrame", "SliderInt3")
6388GenerateCFrameInput("DragCFrame", "DragInt3")
6389
6390ReGui:DefineElement("SliderProgress", {
6391 Base = {
6392 Label = "Slider Progress",
6393 Type = "Progress",
6394 ColorTag = "Frame",
6395 },
6396 Create = Elements.SliderBase,
6397})
6398
6399export type ProgressBar = {
6400 SetPercentage: (ProgressBar, Value: number) -> nil
6401}
6402ReGui:DefineElement("ProgressBar", {
6403 Base = {
6404 Label = "Progress Bar",
6405 Type = "Progress",
6406 ReadOnly = true,
6407 MinValue = 0,
6408 MaxValue = 100,
6409 Format = "% i%%",
6410 Interactable = false,
6411 ColorTag = "Frame"
6412 },
6413 Create = function(self, Config)
6414 function Config:SetPercentage(Value: number)
6415 Config:SetValue(Value)
6416 end
6417
6418 local Slider, Object = self:SliderBase(Config)
6419 local Grab = Slider.Grab
6420
6421 self:TagElements({
6422 [Grab] = {
6423 BackgroundColor3 = "ProgressBar"
6424 }
6425 })
6426
6427 return Slider, Object
6428 end,
6429})
6430
6431export type Combo = {
6432 Label: string?,
6433 Placeholder: string?,
6434 Callback: ((Combo, Value: any) -> any)?,
6435 Items: {[number?]: any}?,
6436 GetItems: (() -> table)?,
6437}
6438ReGui:DefineElement("Combo", {
6439 Base = {
6440 Value = "",
6441 Placeholder = "",
6442 Callback = EmptyFunction,
6443 Items = {},
6444 Disabled = false,
6445 WidthFitPreview = false,
6446 Label = "Combo"
6447 },
6448 Create = function(Canvas, Config: Combo)
6449 --// Unpack configuration
6450 local Placeholder = Config.Placeholder
6451 local NoAnimation = Config.NoAnimation
6452 local Selected = Config.Selected
6453 local LabelText = Config.Label
6454 local Disabled = Config.Disabled
6455 local WidthFitPreview = Config.WidthFitPreview
6456 --local NoPreview = Config.NoPreview
6457
6458 --// Create combo element
6459 local Object = ReGui:InsertPrefab("Combo", Config)
6460 local Class = ReGui:MergeMetatables(Config, Object)
6461
6462 local Combo = Object.Combo
6463 local Dropdown = nil
6464
6465 --// Elements
6466 local ValueText = Canvas:Label({
6467 Text = tostring(Placeholder),
6468 Parent = Combo,
6469 --Visible = not NoPreview,
6470 Name = "ValueText"
6471 })
6472 local ArrowButton = Canvas:ArrowButton({
6473 Parent = Combo,
6474 Interactable = false,
6475 Size = UDim2.fromOffset(19, 19),
6476 LayoutOrder = 2,
6477 })
6478 local Label = Canvas:Label({
6479 Text = LabelText,
6480 Parent = Object,
6481 LayoutOrder = 2,
6482 })
6483
6484 --// Enable automatic sizes
6485 if WidthFitPreview then
6486 ReGui:SetProperties(Object, {
6487 AutomaticSize = Enum.AutomaticSize.XY,
6488 Size = UDim2.new(0, 0, 0, 0)
6489 })
6490 ReGui:SetProperties(Combo, {
6491 AutomaticSize = Enum.AutomaticSize.XY,
6492 Size = UDim2.fromScale(0, 1)
6493 })
6494 end
6495
6496 local function Callback(Value, ...)
6497 Config:SetOpen(false)
6498 return Config.Callback(Class, Value, ...)
6499 end
6500
6501 local function SetAnimationState(Open: boolean, NoAnimation: boolean?)
6502 local Tweeninfo = Canvas:GetThemeKey("AnimationTweenInfo")
6503
6504 Object.Interactable = not Open
6505
6506 --// Animate Arrow button
6507 Animation:HeaderCollapseToggle({
6508 Tweeninfo = Tweeninfo,
6509 NoAnimation = NoAnimation,
6510 Collapsed = not Open,
6511 Toggle = ArrowButton.Icon,
6512 })
6513 end
6514
6515 local function GetItems()
6516 local GetItems = Config.GetItems
6517 local Items = Config.Items
6518
6519 --// Invoke the GetItems function
6520 if GetItems then
6521 return GetItems()
6522 end
6523
6524 --// Return Dict/Array
6525 return Items
6526 end
6527
6528 function Config:SetValueText(Value: string?)
6529 ValueText.Text = tostring(Value)
6530 end
6531
6532 function Config:ClosePopup()
6533 if Dropdown then
6534 Dropdown:ClosePopup(true)
6535 end
6536 end
6537
6538 function Config:SetDisabled(Disabled: boolean)
6539 self.Disabled = Disabled
6540 Object.Interactable = not Disabled
6541 Canvas:SetColorTags({
6542 [Label] = Disabled and "LabelDisabled" or "Label"
6543 }, true)
6544 end
6545
6546 function Config:SetValue(Selected)
6547 local Items = GetItems()
6548 local DictValue = Items[Selected]
6549 local Value = DictValue or Selected
6550
6551 self._Selected = Selected
6552 self.Value = Value
6553
6554 self:ClosePopup()
6555
6556 --// Update Value text with selected item
6557 if typeof(Selected) == "number" then
6558 self:SetValueText(Value)
6559 else
6560 self:SetValueText(Selected)
6561 end
6562
6563 return Callback(Selected, Value)
6564 end
6565
6566 function Config:SetOpen(Open: boolean)
6567 local Selected = self._Selected
6568
6569 self.Open = Open
6570 SetAnimationState(Open, NoAnimation)
6571
6572 if not Open then
6573 --// Close open dropdown
6574 self:ClosePopup()
6575 return
6576 end
6577
6578 --// Create dropdown
6579 Dropdown = Canvas:Dropdown({
6580 RelativeTo = Combo,
6581 Items = GetItems(),
6582 Selected = Selected,
6583 OnSelected = function(...)
6584 Config:SetValue(...)
6585 end,
6586 OnClosed = function()
6587 self:SetOpen(false)
6588 end,
6589 })
6590
6591 return self
6592 end
6593
6594 local function ToggleOpen()
6595 local IsOpen = Config.Open
6596 Config:SetOpen(not IsOpen)
6597 end
6598
6599 --// Connect events
6600 Combo.Activated:Connect(ToggleOpen)
6601
6602 --// Update object state
6603 SetAnimationState(false, true)
6604 Config:SetDisabled(Disabled)
6605
6606 if Selected then
6607 Config:SetValue(Selected)
6608 end
6609
6610 --// Set object animations
6611 ReGui:SetAnimation(Combo, "Inputs")
6612
6613 Canvas:TagElements({
6614 [Combo] = "Frame",
6615 })
6616
6617 return Class, Object
6618 end,
6619})
6620
6621--ReGui:DefineElement("ComboFilter", {
6622-- Base = {
6623-- Value = "",
6624-- Placeholder = "",
6625-- Callback = EmptyFunction,
6626-- Items = {},
6627-- Disabled = false,
6628-- Label = "Combo Filter"
6629-- },
6630-- Create = function(Canvas, Config: Combo)
6631-- --// Unpack configuration
6632-- local Placeholder = Config.Placeholder
6633-- local NoAnimation = Config.NoAnimation
6634-- local Selected = Config.Selected
6635-- local LabelText = Config.Label
6636-- local Disabled = Config.Disabled
6637
6638-- local InputConfig = Copy(Config, {
6639-- Callback = function(self, ...)
6640-- print("InputText", ...)
6641
6642-- if Config.ResolveQuery then
6643-- print("ResolveQuery", ...)
6644-- Config:ResolveQuery(...)
6645-- end
6646-- end,
6647-- })
6648
6649-- --// Create inputText element
6650-- local Object = Canvas:InputText(InputConfig)
6651-- local Class = ReGui:MergeMetatables(Config, Object)
6652-- local Dropdown = nil
6653
6654-- local function Callback(Value, ...)
6655-- local Func = Config.Callback
6656-- Config:SetOpen(false)
6657
6658-- return Func(Class, Value, ...)
6659-- end
6660
6661-- local function GetItems()
6662-- local GetItems = Config.GetItems
6663-- local Items = Config.Items
6664
6665-- --// Invoke the GetItems function
6666-- if GetItems then
6667-- return GetItems()
6668-- end
6669
6670-- --// Return Dict/Array
6671-- return Items
6672-- end
6673
6674-- function Config:SetDropdownVisible(Visible: boolean)
6675-- if self.Open == Visible then return end
6676-- self.Open = Visible
6677
6678-- --// Close open dropdown
6679-- if not Visible then
6680-- if Dropdown then
6681-- Dropdown:Close()
6682-- end
6683-- return
6684-- end
6685
6686-- --// Create dropdown
6687-- Dropdown = Canvas:Dropdown({
6688-- ParentObject = Object,
6689-- Selected = Selected,
6690-- OnSelected = function(...)
6691-- Config:SetValue(...)
6692-- end,
6693-- OnClosed = function()
6694-- self:SetOpen(false)
6695-- end,
6696-- })
6697-- end
6698
6699-- function Config:ResolveQuery(Query: string)
6700-- local Items = GetItems()
6701-- local Sorted = SortByQuery(Items, Query)
6702
6703-- --// Create dropdown
6704-- self:SetDropdownVisible(true)
6705
6706-- --// Set dropdown items
6707-- Dropdown:SetItems(Sorted, 1)
6708-- end
6709
6710-- function Config:SetValue(Selected)
6711-- --local Items = GetItems()
6712
6713-- --local DictValue = Items[Selected]
6714-- --local Value = DictValue or Selected
6715
6716-- --self._Selected = Selected
6717-- --self.Value = Value
6718
6719-- ----// Update Value text with selected item
6720-- --if typeof(Selected) == "number" then
6721-- -- self:SetValueText(Value)
6722-- --else
6723-- -- self:SetValueText(Selected)
6724-- --end
6725
6726-- --return Callback(Selected, Value)
6727-- end
6728
6729-- return Class, Object
6730-- end,
6731--})
6732
6733local WindowClass = {
6734 --// Icons
6735 TileBarConfig = {
6736 Close = {
6737 Image = ReGui.Icons.Close,
6738 IconPadding = UDim.new(0, 3)
6739 },
6740 Collapse = {
6741 Image = ReGui.Icons.Arrow,
6742 IconPadding = UDim.new(0, 3)
6743 },
6744 },
6745
6746 CloseCallback = EmptyFunction, --// Placeholder
6747
6748 --// States
6749 Collapsible = true,
6750 Open = true,
6751 Focused = false
6752}
6753
6754function WindowClass:Tween(Data)
6755 ReGui:CheckConfig(Data, {
6756 Tweeninfo = self:GetThemeKey("AnimationTweenInfo")
6757 })
6758 return Animation:Tween(Data)
6759end
6760
6761function WindowClass:TagElements(Objects: ObjectTable)
6762 local Debug = ReGui.Debug
6763
6764 --// Unpack WindowClass
6765 local Elements = self.TagsList
6766 local Theme = self.Theme
6767
6768 ReGui:MultiUpdateColors({
6769 Theme = Theme,
6770 TagsList = Elements,
6771 Objects = Objects
6772 })
6773end
6774
6775export type TitleBarCanvas = {
6776 Right: table,
6777 Left: table,
6778}
6779function WindowClass:MakeTitleBarCanvas(): TitleBarCanvas
6780 local TitleBar = self.TitleBar
6781
6782 --// Create canvas for each side
6783 local Canvas = ReGui:MakeCanvas({
6784 WindowClass = self,
6785 Element = TitleBar
6786 })
6787 self.TitleBarCanvas = Canvas
6788
6789 return Canvas
6790end
6791
6792function WindowClass:AddDefaultTitleButtons()
6793 local Config = self.TileBarConfig
6794 local TitleBar = self.TitleBar
6795
6796 local Toggle = Config.Collapse
6797 local Close = Config.Close
6798
6799 --// Check for Titlebar canvas
6800 local Canvas = self.TitleBarCanvas
6801 if not Canvas then
6802 Canvas = self:MakeTitleBarCanvas()
6803 end
6804
6805 ReGui:CheckConfig(self, {
6806 --// Create window interaction buttons
6807 Toggle = Canvas:RadioButton({
6808 Icon = Toggle.Image,
6809 IconPadding = Toggle.IconPadding,
6810 LayoutOrder = 1,
6811 Ratio = 1,
6812 Size = UDim2.new(0, 0),
6813 Callback = function()
6814 self:ToggleCollapsed()
6815 end,
6816 }),
6817 CloseButton = Canvas:RadioButton({
6818 Icon = Close.Image,
6819 IconPadding = Close.IconPadding,
6820 LayoutOrder = 3,
6821 Ratio = 1,
6822 Size = UDim2.new(0, 0),
6823 Callback = function()
6824 self:SetVisible(false)
6825 end,
6826 }),
6827 TitleLabel = Canvas:Label({
6828 ColorTag = "Title",
6829 LayoutOrder = 2,
6830 Size = UDim2.new(1, 0),
6831 Active = false,
6832 Fill = true,
6833 ClipsDescendants = true,
6834 AutomaticSize = Enum.AutomaticSize.XY
6835 })
6836 })
6837
6838 --// Registor Elements into Window class
6839 self:TagElements({
6840 [self.TitleLabel] = "WindowTitle"
6841 })
6842end
6843
6844function WindowClass:Close()
6845 local Callback = self.CloseCallback
6846
6847 --// Test for interupt
6848 if Callback then
6849 local ShouldClose = Callback(self)
6850 if ShouldClose == false then return end
6851 end
6852
6853 self:Remove()
6854end
6855
6856function WindowClass:SetVisible(Visible: boolean): WindowClass
6857 local Window = self.WindowFrame
6858 local NoFocusOnAppearing = self.NoFocusOnAppearing
6859
6860 self.Visible = Visible
6861 Window.Visible = Visible
6862
6863 --// Update window focus
6864 if Visible and not NoFocusOnAppearing then
6865 ReGui:SetFocusedWindow(self)
6866 end
6867
6868 return self
6869end
6870
6871function WindowClass:ToggleVisibility(Visible: boolean): WindowClass
6872 local IsVisible = self.Visible
6873 self:SetVisible(not IsVisible)
6874end
6875
6876function WindowClass:GetWindowSize(): Vector2
6877 return self.WindowFrame.AbsoluteSize
6878end
6879
6880function WindowClass:GetTitleBarSizeY(): number
6881 local TitleBar = self.TitleBar
6882 return TitleBar.Visible and TitleBar.AbsoluteSize.Y or 0
6883end
6884
6885function WindowClass:SetTitle(Text: string?): WindowClass
6886 self.TitleLabel.Text = tostring(Text)
6887 return self
6888end
6889
6890function WindowClass:SetPosition(Position): WindowClass
6891 self.WindowFrame.Position = Position
6892 return self
6893end
6894
6895function WindowClass:SetSize(Size: (Vector2|UDim2), NoAnimation: boolean): WindowClass
6896 local Window = self.WindowFrame
6897
6898 --// Convert Vector2 to UDim2
6899 if typeof(Size) == "Vector2" then
6900 Size = UDim2.fromOffset(Size.X, Size.Y)
6901 end
6902
6903 Window.Size = Size
6904 self.Size = Size
6905
6906 return self
6907end
6908
6909function WindowClass:SetCanvasInteractable(Interactable: boolean)
6910 local Body = self.Body
6911 Body.Interactable = Interactable
6912end
6913
6914function WindowClass:Center(): WindowClass --// Without an Anchor point
6915 local Size = self:GetWindowSize() / 2
6916 local Position = UDim2.new(0.5, -Size.X, 0.5, -Size.Y)
6917
6918 self:SetPosition(Position)
6919 return self
6920end
6921
6922function WindowClass:LoadStylesIntoElement(Data)
6923 local Flags = Data.Flags
6924 local Object = Data.Object
6925 local Canvas = Data.Canvas
6926
6927 local TagFunctions = {
6928 ["FrameRounding"] = function()
6929 if Flags.CornerRadius then return end
6930 if not Canvas then return end
6931
6932 local UICorner = Object:FindFirstChild("FrameRounding", true)
6933 if not UICorner then return end
6934
6935 Canvas:TagElements({
6936 [UICorner] = "FrameRounding"
6937 })
6938 end,
6939 }
6940
6941 for Tag, Func in TagFunctions do
6942 local Value = self:GetThemeKey(Tag)
6943 if Value == nil then continue end
6944
6945 task.spawn(Func, Value)
6946 end
6947end
6948
6949function WindowClass:SetTheme(ThemeName: string): WindowClass
6950 local Themes = ReGui.ThemeConfigs
6951
6952 local Elements = self.TagsList
6953 local Focused = self.Focused
6954 local WindowState = self.WindowState
6955
6956 --// Use the current theme if no theme is defined
6957 if not ThemeName then
6958 ThemeName = self.Theme
6959 end
6960
6961 --// Check if the theme actually exists
6962 assert(Themes[ThemeName], `{ThemeName} is not a valid theme!`)
6963
6964 self.Theme = ThemeName
6965
6966 --// Update elements with new colors
6967 ReGui:MultiUpdateColors({
6968 Animate = false,
6969 Theme = ThemeName,
6970 Objects = Elements
6971 })
6972
6973 --// Refresh Focus styles
6974 self:SetFocusedColors(WindowState)
6975
6976 return self
6977end
6978
6979function WindowClass:SetFocusedColors(State: string)
6980 --// Unpack class values
6981 local WindowFrame = self.WindowFrame
6982 local TitleBar = self.TitleBar
6983 local Theme = self.Theme
6984 local TitleLabel = self.TitleLabel
6985 local Tweeninfo = self:GetThemeKey("AnimationTweenInfo")
6986
6987 local Border = WindowFrame:FindFirstChildOfClass("UIStroke")
6988
6989 --// Color tags
6990 local Tags = {
6991 Focused = {
6992 [Border] = "BorderActive",
6993 [TitleBar] = "TitleBarBgActive",
6994 [TitleLabel] = {
6995 TextColor3 = "TitleActive"
6996 }
6997 },
6998 UnFocused = {
6999 [Border] = "Border",
7000 [TitleBar] = "TitleBarBg",
7001 [TitleLabel] = {
7002 TextColor3 = "Title"
7003 }
7004 },
7005 Collapsed = {
7006 [Border] = "Border",
7007 [TitleBar] = "TitleBarBgCollapsed",
7008 [TitleLabel] = {
7009 TextColor3 = "Title"
7010 }
7011 }
7012 }
7013
7014 --// Update colors
7015 ReGui:MultiUpdateColors({
7016 Tweeninfo = Tweeninfo,
7017 Animate = true,
7018 Objects = Tags[State],
7019 Theme = Theme,
7020 })
7021end
7022
7023function WindowClass:SetFocused(Focused: true)
7024 Focused = Focused == nil and true or Focused
7025
7026 --// Unpack class values
7027 local Collapsed = self.Collapsed
7028 local CurrentState = self.WindowState
7029
7030 --// Update Window focus
7031 if Focused then
7032 ReGui:SetFocusedWindow(self)
7033 end
7034
7035 --// Theme tags for Window state
7036 local NewState = Collapsed and "Collapsed" or Focused and "Focused" or "UnFocused"
7037
7038 --// Check if the window state is identical
7039 if NewState == CurrentState then return end
7040 self.Focused = Focused
7041 self.WindowState = NewState
7042
7043 --// Update colors
7044 self:SetFocusedColors(NewState)
7045end
7046
7047function WindowClass:GetThemeKey(Key: string)
7048 return ReGui:GetThemeKey(self.Theme, Key)
7049end
7050
7051function WindowClass:ResetColors(): WindowClass
7052 local Defaults = ReGui.Theme
7053 local Theme = self.Theme
7054 local Elements = self.TagsList
7055
7056 --// Reset values
7057 table.clear(Theme)
7058
7059 ReGui:MultiUpdateColors({
7060 Animate = false,
7061 Theme = Defaults,
7062 Objects = Elements
7063 })
7064
7065 return WindowClass
7066end
7067
7068function WindowClass:SetCollapsible(Collapsible: boolean): WindowClass
7069 self.Collapsible = Collapsible
7070 return self
7071end
7072
7073function WindowClass:ToggleCollapsed(NoCheck: boolean?): WindowClass
7074 local Collapsed = self.Collapsed
7075 local Collapsible = self.Collapsible
7076
7077 --// Check if the window can be opened
7078 if not NoCheck and not Collapsible then return self end
7079
7080 self:SetCollapsed(not Collapsed)
7081 return self
7082end
7083
7084function WindowClass:SetCollapsed(Collapsed: boolean, NoAnimation: false): WindowClass
7085 local Window = self.WindowFrame
7086 local Body = self.Body
7087 local Toggle = self.Toggle
7088 local ResizeGrab = self.ResizeGrab
7089 local OpenSize = self.Size
7090 local AutoSize = self.AutoSize
7091 local Tweeninfo = self:GetThemeKey("AnimationTweenInfo")
7092
7093 local WindowSize = self:GetWindowSize()
7094 local TitleBarSizeY = self:GetTitleBarSizeY()
7095
7096 local ToggleIcon = Toggle.Icon
7097 local ClosedSize = UDim2.fromOffset(WindowSize.X, TitleBarSizeY)
7098
7099 self.Collapsed = Collapsed
7100 self:SetCollapsible(false)
7101
7102 --// Change the window focus
7103 self:SetFocused(not Collapsed)
7104
7105 --// Animate the closing
7106 Animation:HeaderCollapse({
7107 Tweeninfo = Tweeninfo,
7108 NoAnimation = NoAnimation,
7109 Collapsed = Collapsed,
7110 Toggle = ToggleIcon,
7111 Resize = Window,
7112 NoAutomaticSize = not AutoSize,
7113 Hide = Body,
7114 --// Sizes
7115 ClosedSize = ClosedSize,
7116 OpenSize = OpenSize,
7117 Completed = function()
7118 self:SetCollapsible(true)
7119 end
7120 })
7121
7122 --// ResizeGrab
7123 self:Tween({
7124 Object = ResizeGrab,
7125 NoAnimation = NoAnimation,
7126 EndProperties = {
7127 TextTransparency = Collapsed and 1 or 0.6,
7128 Interactable = not Collapsed
7129 }
7130 })
7131
7132 return self
7133end
7134
7135function WindowClass:UpdateConfig(Config)
7136 local Flags = {
7137 NoTitleBar = function(Value)
7138 local Object = self.TitleBar
7139 Object.Visible = not Value
7140 end,
7141 NoClose = function(Value)
7142 local Object = self.CloseButton
7143 Object.Visible = not Value
7144 end,
7145 NoCollapse = function(Value)
7146 local Object = self.Toggle
7147 Object.Visible = not Value
7148 end,
7149 NoTabsBar = function(Value)
7150 local Object = self.WindowTabSelector
7151 if not Object then return end
7152
7153 local TabsBar = Object.TabsBar
7154 TabsBar.Visible = not Value
7155 end,
7156 NoScrollBar = function(Value)
7157 local ScrollBarThickness = Value and 0 or 9
7158 local NoScroll = self.NoScroll
7159 local TabSelector = self.WindowTabSelector
7160 local ContentCanvas = self.ContentCanvas
7161
7162 --// TabSelector
7163 if TabSelector then
7164 TabSelector.Body.ScrollBarThickness = ScrollBarThickness
7165 end
7166 --// Check if the window is a scrolling type
7167 if not NoScroll then
7168 ContentCanvas.ScrollBarThickness = ScrollBarThickness
7169 end
7170 end,
7171 NoScrolling = function(Value)
7172 local NoScroll = self.NoScroll
7173 local TabSelector = self.WindowTabSelector
7174 local ContentCanvas = self.ContentCanvas
7175
7176 if TabSelector then
7177 TabSelector.Body.ScrollingEnabled = not Value
7178 end
7179 if not NoScroll then
7180 ContentCanvas.ScrollingEnabled = not Value
7181 end
7182 end,
7183 NoMove = function(Value)
7184 local Drag = self.DragConnection
7185 Drag:SetEnabled(not Value)
7186 end,
7187 NoResize = function(Value)
7188 local Drag = self.ResizeConnection
7189 Drag:SetEnabled(not Value)
7190 end,
7191 NoBackground = function(Value)
7192 local Transparency = self:GetThemeKey("WindowBgTransparency")
7193 local Frame = self.CanvasFrame
7194 Frame.BackgroundTransparency = Value and 1 or Transparency
7195 end,
7196 }
7197
7198 --// Update class data
7199 Merge(self, Config)
7200
7201 --// Invoke functions connected to flags
7202 for Key, Value in Config do
7203 local Func = Flags[Key]
7204 if Func then
7205 Func(Value)
7206 end
7207 end
7208
7209 return self
7210end
7211
7212--// Window removal function
7213function WindowClass:Remove()
7214 local Window = self.WindowFrame
7215 local WindowClass = self.WindowClass
7216 local Windows = ReGui.Windows
7217
7218 --// Remove Window from the Windows array
7219 local Index = table.find(Windows, WindowClass)
7220 if Index then
7221 table.remove(Windows, Index)
7222 end
7223
7224 --// Destroy the Window frame
7225 Window:Destroy()
7226end
7227
7228function WindowClass:MenuBar(Config, ...)
7229 local ContentCanvas = self.ContentCanvas
7230 local ContentFrame = self.ContentFrame
7231
7232 Config = Config or {}
7233
7234 Merge(Config, {
7235 Parent = ContentFrame,
7236 Layout = -1
7237 })
7238
7239 return ContentCanvas:MenuBar(Config, ...)
7240end
7241
7242export type WindowFlags = {
7243 AutoSize: string?,
7244 CloseCallback: (Window) -> boolean?,
7245 Collapsed: boolean?,
7246 IsDragging: boolean?,
7247 MinSize: Vector2?,
7248 Theme: any?,
7249 Title: string?,
7250 NoTabs: boolean?,
7251 NoMove: boolean?,
7252 NoResize: boolean?,
7253 NoTitleBar: boolean?,
7254 NoClose: boolean?,
7255 NoCollapse: boolean?,
7256 NoScrollBar: boolean?,
7257 NoSelectEffect: boolean?,
7258 NoFocusOnAppearing: boolean?,
7259 NoDefaultTitleBarButtons: boolean?,
7260 NoWindowRegistor: boolean?,
7261 OpenOnDoubleClick: boolean?,
7262 SetTheme: (Window, ThemeName: string) -> Window,
7263 SetTitle: (Window, Title: string) -> Window,
7264 UpdateConfig: (Window, Config: table) -> Window,
7265 SetCollapsed: (Window, Collapsed: boolean, NoAnimation: boolean?) -> Window,
7266 SetCollapsible: (Window, Collapsible: boolean) -> Window,
7267 SetFocused: (Window, Focused: boolean) -> Window,
7268 Center: (Window) -> Window,
7269 SetVisible: (Window, Visible: boolean) -> Window,
7270 TagElements: (Window, Objects: {
7271 [GuiObject]: string
7272 }) -> nil,
7273 Close: (Window) -> nil,
7274}
7275ReGui:DefineElement("Window", {
7276 Export = true,
7277 Base = {
7278 Theme = "DarkTheme",
7279 NoSelect = false,
7280 NoTabs = true,
7281 NoScroll = false,
7282 Collapsed = false,
7283 Visible = true,
7284 AutoSize = false,
7285 MinimumSize = Vector2.new(160, 90),
7286 OpenOnDoubleClick = true,
7287 NoAutoTheme = true,
7288 NoWindowRegistor = false,
7289 NoBringToFrontOnFocus = false,
7290 IsDragging = false,
7291 },
7292 Create = function(self, Config: WindowFlags)
7293 --// Global config unpack
7294 local Windows = ReGui.Windows
7295 local WindowsContainer = ReGui.Container.Windows
7296
7297 ReGui:CheckConfig(Config, {
7298 Parent = WindowsContainer,
7299 Title = ReGui.DefaultTitle
7300 })
7301
7302 --// Unpack config
7303 local NoTitleButtons = Config.NoDefaultTitleBarButtons
7304 local Collapsed = Config.Collapsed
7305 local MinimumSize = Config.MinimumSize
7306 local Title = Config.Title
7307 local NoTabs = Config.NoTabs
7308 local NoScroll = Config.NoScroll
7309 local Theme = Config.Theme
7310 local AutomaticSize = Config.AutomaticSize
7311 local NoWindowRegistor = Config.NoWindowRegistor
7312 local AutoSelectNewTabs = Config.AutoSelectNewTabs
7313 local OpenOnDoubleClick = Config.OpenOnDoubleClick
7314 local NoCollapse = Config.NoCollapse
7315 local _SelectDisabled = Config.Parent ~= WindowsContainer
7316
7317 local CanvasConfig = {
7318 Scroll = not NoScroll,
7319 Fill = not AutomaticSize and true or nil,
7320 UiPadding = UDim.new(0, NoTabs and 8 or 0),
7321 AutoSelectNewTabs = AutoSelectNewTabs
7322 }
7323
7324 --// Merge AutomaticSize configuration
7325 if AutomaticSize then
7326 Merge(CanvasConfig, {
7327 AutomaticSize = AutomaticSize,
7328 Size = UDim2.new(1, 0)
7329 })
7330 end
7331
7332 --// Create Window frame
7333 local Window: CanvasGroup = ReGui:InsertPrefab("Window", Config)
7334 local ContentFrame: Frame = Window.Content
7335 local TitleBar: Frame = ContentFrame.TitleBar
7336
7337 --// Create window class
7338 local Class = NewClass(WindowClass)
7339
7340 --// Content canvas
7341 local BaseCanvas = ReGui:MakeCanvas({
7342 Element = ContentFrame,
7343 WindowClass = Class,
7344 Class = Class
7345 })
7346
7347 --// Create Window content canvas
7348 local Canvas, Body, WindowClass = nil, nil, nil
7349 local WindowCanvas, CanvasFrame = BaseCanvas:Canvas(Copy(CanvasConfig, {
7350 Parent = ContentFrame,
7351 CornerRadius = UDim.new(0, 0),
7352 --NoStyle = true
7353 }))
7354
7355 --// Make the window resizable
7356 local ResizeConnection = ReGui:MakeResizable({
7357 MinimumSize = MinimumSize,
7358 Resize = Window,
7359 OnUpdate = function(Size)
7360 Class:SetSize(Size, true)
7361 end,
7362 })
7363
7364 --// Merge tables
7365 Merge(Class, Config)
7366 Merge(Class, {
7367 WindowFrame = Window,
7368 ContentFrame = ContentFrame,
7369 CanvasFrame = CanvasFrame,
7370 ResizeGrab = ResizeConnection.Grab,
7371 TitleBar = TitleBar,
7372 Elements = Elements,
7373 TagsList = {},
7374 _SelectDisabled = _SelectDisabled,
7375
7376 --// Connections
7377 ResizeConnection = ResizeConnection,
7378 HoverConnection = ReGui:DetectHover(ContentFrame),
7379 DragConnection = ReGui:MakeDraggable({
7380 Grab = ContentFrame,
7381 Move = Window,
7382 SetPosition = function(self, Position: UDim2)
7383 local Tweeninfo = Canvas:GetThemeKey("AnimationTweenInfo")
7384 --// Tween frame element to the new size
7385 Animation:Tween({
7386 Tweeninfo = Tweeninfo,
7387 Object = self.Move,
7388 EndProperties = {
7389 Position = Position
7390 }
7391 })
7392 end,
7393 OnDragStateChange = function(IsDragging: boolean)
7394 Class.IsDragging = IsDragging
7395 CanvasFrame.Interactable = not IsDragging
7396
7397 --// Change window focus on drag
7398 if IsDragging then
7399 ReGui:SetFocusedWindow(WindowClass)
7400 end
7401
7402 --// Disable other window focuses if dragging
7403 ReGui:SetWindowFocusesEnabled(not IsDragging)
7404 end,
7405 }),
7406 })
7407
7408 --// Create canvas for Window type
7409 if NoTabs then
7410 --// Window
7411 Canvas, Body = WindowCanvas, CanvasFrame
7412 else
7413 --// TabsWindow
7414 Canvas, Body = WindowCanvas:TabSelector(CanvasConfig)
7415 Class.WindowTabSelector = Canvas
7416 end
7417
7418 --// Create Window class from Canvas and Class merge
7419 WindowClass = ReGui:MergeMetatables(Class, Canvas)
7420
7421 --// Merge canvas data
7422 Merge(Class, {
7423 ContentCanvas = Canvas,
7424 WindowClass = WindowClass,
7425 Body = Body
7426 })
7427
7428 --// Connect double click events to the collapse
7429 ReGui:ConnectMouseEvent(ContentFrame, {
7430 DoubleClick = true,
7431 OnlyMouseHovering = TitleBar,
7432 Callback = function(...)
7433 if not Class.OpenOnDoubleClick then return end
7434 if Class.NoCollapse then return end
7435
7436 Class:ToggleCollapsed()
7437 end,
7438 })
7439
7440 --// Create default title bar
7441 if not NoTitleButtons then
7442 Class:AddDefaultTitleButtons()
7443 end
7444
7445 --// Update window UI
7446 Class:SetTitle(Title)
7447 Class:SetCollapsed(Collapsed, true)
7448
7449 --// Update window configuration
7450 Class:SetTheme(Theme)
7451 Class:UpdateConfig(Config)
7452
7453 --// Update selection
7454 Class:SetFocused()
7455
7456 --// Register elements into Window Class
7457 local ResizeGrab = ResizeConnection.Grab
7458 ReGui:SetAnimation(ResizeGrab, "TextButtons")
7459
7460 WindowClass:TagElements({
7461 [ResizeGrab] = "ResizeGrab",
7462 [TitleBar] = "TitleBar",
7463 [CanvasFrame] = "Window"
7464 })
7465
7466 --// Append to Windows array
7467 if not NoWindowRegistor then
7468 table.insert(Windows, WindowClass)
7469 end
7470
7471 return WindowClass, Window
7472 end,
7473})
7474
7475export type TabsWindowFlags = {
7476 AutoSelectNewTabs: boolean?,
7477} & WindowFlags
7478ReGui:DefineElement("TabsWindow", {
7479 Export = true,
7480 Base = {
7481 NoTabs = false,
7482 AutoSelectNewTabs = true
7483 },
7484 Create = function(self, Config: TabsWindowFlags)
7485 return self:Window(Config)
7486 end,
7487})
7488
7489export type PopupCanvas = {
7490 Scroll: boolean?,
7491 AutoClose: boolean?,
7492 RelativeTo: GuiObject,
7493 MaxSizeY: number?,
7494 MinSizeX: number?,
7495 MaxSizeX: number?,
7496
7497 UpdateScale: (PopupCanvas) -> nil,
7498 UpdatePosition: (PopupCanvas) -> nil,
7499 ClosePopup: (PopupCanvas) -> nil,
7500 SetPopupVisible: (PopupCanvas, Visible: boolean) -> nil
7501}
7502ReGui:DefineElement("PopupCanvas", {
7503 Base = {
7504 AutoClose = false,
7505 Scroll = false,
7506 Visible = true,
7507 Spacing = UDim.new(0, 1),
7508 AutomaticSize = Enum.AutomaticSize.XY,
7509 MaxSizeY = 150,
7510 MinSizeX = 100,
7511 MaxSizeX = math.huge,
7512 OnClosed = EmptyFunction
7513 },
7514 Create = function(self, Config: PopupCanvas)
7515 Config.Parent = ReGui.Container.Overlays
7516
7517 local RelativeTo = Config.RelativeTo
7518 local MaxSizeY = Config.MaxSizeY
7519 local MinSizeX = Config.MinSizeX
7520 local MaxSizeX = Config.MaxSizeX
7521 local Visible = Config.Visible
7522 local AutoClose = Config.AutoClose
7523 local NoAnimation = Config.NoAnimation
7524
7525 --// Create object
7526 local Canvas, Object = self:OverlayScroll(Config)
7527 local UIStroke = Object.UIStroke
7528
7529 local Padding = UIStroke.Thickness
7530 local Relative = Object.Parent.AbsolutePosition
7531
7532 local Position, Size, YSize, XSize
7533
7534 --// Connect mouse events
7535 local Hover = ReGui:DetectHover(Object, {
7536 MouseOnly = true,
7537 OnInput = function(MouseHovering, Input)
7538 if MouseHovering then return end
7539 if not Object.Visible then return end
7540 Config:OnFocusLost()
7541 end,
7542 })
7543
7544 function Config:FetchScales()
7545 --// Roblox does not support UISizeConstraint on a scrolling frame grr
7546 local CanvasSize = Canvas:GetCanvasSize()
7547
7548 Position = RelativeTo.AbsolutePosition
7549 Size = RelativeTo.AbsoluteSize
7550
7551 YSize = math.clamp(CanvasSize.Y, Size.Y, MaxSizeY)
7552 XSize = math.clamp(Size.X, MinSizeX, MaxSizeX)
7553 end
7554
7555 function Config:UpdatePosition()
7556 Object.Position = UDim2.fromOffset(
7557 Position.X - Relative.X + Padding,
7558 Position.Y - Relative.Y + Size.Y
7559 )
7560 end
7561
7562 function Config:GetScale(Visible: boolean): UDim2
7563 local OpenSize = UDim2.fromOffset(XSize, YSize)
7564 local ClosedSize = UDim2.fromOffset(XSize, 0)
7565
7566 return Visible and OpenSize or ClosedSize
7567 end
7568
7569 function Config:IsMouseHovering(): boolean
7570 return Hover.Hovering
7571 end
7572
7573 function Config:OnFocusLost()
7574 local OnClosed = self.OnClosed
7575
7576 self:SetPopupVisible(false)
7577 OnClosed(self) -- Invoke closed callback
7578
7579 --// Automatically destroy popup
7580 if AutoClose then
7581 self:ClosePopup()
7582 end
7583 end
7584
7585 function Config:ClosePopup(Wait: boolean?)
7586 self:SetPopupVisible(false, NoAnimation, Wait)
7587 Hover:Disconnect()
7588 Object:Remove()
7589 end
7590
7591 function Config:SetPopupVisible(Visible: boolean, Wait: boolean?)
7592 --// Check if the visiblity is the same
7593 if Object.Visible == Visible then return end
7594
7595 RelativeTo.Interactable = not Visible
7596 self:UpdateScales(Visible, NoAnimation, Wait)
7597 self.Visible = Visible
7598 end
7599
7600 function Config:UpdateScales(Visible: boolean, NoAnimation: boolean, Wait: boolean?)
7601 local Tweeninfo = Canvas:GetThemeKey("AnimationTweenInfo")
7602
7603 if Visible == nil then
7604 Visible = Object.Visible
7605 end
7606
7607 Config:FetchScales()
7608 Config:UpdatePosition()
7609
7610 local Tween = Animation:Tween({
7611 Tweeninfo = Tweeninfo,
7612 Object = Object,
7613 NoAnimation = NoAnimation,
7614 EndProperties = {
7615 Size = Config:GetScale(Visible),
7616 Visible = Visible,
7617 }
7618 })
7619
7620 --// Wait for tween to finish
7621 if Tween and Wait then
7622 Tween.Completed:Wait()
7623 end
7624 end
7625
7626 --// Update object
7627 Config:UpdateScales(false, true)
7628 Config:SetPopupVisible(Visible)
7629
7630 Canvas.OnChildChange:Connect(Config.UpdateScales)
7631
7632 return Canvas, Object
7633 end,
7634})
7635
7636ReGui:DefineElement("PopupModal", {
7637 Export = true,
7638 Base = {
7639 NoAnimation = false,
7640 NoCollapse = true,
7641 NoClose = true,
7642 NoResize = true,
7643 NoSelect = true,
7644 NoAutoFlags = true,
7645 NoWindowRegistor = true,
7646 NoScroll = true,
7647 },
7648 Create = function(self, Config: WindowFlags)
7649 Config.Parent = ReGui.Container.Overlays
7650
7651 local WindowClass = self.WindowClass
7652
7653 --// Unpack configuration
7654 local NoAnimation = Config.NoAnimation
7655 local WindowDimTweenInfo = nil
7656
7657 --// Get addional configuration from the Window Class
7658 if WindowClass then
7659 WindowDimTweenInfo = WindowClass:GetThemeKey("ModalWindowDimTweenInfo")
7660 Config.Theme = WindowClass.Theme
7661 end
7662
7663 --// Create Effect object
7664 local ModalEffect = ReGui:InsertPrefab("ModalEffect", Config)
7665
7666 --// Create window used for the modal
7667 local Window = self:Window(Copy(Config, {
7668 NoAutoFlags = false,
7669 Parent = ModalEffect,
7670 AnchorPoint = Vector2.new(0.5, 0.5),
7671 Position = UDim2.fromScale(0.5, 0.5),
7672 Size = UDim2.fromOffset(372, 38),
7673 AutomaticSize = Enum.AutomaticSize.Y
7674 }))
7675
7676 function Config:ClosePopup()
7677 Animation:Tween({
7678 Object = ModalEffect,
7679 Tweeninfo = WindowDimTweenInfo,
7680 NoAnimation = NoAnimation,
7681 EndProperties = {
7682 BackgroundTransparency = 1
7683 },
7684 Completed = function()
7685 ModalEffect:Destroy()
7686 end
7687 })
7688
7689 Window:Close()
7690 end
7691
7692 --// Fade modal effect
7693 Animation:Tween({
7694 Object = ModalEffect,
7695 Tweeninfo = WindowDimTweenInfo,
7696 NoAnimation = NoAnimation,
7697 StartProperties = {
7698 BackgroundTransparency = 1
7699 },
7700 EndProperties = {
7701 BackgroundTransparency = 0.8
7702 }
7703 })
7704
7705 --// Tag elements into the theme
7706 self:TagElements({
7707 [ModalEffect] = "ModalWindowDim"
7708 })
7709
7710 --// Create the modal class
7711 local ModalClass = ReGui:MergeMetatables(Config, Window)
7712 return ModalClass, ModalEffect
7713 end,
7714})
7715
7716return ReGui