├── assets └── rblxguibanner.png ├── default.project.json ├── src ├── rblxgui │ ├── lib │ │ ├── PluginGlobalVariables.lua │ │ ├── GUIElement.lua │ │ ├── Template.lua │ │ ├── Managers │ │ │ ├── EventManager.lua │ │ │ ├── InputManager.lua │ │ │ ├── LayoutManager.lua │ │ │ ├── ThemeManager.lua │ │ │ └── KeybindManager.lua │ │ ├── Objects │ │ │ ├── ObjectTemplate.lua │ │ │ ├── GUIObject.lua │ │ │ ├── InstanceInputField.lua │ │ │ ├── Textbox.lua │ │ │ ├── ProgressBar.lua │ │ │ ├── ToggleableButton.lua │ │ │ ├── TitlebarButton.lua │ │ │ ├── Labeled.lua │ │ │ ├── Checkbox.lua │ │ │ ├── KeybindInputField.lua │ │ │ ├── Slider.lua │ │ │ ├── ColorInput.lua │ │ │ ├── Button.lua │ │ │ ├── ViewButton.lua │ │ │ └── InputField.lua │ │ ├── Frames │ │ │ ├── GUIFrame.lua │ │ │ ├── BackgroundFrame.lua │ │ │ ├── ListFrame.lua │ │ │ ├── ScrollingFrame.lua │ │ │ ├── Section.lua │ │ │ ├── PluginWidget.lua │ │ │ ├── Page.lua │ │ │ └── TitlebarMenu.lua │ │ ├── Prompts │ │ │ ├── InputPrompt.lua │ │ │ ├── Prompt.lua │ │ │ ├── TextPrompt.lua │ │ │ └── ColorPrompt.lua │ │ └── Misc │ │ │ └── GUIUtil.lua │ └── initialize.lua └── Example.client.lua ├── README.md └── LICENSE /assets/rblxguibanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arch4ic/rblxguilib/HEAD/assets/rblxguibanner.png -------------------------------------------------------------------------------- /default.project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rblxguilib", 3 | "tree": { 4 | "$path": "src" 5 | } 6 | } -------------------------------------------------------------------------------- /src/rblxgui/lib/PluginGlobalVariables.lua: -------------------------------------------------------------------------------- 1 | local m = {} 2 | m.LibraryDir = script.Parent 3 | m.FramesDir = m.LibraryDir.Frames 4 | m.ObjectsDir = m.LibraryDir.Objects 5 | m.ManagersDir = m.LibraryDir.Managers 6 | m.PromptsDir = m.LibraryDir.Prompts 7 | m.MiscDir = m.LibraryDir.Misc 8 | 9 | return m -------------------------------------------------------------------------------- /src/rblxgui/lib/GUIElement.lua: -------------------------------------------------------------------------------- 1 | local GUIElement = {} 2 | GUIElement.__index = GUIElement 3 | 4 | local GV = require(script.Parent.PluginGlobalVariables) 5 | 6 | function GUIElement.new(Arguments, Parent) 7 | local self = {} 8 | setmetatable(self,GUIElement) 9 | self.Arguments = Arguments or {} 10 | self.Parent = Parent 11 | return self 12 | end 13 | 14 | return GUIElement -------------------------------------------------------------------------------- /src/rblxgui/lib/Template.lua: -------------------------------------------------------------------------------- 1 | -- template for classes 2 | 3 | --inheritance 4 | --local GUIElement = require(GV.LibraryDir.GUIElement) 5 | --setmetatable(,GUIElement) 6 | 7 | local temp = {} 8 | temp.__index = temp 9 | 10 | 11 | function temp.new() 12 | --self = GUIElement.new() 13 | local self = {} 14 | setmetatable(self,temp) 15 | return self 16 | end 17 | 18 | return temp -------------------------------------------------------------------------------- /src/rblxgui/lib/Managers/EventManager.lua: -------------------------------------------------------------------------------- 1 | local m = {} 2 | 3 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 4 | m.EventList = {} 5 | 6 | function m.AddConnection(Connection, func) 7 | m.EventList[#m.EventList+1] = Connection:Connect(func) 8 | end 9 | 10 | GV.PluginObject.Unloading:Connect(function() 11 | for _, v in pairs(m.EventList) do 12 | v:Disconnect() 13 | end 14 | end) 15 | 16 | return m -------------------------------------------------------------------------------- /src/rblxgui/initialize.lua: -------------------------------------------------------------------------------- 1 | local GV = require(script.Parent.lib.PluginGlobalVariables) 2 | local function requireall(p,id) 3 | GV.PluginObject = p 4 | local library = {} 5 | if id then require(script.Parent.lib.PluginGlobalVariables).PluginID = id end 6 | for _, i in pairs(script.Parent.lib:GetDescendants()) do 7 | if i:IsA("ModuleScript") then 8 | library[i.Name] = require(i) 9 | end 10 | end 11 | return library 12 | end 13 | return requireall -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/ObjectTemplate.lua: -------------------------------------------------------------------------------- 1 | local temp = {} 2 | temp.__index = temp 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | setmetatable(temp,GUIObject) 8 | 9 | function temp.new(Arguments, Parent) 10 | local self = GUIObject.new(Arguments, Parent) 11 | setmetatable(self,temp) 12 | self.Object = nil 13 | self.MainMovable = nil 14 | return self 15 | end 16 | 17 | return temp -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/GUIFrame.lua: -------------------------------------------------------------------------------- 1 | local GUIFrame = {} 2 | GUIFrame.__index = GUIFrame 3 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 4 | local GUIElement = require(GV.LibraryDir.GUIElement) 5 | setmetatable(GUIFrame,GUIElement) 6 | 7 | GV.MainGUI = nil 8 | 9 | function GUIFrame.new(Arguments, Parent) 10 | local self = GUIElement.new(Arguments, Parent or GV.MainGUI) 11 | setmetatable(self,GUIFrame) 12 | self.Content = nil 13 | return self 14 | end 15 | 16 | function GUIFrame:SetMain() 17 | GV.MainGUI = self.Content 18 | end 19 | 20 | return GUIFrame -------------------------------------------------------------------------------- /src/rblxgui/lib/Managers/InputManager.lua: -------------------------------------------------------------------------------- 1 | local m = {} 2 | 3 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 4 | local EventManager = require(GV.ManagersDir.EventManager) 5 | 6 | m.InputFieldEvents = {} 7 | m.InputFrames = {} 8 | function m.AddInputEvent(Event, func) 9 | m.InputFieldEvents[#m.InputFieldEvents+1] = {Event, func} 10 | for _, v in pairs(m.InputFrames) do 11 | EventManager.AddConnection(v[Event], func) 12 | end 13 | end 14 | 15 | function m.AddInput(Frame) 16 | m.InputFrames[#m.InputFrames + 1] = Frame 17 | for _, v in pairs(m.InputFieldEvents) do 18 | EventManager.AddConnection(Frame[v[1]], v[2]) 19 | end 20 | end 21 | 22 | return m -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/BackgroundFrame.lua: -------------------------------------------------------------------------------- 1 | local BackgroundFrame = {} 2 | BackgroundFrame.__index = BackgroundFrame 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIFrame = require(GV.FramesDir.GUIFrame) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(BackgroundFrame,GUIFrame) 9 | 10 | 11 | function BackgroundFrame.new(Arguments, Parent) 12 | local self = GUIFrame.new(Arguments, Parent) 13 | setmetatable(self,BackgroundFrame) 14 | -- generate background frame 15 | self.Content = Instance.new("Frame", self.Parent) 16 | ThemeManager.ColorSync(self.Content, "BackgroundColor3", Enum.StudioStyleGuideColor.MainBackground) 17 | self.Content.Size = UDim2.new(1,0,1,0) 18 | self.Content.Name = "Background" 19 | self.Content.ZIndex = 0 20 | return self 21 | end 22 | 23 | return BackgroundFrame -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/GUIObject.lua: -------------------------------------------------------------------------------- 1 | local GUIObject = {} 2 | GUIObject.__index = GUIObject 3 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 4 | local GUIElement = require(GV.LibraryDir.GUIElement) 5 | local ListFrame = require(GV.FramesDir.ListFrame) 6 | setmetatable(GUIObject,GUIElement) 7 | GV.ObjectList = {} 8 | 9 | function GUIObject.new(Arguments, Parent) 10 | local self = GUIElement.new(Arguments, Parent or ListFrame.new().Content) 11 | setmetatable(self,GUIObject) 12 | self.Object = nil 13 | self.MainMovable = nil 14 | GV.ObjectList[#GV.ObjectList+1] = self 15 | return self 16 | end 17 | 18 | function GUIObject:Move(NewFrame, WithFrame) 19 | local PreviousParent = self.Parent 20 | self.MainMovable.Parent = NewFrame 21 | self.Parent = NewFrame 22 | if PreviousParent:IsA("Frame") and WithFrame then 23 | for _, i in pairs(PreviousParent:GetChildren()) do 24 | if i:IsA("Frame") then 25 | return self.Object 26 | end 27 | end 28 | PreviousParent:Destroy() 29 | end 30 | end 31 | 32 | 33 | 34 | return GUIObject -------------------------------------------------------------------------------- /src/rblxgui/lib/Prompts/InputPrompt.lua: -------------------------------------------------------------------------------- 1 | local InputPrompt = {} 2 | InputPrompt.__index = InputPrompt 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local TextPrompt = require(GV.PromptsDir.TextPrompt) 7 | local InputFieldMod = require(GV.ObjectsDir.InputField) 8 | 9 | setmetatable(InputPrompt, TextPrompt) 10 | 11 | -- Title, Textbox, Buttons, InputField 12 | function InputPrompt.new(Arguments) 13 | local self = TextPrompt.new(Arguments) 14 | setmetatable(self,InputPrompt) 15 | local InputField = self.Arguments.InputField or self.Arguments.Input 16 | if type(InputField) == "string" then 17 | self.InputField = InputFieldMod.new({Placeholder = InputField, InputSize = UDim.new(1,-30), NoDropdown = true, Unpausable = true}) 18 | else 19 | self.InputField = InputField 20 | end 21 | self.InputField.Arguments.Unpausable = true 22 | self.InputField.InputFieldContainer.Size = UDim2.new(1,0,0,25) 23 | self.InputField.DropdownMaxY = 30 24 | self.ButtonsFrame.Parent = nil 25 | self.InputField:Move(self.TextPromptContainer, true) 26 | self.ButtonsFrame.Parent = self.TextPromptContainer 27 | self.Input = self.InputField.Input 28 | return self 29 | end 30 | 31 | return InputPrompt -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/InstanceInputField.lua: -------------------------------------------------------------------------------- 1 | local InstanceInputField = {} 2 | InstanceInputField.__index = InstanceInputField 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local InputField = require(GV.ObjectsDir.InputField) 7 | local Selection = game:GetService("Selection") 8 | setmetatable(InstanceInputField,InputField) 9 | 10 | function InstanceInputField.new(Arguments, Parent) 11 | Arguments = Arguments or {} 12 | Arguments.Placeholder = Arguments.Placeholder or "Select object(s)" 13 | Arguments.DisableEditing = true 14 | local self = InputField.new(Arguments, Parent) 15 | setmetatable(self,InstanceInputField) 16 | self.IgnoreText = true 17 | self.DefaultEmpty = {} 18 | self.Focusable = true 19 | self.TextEditable = true 20 | self.Input.Focused:Connect(function() 21 | if self.Disabled then return end 22 | local CurrentSelection = Selection:Get() 23 | if #CurrentSelection > 0 then self:SetValue(CurrentSelection) end 24 | end) 25 | Selection.SelectionChanged:Connect(function() 26 | if self.Disabled then return end 27 | if self.Input:IsFocused() then 28 | local CurrentSelection = Selection:Get() 29 | if #CurrentSelection > 0 then self:SetValue(CurrentSelection) end 30 | end 31 | end) 32 | return self 33 | end 34 | 35 | return InstanceInputField -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/Textbox.lua: -------------------------------------------------------------------------------- 1 | local Textbox = {} 2 | Textbox.__index = Textbox 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(Textbox,GUIObject) 9 | 10 | function Textbox:SetDisabled(State) 11 | self.Disabled = State 12 | if self.Disabled then 13 | self.Textbox.TextTransparency = 0.5 14 | else 15 | self.Textbox.TextTransparency = 0 16 | end 17 | end 18 | 19 | function Textbox:ToggleDisable() 20 | self:SetDisabled(not self.Disabled) 21 | end 22 | 23 | -- Text, Font, Alignment, TextSize 24 | function Textbox.new(Arguments, Parent) 25 | local self = GUIObject.new(Arguments, Parent) 26 | setmetatable(self,Textbox) 27 | local Alignment = self.Arguments.Alignment or Enum.TextXAlignment.Center 28 | local Font = self.Arguments.Font or Enum.Font.SourceSans 29 | local TextSize = self.Arguments.TextSize or self.Arguments.FontSize or 15 30 | self.Textbox = Instance.new("TextLabel", self.Parent) 31 | self.Textbox.BackgroundTransparency = 1 32 | self.Textbox.Size = UDim2.new(1,0,1,0) 33 | self.Textbox.TextXAlignment = Alignment 34 | self.Textbox.TextSize = TextSize 35 | self.Textbox.Font = Font 36 | self.Textbox.Text = self.Arguments.Text 37 | ThemeManager.ColorSync(self.Textbox, "TextColor3", Enum.StudioStyleGuideColor.MainText) 38 | self.Object = self.Textbox 39 | self.MainMovable = self.Textbox 40 | return self 41 | end 42 | 43 | return Textbox -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/ListFrame.lua: -------------------------------------------------------------------------------- 1 | local ListFrame = {} 2 | ListFrame.__index = ListFrame 3 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 4 | local GUIFrame = require(GV.FramesDir.GUIFrame) 5 | setmetatable(ListFrame,GUIFrame) 6 | local Count = 0 7 | 8 | 9 | -- Name, Height 10 | function ListFrame.new(Arguments, Parent) 11 | local self = GUIFrame.new(Arguments, Parent) 12 | setmetatable(self,ListFrame) 13 | Count = Count + 1; 14 | self.Arguments.Height = self.Arguments.Height or 28 15 | self.Content = Instance.new("Frame", self.Parent) 16 | self.Content.BackgroundTransparency = 1 17 | self.Content.Size = UDim2.new(1,0,0,self.Arguments.Height) 18 | self.Content.Name = Count 19 | if self.Arguments.Name then self.Content.Name = self.Content.Name .. ": " .. self.Arguments.Name end 20 | -- layout (used for stacking multiple elements in one row) 21 | self.Layout = Instance.new("UIGridLayout", self.Content) 22 | self.Layout.SortOrder = Enum.SortOrder.LayoutOrder 23 | self.Layout.FillDirection = Enum.FillDirection.Vertical 24 | self.Layout.HorizontalAlignment = Enum.HorizontalAlignment.Center 25 | self.Layout.Changed:Connect(function(p) 26 | if p == "AbsoluteCellCount" and self.Layout.AbsoluteCellCount.X > 0 then 27 | self.Layout.CellSize = UDim2.new(1/self.Layout.AbsoluteCellCount.X,0,1,0) 28 | end 29 | end) 30 | -- self.Padding for elements in frame 31 | self.Padding = Instance.new("UIPadding", self.Content) 32 | self.Padding.PaddingBottom, self.Padding.PaddingLeft, self.Padding.PaddingRight, self.Padding.PaddingTop = UDim.new(0,2), UDim.new(0,2), UDim.new(0,2), UDim.new(0,2) 33 | return self 34 | end 35 | 36 | return ListFrame -------------------------------------------------------------------------------- /src/rblxgui/lib/Prompts/Prompt.lua: -------------------------------------------------------------------------------- 1 | local Prompt = {} 2 | Prompt.__index = Prompt 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local BackgroundFrame = require(GV.FramesDir.BackgroundFrame) 7 | local GUIElement = require(GV.LibraryDir.GUIElement) 8 | local ResetThreshold = 5 9 | setmetatable(Prompt,GUIElement) 10 | 11 | function Prompt:Destroy() 12 | if not self.Arguments.NoPause then util.UnpauseAll() end 13 | self.Widget:Destroy() 14 | end 15 | 16 | function Prompt:OnWindowClose(func) 17 | self.CloseAction = func 18 | end 19 | 20 | function Prompt:Reset(Title, Width, Height) 21 | if self.Resetting then return end 22 | self.Resetting = true 23 | Title = Title or "Prompt" 24 | if not Width or Width < 1 then Width = 260 end 25 | if not Height or Height < 1 then Height = 75 end 26 | local NewWidget = GV.PluginObject:CreateDockWidgetPluginGui(game:GetService("HttpService"):GenerateGUID(false), DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, true, true, Width+2, Height+24,1,1)) 27 | if self.Widget then for _,v in pairs(self.Widget:GetChildren())do 28 | v.Parent = NewWidget 29 | end self.Widget:Destroy() end 30 | NewWidget.Title = Title 31 | NewWidget.Changed:Connect(function(p) 32 | if p == "AbsoluteSize" then 33 | if NewWidget.AbsoluteSize.X ~= Width or NewWidget.AbsoluteSize.Y ~= Height then 34 | if not self.ResetCounter or self.ResetCounter < ResetThreshold then 35 | self.ResetCounter = (self.ResetCounter or 0) + 1 36 | self:Reset(Title, Width, Height) 37 | end 38 | end 39 | elseif p == "Enabled" then 40 | NewWidget.Enabled = true 41 | if self.CloseAction then self.CloseAction() end 42 | end 43 | end) 44 | self.Widget = NewWidget 45 | self.Resetting = false 46 | end 47 | 48 | -- Title, Width, Height, NoPause 49 | function Prompt.new(Arguments) 50 | local self = GUIElement.new(Arguments) 51 | setmetatable(self,Prompt) 52 | self:Reset(self.Arguments.Title, self.Arguments.Width, self.Arguments.Height) 53 | if not self.Arguments.NoPause then util.PauseAll() end 54 | local BackgroundFrame = BackgroundFrame.new(nil, self.Widget) 55 | self.Parent = BackgroundFrame.Content 56 | return self 57 | end 58 | 59 | return Prompt -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/ProgressBar.lua: -------------------------------------------------------------------------------- 1 | local ProgressBar = {} 2 | ProgressBar.__index = ProgressBar 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(ProgressBar,GUIObject) 9 | 10 | function ProgressBar:SetDisabled(State) 11 | self.Disabled = State 12 | if self.Disabled then 13 | self.ProgressBar.BackgroundTransparency, self.ProgressIndicator.BackgroundTransparency = 0.5, 0.5 14 | else 15 | self.ProgressBar.BackgroundTransparency, self.ProgressIndicator.BackgroundTransparency = 0, 0 16 | end 17 | end 18 | 19 | function ProgressBar:ToggleDisable() 20 | self:SetDisabled(not self.Disabled) 21 | end 22 | 23 | function ProgressBar:SetValue(Value) 24 | self.Value = Value 25 | self.ProgressIndicator.Size = UDim2.new(self.Value,0,1,0) 26 | end 27 | 28 | -- BarSize, Value, Disabled 29 | function ProgressBar.new(Arguments, Parent) 30 | local self = GUIObject.new(Arguments, Parent) 31 | setmetatable(self,ProgressBar) 32 | self.ProgressBarContainer = Instance.new("Frame", self.Parent) 33 | self.ProgressBarContainer.Name = "ProgressBarContainer" 34 | self.ProgressBarContainer.BackgroundTransparency = 1 35 | self.ProgressBarContainer.Size = UDim2.new(1,0,1,0) 36 | self.ProgressBar = Instance.new("Frame", self.ProgressBarContainer) 37 | self.ProgressBar.Name = "ProgressBar" 38 | self.ProgressBar.AnchorPoint = Vector2.new(0.5,0.5) 39 | local Size = util.GetScale(self.Arguments.BarSize) or UDim.new(1,-12) 40 | self.ProgressBar.Size = UDim2.new(Size.Scale,Size.Offset,0,16) 41 | self.ProgressBar.Position = UDim2.new(0.5,0,0.5,0) 42 | ThemeManager.ColorSync(self.ProgressBar, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 43 | ThemeManager.ColorSync(self.ProgressBar, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 44 | self.ProgressIndicator = Instance.new("Frame", self.ProgressBar) 45 | self.ProgressIndicator.Name = "Indicator" 46 | self:SetValue(self.Arguments.Value) 47 | self.ProgressIndicator.BorderSizePixel = 0 48 | ThemeManager.ColorSync(self.ProgressIndicator, "BackgroundColor3", Enum.StudioStyleGuideColor.LinkText, nil, true) 49 | self:SetDisabled(self.Arguments.Disabled) 50 | self.Object = self.ProgressIndicator 51 | self.MainMovable = self.ProgressBarContainer 52 | return self 53 | end 54 | 55 | return ProgressBar -------------------------------------------------------------------------------- /src/rblxgui/lib/Managers/LayoutManager.lua: -------------------------------------------------------------------------------- 1 | local m = {} 2 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 3 | local util = require(GV.MiscDir.GUIUtil) 4 | 5 | function m.SearchForID(ID, Table) 6 | for i,v in pairs(Table) do 7 | if v.ID == ID then return {i,v} end 8 | end 9 | return {nil,nil} 10 | end 11 | 12 | function m.GetLayout() 13 | local layout = {Widgets = {}, Pages = {}} 14 | for _, Widget in pairs(GV.PluginWidgets) do 15 | local WidgetDesc = { 16 | ID = Widget.ID, 17 | Title = Widget.WidgetObject.Title 18 | } 19 | layout.Widgets[#layout.Widgets+1] = WidgetDesc 20 | end 21 | for _, Page in pairs(GV.PluginPages) do 22 | local PageDesc = { 23 | ID = Page.ID, 24 | MenuID = Page.TitlebarMenu.ID 25 | } 26 | layout.Pages[#layout.Pages+1] = PageDesc 27 | end 28 | return layout 29 | end 30 | 31 | function m.RecallLayout(layout) 32 | for _, Widget in pairs(layout.Widgets) do 33 | local WidgetTable = m.SearchForID(Widget.ID, GV.PluginWidgets)[2] 34 | if not WidgetTable then 35 | WidgetTable = require(GV.FramesDir.PluginWidget).new({ID = Widget.ID, Title = Widget.Title, Enabled = true}) 36 | end 37 | WidgetTable.WidgetObject.Title = Widget.Title 38 | end 39 | for _, Page in pairs(layout.Pages) do 40 | local PageTable = m.SearchForID(Page.ID, GV.PluginPages)[2] 41 | if PageTable then 42 | if PageTable.TitlebarMenu.ID ~= Page.MenuID then 43 | local NewMenu = m.SearchForID(Page.MenuID, GV.PluginWidgets)[2] 44 | if NewMenu then 45 | PageTable.TitlebarMenu:RemovePage(PageTable) 46 | NewMenu.TitlebarMenu:RecievePage(PageTable) 47 | end 48 | end 49 | end 50 | end 51 | for i, Widget in pairs(GV.PluginWidgets) do 52 | if not m.SearchForID(Widget.ID, layout.Widgets)[2] then 53 | Widget.WidgetObject:Destroy() 54 | Widget = nil 55 | GV.PluginWidgets[i] = nil 56 | end 57 | end 58 | end 59 | 60 | function m.SaveLayout(layout) 61 | layout = layout or m.GetLayout() 62 | GV.PluginObject:SetSetting(GV.PluginID.."PreviousGUIState", layout) 63 | end 64 | 65 | function m.RecallSave() 66 | m.DefaultLayout = m.GetLayout() 67 | m.RecallLayout(GV.PluginObject:GetSetting(GV.PluginID.."PreviousGUIState")) 68 | end 69 | 70 | function m.ResetLayout() 71 | m.RecallLayout(m.DefaultLayout) 72 | end 73 | 74 | GV.PluginObject.Unloading:Connect(function() 75 | m.SaveLayout() 76 | end) 77 | 78 | return m -------------------------------------------------------------------------------- /src/rblxgui/lib/Managers/ThemeManager.lua: -------------------------------------------------------------------------------- 1 | local m = {} 2 | 3 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 4 | local EventManager = require(GV.ManagersDir.EventManager) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | 7 | -- syncs colors with studio theme 8 | local syncedelements = {} 9 | m.DefaultAccentColor = Color3.fromRGB(53, 181, 255) 10 | m.DefaultThemeColor = Color3.new(0.5,0.5,0.5) 11 | 12 | m.PreinstalledThemes = {{Name = "Default Theme", Theme = util.Color3ToTable(m.DefaultThemeColor), Accent = util.Color3ToTable(m.DefaultAccentColor)}} 13 | 14 | function m.ColorSync(element, property, enum, enum2, accent, accenttheme, ignoretheme) 15 | syncedelements[#syncedelements + 1] = {element, property, enum, enum2, accent, accenttheme, ignoretheme} 16 | m.MatchColor(element, property, enum, enum2, accent, accenttheme, ignoretheme) 17 | end 18 | 19 | function m.MatchColor(element, property, enum, enum2, useaccent, accenttheme, ignoretheme) 20 | local Theme = settings().Studio.Theme 21 | if useaccent and (((accenttheme) and accenttheme == tostring(Theme)) or not accenttheme) then 22 | element[property] = m.CurrentAccent 23 | else 24 | local ThemeColor = Theme:GetColor(enum, enum2) 25 | if not ignoretheme then 26 | element[property] = util.AddColor(util.MulitplyColor(util.SubColor(Color3.new(1,1,1), util.MulitplyColor(m.CurrentTheme, Color3.new(2,2,2))), util.MulitplyColor(ThemeColor, ThemeColor)), util.MulitplyColor(util.MulitplyColor(ThemeColor, m.CurrentTheme), Color3.new(2,2,2))) 27 | else 28 | element[property] = ThemeColor 29 | end 30 | end 31 | end 32 | 33 | function m.ReloadTheme(theme, accent) 34 | m.CurrentTheme = theme or m.CurrentTheme 35 | m.CurrentAccent = accent or m.CurrentAccent 36 | for _, v in pairs(syncedelements) do 37 | m.MatchColor(v[1], v[2], v[3], v[4], v[5], v[6], v[7]) 38 | end 39 | end 40 | 41 | function m.UpdateTheme(theme,accent) 42 | m.ThemeColor = theme or m.CurrentTheme 43 | m.AccentColor = accent or m.CurrentAccent 44 | m.ReloadTheme(m.ThemeColor, m.AccentColor) 45 | end 46 | 47 | EventManager.AddConnection(settings().Studio.ThemeChanged, function() 48 | m.ReloadTheme(m.CurrentTheme, m.CurrentAccent) 49 | end) 50 | 51 | local LatestThemeSave = GV.PluginObject:GetSetting(GV.PluginID.."PreviousPluginGUITheme") or {Theme = util.Color3ToTable(m.DefaultThemeColor), Accent = util.Color3ToTable(m.DefaultAccentColor)} 52 | m.AccentColor = util.TableToColor3(LatestThemeSave.Accent) 53 | m.ThemeColor = util.TableToColor3(LatestThemeSave.Theme) 54 | m.CurrentTheme = m.ThemeColor 55 | m.CurrentAccent = m.AccentColor 56 | 57 | GV.PluginObject.Unloading:Connect(function() 58 | GV.PluginObject:SetSetting(GV.PluginID.."PreviousPluginGUITheme", {Theme = util.Color3ToTable(m.ThemeColor), Accent = util.Color3ToTable(m.AccentColor)}) 59 | end) 60 | 61 | return m -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/ScrollingFrame.lua: -------------------------------------------------------------------------------- 1 | local ScrollingFrame = {} 2 | ScrollingFrame.__index = ScrollingFrame 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIFrame = require(GV.FramesDir.GUIFrame) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(ScrollingFrame,GUIFrame) 9 | 10 | ScrollingFrame.Images = { 11 | bottom = "http://www.roblox.com/asset/?id=9599518795", 12 | mid = "http://www.roblox.com/asset/?id=9599545837", 13 | top = "http://www.roblox.com/asset/?id=9599519108" 14 | } 15 | 16 | -- updaing the scrolling frame to fit window size based on element size 17 | function ScrollingFrame:UpdateFrameSize() 18 | local ScrollbarVisibility = self.Content.AbsoluteWindowSize.Y < self.Content.AbsoluteCanvasSize.Y 19 | self.Content.CanvasSize = UDim2.new(0,0,0,self.Layout.AbsoluteContentSize.Y) 20 | self.ScrollbarBackground.Visible = ScrollbarVisibility 21 | end 22 | 23 | -- BarSize 24 | function ScrollingFrame.new(Arguments, Parent) 25 | local self = GUIFrame.new(Arguments, Parent) 26 | setmetatable(self, ScrollingFrame) 27 | -- scroll bar background 28 | self.ScrollbarBackground = Instance.new("Frame", self.Parent) 29 | self.ScrollbarBackground.Size = UDim2.new(0,self.Arguments.BarSize or 15,1,0) 30 | self.ScrollbarBackground.Position = UDim2.new(1,-(self.Arguments.BarSize or 15),0,0) 31 | self.ScrollbarBackground.Name = "ScrollbarBackground" 32 | ThemeManager.ColorSync(self.ScrollbarBackground, "BackgroundColor3", Enum.StudioStyleGuideColor.ScrollBarBackground) 33 | 34 | -- scrolling frame 35 | self.Content = Instance.new("ScrollingFrame", self.Parent) 36 | self.Content.BackgroundTransparency = 1 37 | self.Content.Size = UDim2.new(1,0,1,0) 38 | self.Content.ScrollBarThickness = self.Arguments.BarSize or 15 39 | self.Content.BottomImage, self.Content.MidImage, self.Content.TopImage = self.Images.bottom, self.Images.mid, self.Images.top 40 | self.Content.ScrollingDirection = Enum.ScrollingDirection.Y 41 | self.Content.VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar 42 | self.Content.Name = "ScrollingFrame" 43 | self.Content.ZIndex = 2 44 | ThemeManager.ColorSync(self.Content, "ScrollBarImageColor3", Enum.StudioStyleGuideColor.ScrollBar) 45 | ThemeManager.ColorSync(self.Content, "BorderColor3", Enum.StudioStyleGuideColor.Border) 46 | 47 | -- list layout for later elements 48 | self.Layout = Instance.new("UIListLayout", self.Content) 49 | self.Layout.SortOrder = Enum.SortOrder.LayoutOrder 50 | self.Layout.HorizontalAlignment = Enum.HorizontalAlignment.Center 51 | 52 | -- updating the scrollingframe whenever things are added or the size of the widow is changed 53 | self.Layout.Changed:Connect(function(p) 54 | if p == "AbsoluteContentSize" then self:UpdateFrameSize() end 55 | end) 56 | self.Parent.Changed:Connect(function(p) 57 | if p == "AbsoluteSize" then self:UpdateFrameSize() end 58 | end) 59 | return self 60 | end 61 | 62 | return ScrollingFrame -------------------------------------------------------------------------------- /src/rblxgui/lib/Misc/GUIUtil.lua: -------------------------------------------------------------------------------- 1 | local m = {} 2 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 3 | 4 | -- dumps the gui into workspace for debugging 5 | function m.DumpGUI(parent) 6 | local StarterGUI = game:GetService("StarterGui") 7 | local temp = Instance.new("ScreenGui", StarterGUI) 8 | if StarterGUI:FindFirstChild("Dump") then 9 | StarterGUI.Dump.Parent = nil 10 | end 11 | temp.Name = "Dump" 12 | for _, i in pairs(parent:GetChildren()) do 13 | i:Clone().Parent = temp 14 | end 15 | end 16 | 17 | function m.AppendTable(table,newtable) 18 | local fulltable = table 19 | for i, v in pairs(newtable) do fulltable[i] = v end 20 | return fulltable 21 | end 22 | 23 | function m.DumpTable(Table, Step) 24 | Step = Step or 1 25 | if type(Table) == "table"then 26 | local result = "{\n" .. string.rep(":", Step) 27 | for i, v in pairs(Table) do 28 | result = result .. i .." = " .. m.DumpTable(v, Step+1) .. "," 29 | end 30 | return result .. "\n".. string.rep(":", Step-1) .. "}" 31 | else 32 | return tostring(Table) 33 | end 34 | end 35 | 36 | function m.HoverIcon(element, icon) 37 | icon = icon or "rbxasset://SystemCursors/PointingHand" 38 | element.MouseMoved:Connect(function() 39 | GV.PluginObject:GetMouse().Icon = icon 40 | end) 41 | element.MouseLeave:Connect(function() 42 | task.wait(0) 43 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Arrow" 44 | end) 45 | end 46 | 47 | function m.CopyTable(t) 48 | local newt = {} 49 | for i,v in pairs(t) do 50 | newt[i] = v 51 | end 52 | return newt 53 | end 54 | 55 | function m.GetScale(Scale) 56 | if typeof(Scale) == "UDim" then 57 | return Scale 58 | elseif typeof(Scale) == "number" then 59 | return UDim.new(Scale,0) 60 | else 61 | return nil 62 | end 63 | end 64 | 65 | function m.RoundNumber(number, factor) 66 | if factor == 0 then return number else return math.floor(number/factor+0.5)*factor end 67 | end 68 | 69 | local UnpauseList = {} 70 | function m.PauseAll() 71 | if #UnpauseList > 0 then return end 72 | for _,v in pairs(GV.ObjectList) do 73 | if v and v.SetDisabled and not v.Disabled and not v.Arguments.Unpausable then 74 | v:SetDisabled(true) 75 | UnpauseList[#UnpauseList+1] = v 76 | end 77 | end 78 | end 79 | 80 | function m.UnpauseAll() 81 | for _,v in pairs(UnpauseList) do 82 | v:SetDisabled(false) 83 | end 84 | UnpauseList = {} 85 | end 86 | 87 | function m.AddColor(c1, c2) 88 | return Color3.new(c1.R + c2.R, c1.G + c2.G, c1.B + c2.B) 89 | end 90 | function m.SubColor(c1, c2) 91 | return Color3.new(c1.R - c2.R, c1.G - c2.G, c1.B - c2.B) 92 | end 93 | function m.MulitplyColor(c1,c2) 94 | return Color3.new(c1.R * c2.R, c1.G * c2.G, c1.B * c2.B) 95 | end 96 | 97 | function m.Color3ToText(color) 98 | return "[" .. m.RoundNumber(color.R*255, 1) .. ", " .. m.RoundNumber(color.G*255, 1) .. ", " .. m.RoundNumber(color.B*255, 1) .. "]" 99 | end 100 | 101 | function m.TextToColor3(text) 102 | local numbers = {} 103 | for i in text:gmatch("[%.%d]+") do 104 | numbers[#numbers+1] = tonumber(i) 105 | if #numbers == 3 then break end 106 | end 107 | return Color3.fromRGB(numbers[1] or 0, numbers[2] or 0, numbers[3] or 0) 108 | end 109 | 110 | function m.Color3ToTable(color) 111 | return {R = color.R, G = color.G, B = color.B} 112 | end 113 | 114 | function m.TableToColor3(table) 115 | return Color3.new(table.R, table.G, table.B) 116 | end 117 | 118 | return m -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/ToggleableButton.lua: -------------------------------------------------------------------------------- 1 | local ToggleableButton = {} 2 | ToggleableButton.__index = ToggleableButton 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local Button = require(GV.ObjectsDir.Button) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(ToggleableButton,Button) 9 | 10 | function ToggleableButton:Update() 11 | if not self.Value then 12 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder) 13 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button) 14 | else 15 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder, Enum.StudioStyleGuideModifier.Pressed) 16 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Pressed) 17 | end 18 | end 19 | 20 | function ToggleableButton:Toggle() 21 | self:SetValue(not self.Value) 22 | return self.Value 23 | end 24 | 25 | function ToggleableButton:SetValue(Value) 26 | self.Value = Value 27 | self:Update() 28 | end 29 | 30 | -- Textbox, Size, Value, Disabled 31 | function ToggleableButton.new(Arguments, Parent) 32 | local self = Button.new(Arguments, Parent) 33 | setmetatable(self,ToggleableButton) 34 | self.Toggleable = true 35 | local Pressed = false 36 | self.Button.MouseMoved:Connect(function() 37 | if self.Disabled or Pressed then return end 38 | if not self.Value then 39 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder, Enum.StudioStyleGuideModifier.Hover) 40 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Hover) 41 | else 42 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 43 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 44 | end 45 | end) 46 | self.Button.MouseLeave:Connect(function() 47 | if self.Disabled then return end 48 | Pressed = false 49 | self:Update() 50 | end) 51 | self.Button.MouseButton1Down:Connect(function() 52 | if self.Disabled then return end 53 | Pressed = true 54 | if not self.Value then 55 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 56 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 57 | else 58 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder, Enum.StudioStyleGuideModifier.Pressed) 59 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Pressed) 60 | end 61 | end) 62 | 63 | self.Button.MouseButton1Up:Connect(function() 64 | if self.Disabled then return end 65 | Pressed = false 66 | if not self.Value then 67 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder, Enum.StudioStyleGuideModifier.Hover) 68 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Hover) 69 | end 70 | end) 71 | 72 | self.Button.MouseButton1Click:Connect(function() 73 | if not self.Disabled then 74 | self:Toggle() 75 | end 76 | end) 77 | 78 | self:SetValue(self.Arguments.Value) 79 | return self 80 | end 81 | 82 | return ToggleableButton -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/TitlebarButton.lua: -------------------------------------------------------------------------------- 1 | local TitlebarButton = {} 2 | TitlebarButton.__index = TitlebarButton 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(TitlebarButton,GUIObject) 9 | 10 | GV.TitleBarButtons = {} 11 | 12 | function TitlebarButton:SetDisabled(State) 13 | self.Disabled = State 14 | if self.Disabled then 15 | self.CursorIcon = "rbxasset://SystemCursors/Forbidden" 16 | for _,v in pairs(self.Buttons) do 17 | v.Transparency = 0.5 18 | end 19 | else 20 | self.CursorIcon = "rbxasset://SystemCursors/PointingHand" 21 | for _,v in pairs(self.Buttons) do 22 | v.Transparency = 0 23 | end 24 | end 25 | end 26 | 27 | function TitlebarButton:ToggleDisable() 28 | self:SetDisabled(not self.Disabled) 29 | end 30 | 31 | function TitlebarButton:Clicked(func) 32 | self.Action = func 33 | end 34 | 35 | function TitlebarButton:SelectedAction(func) 36 | self.TitlebarMenuSelectedAction = func 37 | end 38 | 39 | function TitlebarButton:CreateCopy(TitlebarMenu) 40 | local Button = Instance.new("TextButton", TitlebarMenu.ButtonContainer) 41 | Button = Instance.new("TextButton", TitlebarMenu.ButtonContainer) 42 | Button.Name = self.Name 43 | Button.Position = UDim2.new(0,TitlebarMenu.ButtonContainer.Size.X.Offset,1,0) 44 | ThemeManager.ColorSync(Button, "BackgroundColor3", Enum.StudioStyleGuideColor.Titlebar,nil,nil,nil,true) 45 | Button.ZIndex = 4 46 | Button.BorderSizePixel = 0 47 | Button.Font = Enum.Font.SourceSans 48 | Button.TextSize = 14 49 | ThemeManager.ColorSync(Button, "TextColor3", Enum.StudioStyleGuideColor.MainText,nil,nil,nil,true) 50 | Button.Text = self.Name 51 | if not self.TabSize then 52 | local function sync() 53 | Button.Size = UDim2.new(0,Button.TextBounds.X+1.5*Button.TextSize, 0, 24) 54 | end 55 | Button.Changed:Connect(function(p) 56 | if p == "TextBounds" then sync() end 57 | end) 58 | else 59 | Button.Size = UDim2.new(0,self.TabSize,1,0) 60 | end 61 | Button.MouseMoved:Connect(function() 62 | GV.PluginObject:GetMouse().Icon = self.CursorIcon 63 | end) 64 | Button.MouseLeave:Connect(function() 65 | task.wait(0) 66 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Arrow" 67 | end) 68 | Button.MouseButton1Click:Connect(function() 69 | if self.Disabled then return end 70 | if self.Action then self.Action() end 71 | if self.PluginMenu then 72 | -- ???? what 73 | task.wait() 74 | task.wait() 75 | -- i have no idea how this works but it does 76 | local SelectedAction = self.PluginMenu:ShowAsync() 77 | if self.TitlebarMenuSelectedAction then self.TitlebarMenuSelectedAction(SelectedAction) end 78 | end 79 | end) 80 | self.Buttons[#self.Buttons+1] = Button 81 | end 82 | 83 | -- Name, TabSize, Disabled, PluginMenu 84 | function TitlebarButton.new(Arguments) 85 | local self = GUIObject.new(Arguments) 86 | setmetatable(self,TitlebarButton) 87 | self.Buttons = {} 88 | self.Name = self.Arguments.Name 89 | self.PluginMenu = self.Arguments.PluginMenu 90 | self.TabSize = self.Arguments.TabSize 91 | for _, v in pairs(GV.PluginWidgets) do 92 | self:CreateCopy(v.TitlebarMenu) 93 | end 94 | self:SetDisabled(self.Arguments.Disabled) 95 | self.Object = self.Buttons 96 | GV.TitleBarButtons[#GV.TitleBarButtons+1] = self 97 | return self 98 | end 99 | 100 | return TitlebarButton -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/Labeled.lua: -------------------------------------------------------------------------------- 1 | local LabeledObject = {} 2 | LabeledObject.__index = LabeledObject 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local TextboxMod = require(GV.ObjectsDir.Textbox) 7 | local GUIObject = require(GV.ObjectsDir.GUIObject) 8 | setmetatable(LabeledObject,GUIObject) 9 | 10 | function LabeledObject:SetDisabled(State) 11 | self.Disabled = State 12 | for _, v in pairs(self.Objects) do v:SetDisabled(State) end 13 | if self.Disabled then 14 | self.Label.TextTransparency = 0.5 15 | else 16 | self.Label.TextTransparency = 0 17 | end 18 | end 19 | 20 | function LabeledObject:ToggleDisable() 21 | self:SetDisabled(not self.Disabled) 22 | end 23 | 24 | function LabeledObject:AddObject(Object, Name, Size) 25 | Object:Move(self.Content, true) 26 | Size = util.GetScale(Size) 27 | if not Size then Size = UDim.new(1-self.TotalUsedScale, -self.TotalUsedOffset) end 28 | Object.MainMovable.Size = UDim2.new(Size.Scale,Size.Offset,1,0) 29 | Object.MainMovable.Position = UDim2.new(self.TotalUsedScale,self.TotalUsedOffset,0,0) 30 | self.TotalUsedScale += Size.Scale 31 | self.TotalUsedOffset += Size.Offset 32 | self[Name] = Object 33 | self.Objects[#self.Objects+1] = Object 34 | end 35 | 36 | -- Textbox, LabelSize, Objects 37 | function LabeledObject.new(Arguments, Parent) 38 | local self = GUIObject.new(Arguments, Parent) 39 | setmetatable(self,LabeledObject) 40 | self.Objects = {} 41 | self.TotalUsedScale = 0 42 | self.TotalUsedOffset = 0 43 | self.MainFrame = Instance.new("Frame", self.Parent) 44 | self.MainFrame.BackgroundTransparency = 1 45 | self.MainFrame.Name = "MainFrame" 46 | self.MainLayout = Instance.new("UIListLayout", self.MainFrame) 47 | self.MainLayout.HorizontalAlignment = Enum.HorizontalAlignment.Left 48 | self.MainLayout.SortOrder = Enum.SortOrder.LayoutOrder 49 | self.MainLayout.FillDirection = Enum.FillDirection.Horizontal 50 | self.MainPadding = Instance.new("UIPadding", self.MainFrame) 51 | self.MainPadding.PaddingBottom, self.MainPadding.PaddingLeft, self.MainPadding.PaddingRight, self.MainPadding.PaddingTop = UDim.new(0,2), UDim.new(0,6), UDim.new(0,0), UDim.new(0,2) 52 | local Textbox = self.Arguments.Textbox or self.Arguments.Text 53 | if type(Textbox) == "string" then 54 | self.TextboxTable = TextboxMod.new({Text = Textbox, Alignment = Enum.TextXAlignment.Left, TextSize = 14}, self.MainFrame) 55 | else 56 | self.TextboxTable = Textbox 57 | Textbox:Move(self.MainFrame, true) 58 | end 59 | self.Label = self.TextboxTable.Textbox 60 | self.Content = Instance.new("Frame", self.MainFrame) 61 | self.Content.Name = "Content" 62 | self.Content.BackgroundTransparency = 1 63 | local LabelSize = util.GetScale(self.Arguments.LabelSize) 64 | if LabelSize then 65 | self.Label.Size = UDim2.new(LabelSize.Scale, LabelSize.Offset, 0, 20) 66 | self.Content.Size = UDim2.new(1-LabelSize.Scale, -LabelSize.Offset, 0, 20) 67 | else 68 | local function sync() 69 | self.Label.Size = UDim2.new(0,self.Label.TextBounds.X+self.Label.TextSize, 1, 0) 70 | self.Content.Size = UDim2.new(1,-(self.Label.TextBounds.X+self.Label.TextSize), 0, 20) 71 | end 72 | self.Label.Changed:Connect(function(p) 73 | if p == "TextBounds" then sync() end 74 | end) 75 | end 76 | self.TotalUsedScale = 0 77 | local Objects = self.Arguments.Objects or self.Arguments.Object 78 | if type(Objects) == "table" and Objects[1] and type(Objects[1] == "table") then 79 | for _, v in pairs(Objects) do 80 | self:AddObject(v.Object, v.Name, v.Size) 81 | end 82 | else 83 | self:AddObject(Objects, "Object") 84 | end 85 | self:SetDisabled(self.Arguments.Disabled) 86 | self.MainMovable = self.MainFrame 87 | return self 88 | end 89 | 90 | return LabeledObject -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/Checkbox.lua: -------------------------------------------------------------------------------- 1 | local Checkbox = {} 2 | Checkbox.__index = Checkbox 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(Checkbox,GUIObject) 9 | 10 | Checkbox.Images = { 11 | check = "http://www.roblox.com/asset/?id=10278675078" 12 | } 13 | 14 | function Checkbox:SetDisabled(State) 15 | self.Disabled = State 16 | if self.Disabled then 17 | self.CursorIcon = "rbxasset://SystemCursors/Forbidden" 18 | self.Checkbox.Transparency, self.CheckImage.ImageTransparency = 0.5, 0.5 19 | else 20 | self.CursorIcon = "rbxasset://SystemCursors/PointingHand" 21 | self.Checkbox.Transparency, self.CheckImage.ImageTransparency = 0, 0 22 | end 23 | end 24 | 25 | function Checkbox:ToggleDisable() 26 | self:SetDisabled(not self.Disabled) 27 | end 28 | 29 | function Checkbox:Toggle() 30 | self:SetValue(not self.Value) 31 | return self.Value 32 | end 33 | 34 | function Checkbox:SetValue(Toggle) 35 | self.Value = Toggle 36 | self.CheckImage.Visible = Toggle 37 | if Toggle then 38 | ThemeManager.ColorSync(self.Checkbox, "BackgroundColor3", Enum.StudioStyleGuideColor.CheckedFieldBackground, Enum.StudioStyleGuideModifier.Selected, true, "Light") 39 | else 40 | ThemeManager.ColorSync(self.Checkbox, "BackgroundColor3", Enum.StudioStyleGuideColor.CheckedFieldBackground) 41 | end 42 | end 43 | 44 | function Checkbox:Clicked(func) 45 | self.Action = func 46 | end 47 | -- Value, Disabled 48 | function Checkbox.new(Arguments, Parent) 49 | local self = GUIObject.new(Arguments, Parent) 50 | setmetatable(self,Checkbox) 51 | self.Value = self.Arguments.Value 52 | self.Disabled = self.Arguments.Disabled 53 | self.CheckboxFrame = Instance.new("Frame", self.Parent) 54 | self.CheckboxFrame.BackgroundTransparency = 1 55 | self.CheckboxFrame.Name = "CheckboxFrame" 56 | self.Checkbox = Instance.new("TextButton", self.CheckboxFrame) 57 | self.Checkbox.BackgroundTransparency = 1 58 | self.Checkbox.AnchorPoint = Vector2.new(0.5,0.5) 59 | self.Checkbox.Position = UDim2.new(0.5,0,0.5,0) 60 | self.Checkbox.Size = UDim2.new(0,16,0,16) 61 | self.Checkbox.Name = "Checkbox" 62 | self.Checkbox.Text = "" 63 | ThemeManager.ColorSync(self.Checkbox, "BorderColor3", Enum.StudioStyleGuideColor.CheckedFieldBorder) 64 | ThemeManager.ColorSync(self.Checkbox, "BackgroundColor3", Enum.StudioStyleGuideColor.CheckedFieldBackground) 65 | self.CheckImage = Instance.new("ImageLabel", self.Checkbox) 66 | self.CheckImage.AnchorPoint = Vector2.new(0.5,0.5) 67 | self.CheckImage.Position = UDim2.new(0.5,0,0.5,0) 68 | self.CheckImage.Size = UDim2.new(0,16,0,16) 69 | self.CheckImage.Image = self.Images.check 70 | self.CheckImage.BackgroundTransparency = 1 71 | self.CheckImage.Name = "CheckIndicator" 72 | ThemeManager.ColorSync(self.CheckImage, "ImageColor3", Enum.StudioStyleGuideColor.CheckedFieldIndicator, nil, true, "Dark") 73 | self.Checkbox.MouseMoved:Connect(function() 74 | GV.PluginObject:GetMouse().Icon = self.CursorIcon 75 | if not self.Disabled then 76 | ThemeManager.ColorSync(self.Checkbox, "BorderColor3", Enum.StudioStyleGuideColor.CheckedFieldBorder, Enum.StudioStyleGuideModifier.Hover) 77 | end 78 | end) 79 | self.Checkbox.MouseLeave:Connect(function() 80 | task.wait(0) 81 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Arrow" 82 | ThemeManager.ColorSync(self.Checkbox, "BorderColor3", Enum.StudioStyleGuideColor.CheckedFieldBorder) 83 | end) 84 | self.Checkbox.MouseButton1Click:Connect(function() 85 | if not self.Disabled then 86 | self:Toggle() 87 | if self.Action then self.Action(self.Value) end 88 | end 89 | end) 90 | self:SetValue(self.Value) 91 | self:SetDisabled(self.Disabled) 92 | self.Object = self.Checkbox 93 | self.MainMovable = self.CheckboxFrame 94 | return self 95 | end 96 | 97 | return Checkbox -------------------------------------------------------------------------------- /src/rblxgui/lib/Prompts/TextPrompt.lua: -------------------------------------------------------------------------------- 1 | local TextPrompt = {} 2 | TextPrompt.__index = TextPrompt 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local Prompt = require(GV.PromptsDir.Prompt) 7 | local TextboxMod = require(GV.ObjectsDir.Textbox) 8 | local Button = require(GV.ObjectsDir.Button) 9 | setmetatable(TextPrompt, Prompt) 10 | 11 | function TextPrompt:Clicked(func) 12 | self.Action = func 13 | end 14 | 15 | -- Title, Textbox/Text, Buttons 16 | function TextPrompt.new(Arguments) 17 | local self = Prompt.new(Arguments) 18 | setmetatable(self,TextPrompt) 19 | local Buttons = self.Arguments.Buttons or {"OK"} 20 | self.TextPromptContainer = Instance.new("Frame", self.Parent) 21 | self.TextPromptContainer.BackgroundTransparency = 1 22 | self.TextPromptContainer.BorderSizePixel = 0 23 | self.TextPromptContainer.Size = UDim2.new(0,self.Parent.AbsoluteSize.X,0,self.Parent.AbsoluteSize.Y) 24 | self.TextPromptContainer.Name = "TextPromptContainer" 25 | self.TextPromptLayout = Instance.new("UIListLayout", self.TextPromptContainer) 26 | self.TextPromptLayout.SortOrder = Enum.SortOrder.LayoutOrder 27 | self.TextFrame = Instance.new("Frame", self.TextPromptContainer) 28 | self.TextFrame.Name = "TextFrame" 29 | self.TextFrame.Size = UDim2.new(0,0,0,35) 30 | self.TextFrame.BackgroundTransparency = 1 31 | self.TextFrame.BorderSizePixel = 0 32 | self.TextboxTable = self.Arguments.Textbox or self.Arguments.Text 33 | if type(self.TextboxTable) == "string" or not self.TextboxTable then 34 | self.TextboxTable = TextboxMod.new({Text = self.TextboxTable or ""}, self.TextFrame) 35 | else 36 | self.TextboxTable:Move(self.TextFrame, true) 37 | end 38 | self.TextboxTable.Arguments.Unpausable = true 39 | self.Textbox = self.TextboxTable.Textbox 40 | self.Textbox.ZIndex = 1 41 | self.Textbox.TextXAlignment = Enum.TextXAlignment.Left 42 | self.Textbox.AnchorPoint = Vector2.new(0.5,0.5) 43 | self.Textbox.Position = UDim2.new(0.5,0,0.6,0) 44 | self.Textbox.Size = UDim2.new(1,-24,0,14) 45 | self.ButtonsFrame = Instance.new("Frame", self.TextPromptContainer) 46 | self.ButtonsFrame.Name = "ButtonsFrame" 47 | self.ButtonsFrame.Size = UDim2.new(1,0,0,40) 48 | self.ButtonsFrame.BackgroundTransparency = 1 49 | self.ButtonsFrame.BorderSizePixel = 0 50 | local ButtonsFramePadding = Instance.new("UIPadding", self.ButtonsFrame) 51 | ButtonsFramePadding.PaddingBottom, ButtonsFramePadding.PaddingLeft, ButtonsFramePadding.PaddingRight, ButtonsFramePadding.PaddingTop = UDim.new(0,7), UDim.new(0,7), UDim.new(0,7), UDim.new(0,7) 52 | self.ButtonsFrameLayout = Instance.new("UIListLayout", self.ButtonsFrame) 53 | self.ButtonsFrameLayout.FillDirection = Enum.FillDirection.Horizontal 54 | self.ButtonsFrameLayout.HorizontalAlignment = Enum.HorizontalAlignment.Right 55 | self.ButtonsFrameLayout.SortOrder = Enum.SortOrder.LayoutOrder 56 | self:OnWindowClose(function() 57 | self:Destroy() 58 | if self.Action then self.Action(0) end 59 | end) 60 | if (#Buttons*82)+14 > 260 then 61 | self.ButtonsFrame.Size = UDim2.new(0,(#Buttons*82)+14,0,40) 62 | end 63 | for i,v in pairs(Buttons) do 64 | local NewButton = v 65 | if type(v) == "string" then 66 | NewButton = Button.new({Text = v, ButtonSize = 0.95}, self.ButtonsFrame) 67 | else 68 | NewButton:Move(self.ButtonsFrame, true) 69 | end 70 | NewButton.Arguments.Unpausable = true 71 | NewButton.ButtonFrame.Size = UDim2.new(0,82,1,0) 72 | NewButton:Clicked(function() 73 | self:Destroy() 74 | if self.Action then self.Action(i) end 75 | end) 76 | end 77 | local function syncTextFrame() 78 | self.TextFrame.Size = UDim2.new(0,self.Textbox.TextBounds.X+24,0,self.Textbox.TextBounds.Y+21) 79 | end 80 | syncTextFrame() 81 | self.Textbox.Changed:Connect(function(p) 82 | if p == "TextBounds" then 83 | syncTextFrame() 84 | end 85 | end) 86 | local function syncTextPromptSize() 87 | self:Reset(self.Arguments.Title, self.TextPromptLayout.AbsoluteContentSize.X, self.TextPromptLayout.AbsoluteContentSize.Y) 88 | self.TextPromptContainer.Size = UDim2.fromOffset(self.TextPromptLayout.AbsoluteContentSize.X, self.TextPromptLayout.AbsoluteContentSize.Y) 89 | self.TextPromptContainer.Parent = self.Parent 90 | end 91 | syncTextPromptSize() 92 | self.TextPromptLayout.Changed:Connect(function(p) 93 | if p == "AbsoluteContentSize" then 94 | syncTextPromptSize() 95 | end 96 | end) 97 | return self 98 | end 99 | 100 | return TextPrompt -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/Section.lua: -------------------------------------------------------------------------------- 1 | local Section = {} 2 | Section.__index = Section 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIFrame = require(GV.FramesDir.GUIFrame) 7 | local TextboxMod = require(GV.ObjectsDir.Textbox) 8 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 9 | setmetatable(Section,GUIFrame) 10 | 11 | Section.Images = { 12 | Open = "http://www.roblox.com/asset/?id=9666389442", 13 | Closed = "http://www.roblox.com/asset/?id=9666389853" 14 | } 15 | 16 | function Section:SetState(State) 17 | self.Open = State 18 | self.Content.Visible = self.Open 19 | if self.Open then self.CollapseImage.Image = self.Images.Open else self.CollapseImage.Image = self.Images.Closed end 20 | end 21 | 22 | function Section:Toggle() 23 | self:SetState(not self.Open) 24 | end 25 | 26 | -- Text, Open 27 | function Section.new(Arguments, Parent) 28 | local self = GUIFrame.new(Arguments, Parent) 29 | setmetatable(self, Section) 30 | self.Open = self.Arguments.Open 31 | 32 | self.Collapse = Instance.new("Frame", self.Parent) 33 | self.Collapse.BackgroundTransparency = 1 34 | self.Collapse.Size = UDim2.new(1,0,0,0) 35 | self.Collapse.AutomaticSize = Enum.AutomaticSize.Y 36 | 37 | self.CollapseLayout = Instance.new("UIListLayout", self.Collapse) 38 | self.CollapseLayout.SortOrder = Enum.SortOrder.LayoutOrder 39 | self.CollapseLayout.FillDirection = Enum.FillDirection.Vertical 40 | self.CollapseLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center 41 | --self.CollapseLayout.Padding = UDim.new(0,5) 42 | 43 | self.Label = Instance.new("TextButton", self.Collapse) 44 | self.Label.Text = "" 45 | self.Label.Name = "Section Label" 46 | self.Label.Size = UDim2.new(2,0,0,25) 47 | self.Label.BorderSizePixel = 0 48 | ThemeManager.ColorSync(self.Label, "BackgroundColor3", Enum.StudioStyleGuideColor.Titlebar) 49 | self.Label.MouseButton1Click:Connect(function() self:Toggle() end) 50 | util.HoverIcon(self.Label, "rbxasset://SystemCursors/PointingHand") 51 | 52 | self.LabelFrame = Instance.new("Frame", self.Label) 53 | self.LabelFrame.AnchorPoint = Vector2.new(0.5,0) 54 | self.LabelFrame.Position = UDim2.new(0.5,0,0,0) 55 | self.LabelFrame.Size = UDim2.new(0.5,0,0,25) 56 | self.LabelFrame.BackgroundTransparency = 1 57 | 58 | self.LabelLayout = Instance.new("UIListLayout", self.LabelFrame) 59 | self.LabelLayout.SortOrder = Enum.SortOrder.LayoutOrder 60 | self.LabelLayout.FillDirection = Enum.FillDirection.Horizontal 61 | 62 | self.CollapseImageFrame = Instance.new("Frame", self.LabelFrame) 63 | self.CollapseImageFrame.Size = UDim2.new(0,25,0,25) 64 | self.CollapseImageFrame.BackgroundTransparency = 1 65 | 66 | self.CollapseTextboxFrame = Instance.new("Frame", self.LabelFrame) 67 | self.CollapseTextboxFrame.Size = UDim2.new(1,-25,0,25) 68 | self.CollapseTextboxFrame.BackgroundTransparency = 1 69 | 70 | self.CollapseImage = Instance.new("ImageLabel", self.CollapseImageFrame) 71 | self.CollapseImage.BackgroundTransparency = 1 72 | self.CollapseImage.AnchorPoint = Vector2.new(0.5,0.5) 73 | self.CollapseImage.Position = UDim2.new(0.5,0,0.5,0) 74 | self.CollapseImage.Size = UDim2.new(0,15,0,15) 75 | ThemeManager.ColorSync(self.CollapseImage, "ImageColor3", Enum.StudioStyleGuideColor.MainText) 76 | 77 | local Textbox = self.Arguments.Textbox or self.Arguments.Text 78 | if type(Textbox) == "string" then 79 | self.TextboxTable = TextboxMod.new({Text = Textbox, Font = Enum.Font.SourceSansBold, Alignment = Enum.TextXAlignment.Left, TextSize = 15}, self.CollapseTextboxFrame) 80 | else 81 | self.TextboxTable = Textbox 82 | Textbox:Move(self.CollapseTextboxFrame, true) 83 | end 84 | self.TextboxTable.Arguments.Unpausable = true 85 | self.Textbox = self.TextboxTable.Textbox 86 | self.Collapse.Name = "Section - " .. self.Textbox.Text 87 | self.Textbox.AnchorPoint = Vector2.new(0,0.5) 88 | self.Textbox.Position = UDim2.new(0,0,0.5,0) 89 | 90 | self.Content = Instance.new("Frame", self.Collapse) 91 | self.Content.Size = UDim2.new(1,-15,0,0) 92 | self.Content.BackgroundTransparency = 1 93 | self.Content.Visible = self.Open 94 | self.Content.Name = "Contents" 95 | 96 | self.Layout = Instance.new("UIListLayout", self.Content) 97 | self.Layout.SortOrder = Enum.SortOrder.LayoutOrder 98 | self.Layout.HorizontalAlignment = Enum.HorizontalAlignment.Center 99 | self:SetState(self.Arguments.Open) 100 | 101 | local function syncContentSize() 102 | self.Content.Size = UDim2.new(1, -15, 0, self.Layout.AbsoluteContentSize.Y); 103 | end 104 | syncContentSize() 105 | self.Layout.Changed:Connect(function(p) 106 | if p == "AbsoluteContentSize" then 107 | syncContentSize() 108 | end 109 | end) 110 | 111 | return self 112 | end 113 | 114 | return Section -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/KeybindInputField.lua: -------------------------------------------------------------------------------- 1 | local KeybindInputField = {} 2 | KeybindInputField.__index = KeybindInputField 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local KeybindManager = require(GV.ManagersDir.KeybindManager) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | local InputField = require(GV.ObjectsDir.InputField) 9 | local KeybindNum = 0 10 | setmetatable(KeybindInputField,InputField) 11 | 12 | --[[ 13 | How to make keybinds in code 14 | Always use Left if its control alt or shift 15 | ex: 16 | {{LeftControl, LeftAlt, Zero},{P}} 17 | {{"Keybind Preset",{{LeftControl, LeftAlt, Zero},{P}}}} 18 | ]]-- 19 | 20 | function KeybindInputField:UpdateValues(Value) 21 | Value = Value or self.Value 22 | KeybindManager.UpdateKeybinds(self.ID, {Keybinds = Value, Holdable = self.Holdable, PressedAction = self.PressedAction, ReleasedAction = self.ReleasedAction}) 23 | end 24 | 25 | function KeybindInputField:UpdateBind(Value) 26 | if not Value then return end 27 | if #Value[1]>0 and #Value[#Value]>0 then Value[#Value + 1] = {} end 28 | self:UpdateValues(Value) 29 | end 30 | 31 | function KeybindInputField:SetBind(Bind) 32 | Bind = Bind or {Value = {{}}} 33 | local BindInfo = self.GetItemInfo(Bind) 34 | local Value = BindInfo.Value 35 | self:UpdateBind(Value) 36 | self:SetValue({Name = BindInfo.Name or KeybindManager.GenerateKeybindList(Value), ["Value"] = Value}) 37 | end 38 | 39 | function KeybindInputField:AddBind(Bind) 40 | local BindInfo = self.GetItemInfo(Bind) 41 | if #BindInfo.Value[1]>0 and #BindInfo.Value[#BindInfo.Value]>0 then BindInfo.Value[#BindInfo.Value+1] = {} end 42 | self:AddItem({Name = BindInfo.Name or KeybindManager.GenerateKeybindList(BindInfo.Value), Value = BindInfo.Value}, function() self:UpdateBind(BindInfo.Value) end) 43 | end 44 | 45 | function KeybindInputField:AddBinds(Binds) 46 | for _, Bind in pairs(Binds) do 47 | self:AddBind(Bind) 48 | end 49 | end 50 | 51 | function KeybindInputField:EditKeybind(Keybind, Complete) 52 | local Value = util.CopyTable(self.Value) 53 | Value[#Value] = Keybind 54 | if Complete then 55 | Value[#Value+1] = {} 56 | end 57 | self:UpdateValues(Value) 58 | self:SetValue({Name = KeybindManager.GenerateKeybindList(Value), ["Value"] = Value}) 59 | end 60 | 61 | function KeybindInputField:RemoveKeybind(Index) 62 | local Value = util.CopyTable(self.Value) 63 | Index = Index or #Value - 1 64 | table.remove(Value, Index) 65 | self:SetValue({Name = KeybindManager.GenerateKeybindList(Value), ["Value"] = Value}) 66 | end 67 | 68 | function KeybindInputField:UnfocusInputField(ForceUnfocus) 69 | if not ForceUnfocus and self.MouseInInput then return false 70 | else 71 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 72 | self.Focused = false 73 | end 74 | return true 75 | end 76 | 77 | function KeybindInputField:Pressed(func) 78 | function self.PressedAction() 79 | if not self.Disabled and func then func() end 80 | end 81 | self:UpdateValues() 82 | end 83 | 84 | function KeybindInputField:Released(func) 85 | function self.ReleasedAction() 86 | if not self.Disabled and func then func() end 87 | end 88 | self:UpdateValues() 89 | end 90 | 91 | -- PressedAction, ReleasedAction, Holdable, Unrestricted, Bind/CurrentBind, Items/Binds 92 | function KeybindInputField.new(Arguments, Parent) 93 | Arguments = Arguments or {} 94 | KeybindNum += 1 95 | Arguments.Placeholder = Arguments.Placeholder or "Set Keybind" 96 | Arguments.DisableEditing = true 97 | local self = InputField.new(Arguments, Parent) 98 | setmetatable(self,KeybindInputField) 99 | self.IgnoreText = true 100 | self.Holdable = self.Arguments.Holdable 101 | self.Unrestricted = self.Arguments.Unrestricted 102 | if not self.Holdable then self.Holdable = false end 103 | if not self.Unrestricted then self.Unrestricted = false end 104 | self.DefaultEmpty = {{}} 105 | self.TextEditable = true 106 | self.ID = KeybindNum 107 | self:Pressed(self.Arguments.PressedAction) 108 | self:Released(self.Arguments.ReleasedAction) 109 | self.Value = {{}} 110 | self.Arguments.Binds = self.Arguments.Items or self.Arguments.Binds 111 | self.Input.Focused:Connect(function() 112 | if self.Disabled then return end 113 | self.Focused = true 114 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder, Enum.StudioStyleGuideModifier.Selected, true) 115 | task.wait() 116 | KeybindManager.FocusInputField(self.ID, self, self.EditKeybind, self.RemoveKeybind, self.UnfocusInputField) 117 | end) 118 | if self.Arguments.Binds then self:AddBinds(self.Arguments.Binds) end 119 | self:SetBind(self.Arguments.Bind or self.Arguments.CurrentBind) 120 | return self 121 | end 122 | 123 | return KeybindInputField -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/Slider.lua: -------------------------------------------------------------------------------- 1 | local Slider = {} 2 | Slider.__index = Slider 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | local InputManager = require(GV.ManagersDir.InputManager) 8 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 9 | setmetatable(Slider,GUIObject) 10 | 11 | function Slider:SetDisabled(State) 12 | self.Disabled = State 13 | self.SliderSelected = false 14 | if self.Disabled then 15 | self.CursorIcon = "rbxasset://SystemCursors/Forbidden" 16 | self.SlideBar.BackgroundTransparency, self.SlideButton.BackgroundTransparency = 0.5, 0.5 17 | else 18 | self.CursorIcon = "rbxasset://SystemCursors/PointingHand" 19 | self.SlideBar.BackgroundTransparency, self.SlideButton.BackgroundTransparency = 0, 0 20 | end 21 | end 22 | 23 | function Slider:SetValue(Value) 24 | self.Value = Value 25 | self:UpdatePosition() 26 | end 27 | 28 | function Slider:SetRange(Min, Max) 29 | self.Min = Min 30 | self.Max = Max 31 | self:UpdatePosition() 32 | end 33 | 34 | function Slider:UpdatePosition() 35 | self.SlideButton.Position = UDim2.new((self.Value-self.Min)/(self.Max - self.Min), 0, 0.5, 0) 36 | if self.Value ~= self.PreviousValue then 37 | self.PreviousValue = self.Value 38 | if self.Action then self.Action(self.Value) end 39 | end 40 | end 41 | 42 | function Slider:ToggleDisable() 43 | self:SetDisabled(not self.Disabled) 44 | end 45 | 46 | function Slider:Changed(func) 47 | self.Action = func 48 | end 49 | 50 | function Slider:Pressed(func) 51 | self.PressedAction = func 52 | end 53 | 54 | function Slider:Released(func) 55 | self.ReleasedAction = func 56 | end 57 | 58 | -- Min, Max, Value, Increment, SliderSize, Disabled 59 | function Slider.new(Arguments, Parent) 60 | local self = GUIObject.new(Arguments, Parent) 61 | setmetatable(self,Slider) 62 | self.Increment = self.Arguments.Increment or 0 63 | self.Value = self.Arguments.Value or self.Arguments.Min 64 | self.Min = self.Arguments.Min 65 | self.Max = self.Arguments.Max 66 | self.SliderFrame = Instance.new("Frame", self.Parent) 67 | self.SliderFrame.BackgroundTransparency = 1 68 | self.SlideBar = Instance.new("Frame", self.SliderFrame) 69 | self.SlideBar.AnchorPoint = Vector2.new(0.5,0.5) 70 | self.SlideBar.Position = UDim2.new(0.5,0,0.5,0) 71 | local Size = util.GetScale(self.Arguments.SliderSize) or UDim.new(1,-12) 72 | self.SlideBar.Size = UDim2.new(Size.Scale, Size.Offset, 0, 5) 73 | ThemeManager.ColorSync(self.SlideBar, "BackgroundColor3", Enum.StudioStyleGuideColor.FilterButtonAccent) 74 | self.SlideButton = Instance.new("TextButton", self.SlideBar) 75 | self.SlideButton.Text = "" 76 | self.SlideButton.BorderSizePixel = 1 77 | self.SlideButton.AnchorPoint = Vector2.new(0.5,0.5) 78 | self:UpdatePosition() 79 | self.SlideButton.Size = UDim2.new(0,7,0,18) 80 | ThemeManager.ColorSync(self.SlideButton, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 81 | ThemeManager.ColorSync(self.SlideButton, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 82 | self.SlideBar.BorderSizePixel = 0 83 | self.SliderSelected = false 84 | self.InitialX = 0 85 | self.SlideButton.MouseButton1Down:Connect(function(x) 86 | if self.PressedAction then self.PressedAction() end 87 | if self.Disabled then return end 88 | self.SliderSelected = true 89 | self.InitialX = self.SlideButton.AbsolutePosition.X - x 90 | end) 91 | self.SlideButton.MouseButton1Up:Connect(function() 92 | if self.ReleasedAction then self.ReleasedAction() end 93 | end) 94 | self.PreviousValue = self.Value 95 | InputManager.AddInputEvent("MouseMoved", function(x) 96 | if not self.SliderSelected then return end 97 | self.Value = util.RoundNumber(math.clamp((x + self.InitialX - self.SlideBar.AbsolutePosition.X + self.SlideButton.Size.X.Offset / 2)/self.SlideBar.AbsoluteSize.X, 0, 1) * (self.Max - self.Min) + self.Min, self.Increment) 98 | self:UpdatePosition() 99 | end) 100 | InputManager.AddInputEvent("InputEnded", function(p) 101 | if self.SliderSelected and p.UserInputType == Enum.UserInputType.MouseButton1 then 102 | self.SliderSelected = false 103 | if self.ReleasedAction then self.ReleasedAction() end 104 | end 105 | end) 106 | InputManager.AddInputEvent("MouseLeave", function() 107 | if self.SliderSelected and self.ReleasedAction then self.ReleasedAction() end 108 | self.SliderSelected = false 109 | end) 110 | self.SlideButton.MouseMoved:Connect(function() 111 | GV.PluginObject:GetMouse().Icon = self.CursorIcon 112 | end) 113 | self.SlideButton.MouseLeave:Connect(function() 114 | task.wait(0) 115 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Arrow" 116 | end) 117 | self:SetDisabled(self.Arguments.Disabled) 118 | self.Object = self.SlideButton 119 | self.MainMovable = self.SliderFrame 120 | return self 121 | end 122 | 123 | return Slider -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/ColorInput.lua: -------------------------------------------------------------------------------- 1 | local ColorInput = {} 2 | ColorInput.__index = ColorInput 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | local InputField = require(GV.ObjectsDir.InputField) 8 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 9 | local ColorPrompt = require(GV.PromptsDir.ColorPrompt) 10 | setmetatable(ColorInput,GUIObject) 11 | 12 | local RightClickMenu = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "RightClickMenu - ColorInput") 13 | RightClickMenu.Name = "ColorInput Right-Click Menu" 14 | RightClickMenu:AddNewAction("Reset", "Reset") 15 | 16 | function ColorInput:SetDisabled(State) 17 | self.Disabled = State 18 | self.ColorInput:SetDisabled(State) 19 | if self.Disabled then 20 | self.CursorIcon = "rbxasset://SystemCursors/Forbidden" 21 | self.ColorButton.BackgroundTransparency = 0.5 22 | else 23 | self.CursorIcon = "rbxasset://SystemCursors/PointingHand" 24 | self.ColorButton.BackgroundTransparency = 0 25 | end 26 | end 27 | 28 | function ColorInput:ToggleDisable() 29 | self:SetDisabled(not self.Disabled) 30 | end 31 | 32 | function ColorInput:SetValue(Value, IgnoreText) 33 | self.Value = Value 34 | self.ColorButton.BackgroundColor3 = self.Value 35 | if not IgnoreText then self.ColorInput.Input.Text = util.Color3ToText(self.Value) end 36 | if self.Action then self.Action(self.Value) end 37 | end 38 | 39 | function ColorInput:Changed(func) 40 | self.Action = func 41 | end 42 | 43 | -- Color/Value/DefaultColor, NoPause, Disabled 44 | function ColorInput.new(Arguments, Parent) 45 | local self = GUIObject.new(Arguments, Parent) 46 | setmetatable(self,ColorInput) 47 | self.IgnoreText = true 48 | self.Disabled = self.Arguments.Disabled 49 | self.ColorInputContainer = Instance.new("Frame", self.Parent) 50 | self.ColorInputContainer.BackgroundTransparency = 1 51 | self.ColorInputContainer.Name = "ColorInputContainer" 52 | self.ColorInputFrame = Instance.new("Frame", self.ColorInputContainer) 53 | self.ColorInputFrame.Name = "ColorInputFrame" 54 | self.ColorInputFrame.AnchorPoint = Vector2.new(0.5,0.5) 55 | self.ColorInputFrame.BackgroundTransparency = 1 56 | self.ColorInputFrame.Position = UDim2.new(0.5,0,0.5,0) 57 | self.ColorInputFrame.Size = UDim2.new(0,130,1,0) 58 | self.ColorInputLayout = Instance.new("UIListLayout", self.ColorInputFrame) 59 | self.ColorInputLayout.Padding = UDim.new(0,10) 60 | self.ColorInputLayout.FillDirection = Enum.FillDirection.Horizontal 61 | self.ColorInputLayout.SortOrder = Enum.SortOrder.LayoutOrder 62 | self.ColorInputLayout.VerticalAlignment = Enum.VerticalAlignment.Center 63 | self.ColorButton = Instance.new("TextButton", self.ColorInputFrame) 64 | self.ColorButton.Name = "ColorButton" 65 | self.ColorButton.Size = UDim2.new(0,18,0,18) 66 | ThemeManager.ColorSync(self.ColorButton, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 67 | self.ColorButton.Text = "" 68 | self.ColorButton.MouseButton1Click:Connect(function() 69 | if self.Disabled then return end 70 | local prompt = ColorPrompt.new({Value = self.Value, NoPause = self.Arguments.NoPause}) 71 | prompt:Done(function(p) 72 | self:SetValue(p) 73 | end) 74 | prompt:Changed(function(p) 75 | self:SetValue(p) 76 | end) 77 | end) 78 | self.ColorButton.MouseButton2Click:Connect(function() 79 | if self.Disabled then return end 80 | local Response = RightClickMenu:ShowAsync() 81 | if Response then 82 | if Response.Text == "Reset" then self:SetValue(self.DefaultValue) end 83 | end 84 | end) 85 | self.ColorInput = InputField.new({NoDropdown = true, ClearBackground = true}, self.ColorInputFrame) 86 | self.ColorInput.Name = "ColorInput" 87 | self.ColorInput.InputFieldContainer.Size = UDim2.new(0,100,0,20) 88 | self.ColorInput.InputFieldFrame.Size = UDim2.new(1,0,1,0) 89 | self.ColorInput.Input.TextXAlignment = Enum.TextXAlignment.Center 90 | self.ColorInput:Changed(function(p) 91 | self:SetValue(util.TextToColor3(p), true) 92 | end) 93 | self.ColorInput:LostFocus(function(p) 94 | self:SetValue(util.TextToColor3(p)) 95 | self.ColorInput.Input.TextXAlignment = Enum.TextXAlignment.Center 96 | end) 97 | self.ColorInput:GainedFocus(function() 98 | self.ColorInput.Input.TextXAlignment = Enum.TextXAlignment.Left 99 | end) 100 | self.ColorButton.MouseMoved:Connect(function() 101 | GV.PluginObject:GetMouse().Icon = self.CursorIcon 102 | end) 103 | self.ColorButton.MouseLeave:Connect(function() 104 | task.wait(0) 105 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Arrow" 106 | end) 107 | self.DefaultValue = self.Arguments.Color or self.Arguments.Value or Color3.new(1,1,1) 108 | self:SetValue(self.DefaultValue) 109 | self:SetDisabled(self.Disabled) 110 | self.Object = self.ColorButton 111 | self.MainMovable = self.ColorInputContainer 112 | return self 113 | end 114 | 115 | return ColorInput -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/PluginWidget.lua: -------------------------------------------------------------------------------- 1 | local GuiService = game:GetService("GuiService") 2 | local Widget = {} 3 | Widget.__index = Widget 4 | 5 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 6 | local plugin = GV.PluginObject 7 | local util = require(GV.MiscDir.GUIUtil) 8 | local InputManager = require(GV.ManagersDir.InputManager) 9 | local GUIFrame = require(GV.FramesDir.GUIFrame) 10 | local TitlebarMenu = require(GV.FramesDir.TitlebarMenu) 11 | local InputField = require(GV.ObjectsDir.InputField) 12 | local TextPrompt = require(GV.PromptsDir.TextPrompt) 13 | local InputPrompt = require(GV.PromptsDir.InputPrompt) 14 | local BackgroundFrame = require(GV.FramesDir.BackgroundFrame) 15 | setmetatable(Widget,GUIFrame) 16 | GV.PluginWidgets = {} 17 | local Unnamed = 0 18 | 19 | function Widget:Delete() 20 | local WidgetTitle = self.WidgetObject.Title 21 | local DeletePrompt = TextPrompt.new({Title = "Delete " .. WidgetTitle, Text = 'Are you sure you want to delete "' .. WidgetTitle .. '"?', Buttons = {"Yes", "No"}}) 22 | DeletePrompt:Clicked(function(p) 23 | if p == 2 or p == 0 then return end 24 | if self.TitlebarMenu and #self.TitlebarMenu.Pages > 0 then 25 | local AvailibleWidgets = {} 26 | for _,v in pairs(GV.PluginWidgets)do 27 | if v.TitlebarMenu and v.WidgetObject.Title ~= WidgetTitle then AvailibleWidgets[#AvailibleWidgets+1] = {Name = v.WidgetObject.Title, Value = v} end 28 | end 29 | if #AvailibleWidgets < 1 then return end 30 | local TransferPrompt = InputPrompt.new({Title = "Transfer Pages", Text = "Where would you like to move the pages?", Buttons = {"OK", "Cancel"}, InputField = InputField.new({Value = AvailibleWidgets[1], Items = AvailibleWidgets, DisableEditing = true, NoFiltering = true, Unpausable = true})}) 31 | TransferPrompt:Clicked(function(p2) 32 | if p2 == 2 then return end 33 | local NewWidget = TransferPrompt.InputField.Value 34 | if NewWidget == "" then return end 35 | for _, v in pairs(self.TitlebarMenu.Pages) do 36 | NewWidget.TitlebarMenu:RecievePage(v) 37 | end 38 | self.WidgetObject:Destroy() 39 | table.remove(GV.PluginWidgets, self.Index) 40 | self = nil 41 | end) 42 | util.DumpGUI(TransferPrompt.Widget) 43 | else 44 | self.WidgetObject:Destroy() 45 | table.remove(GV.PluginWidgets, self.Index) 46 | self = nil 47 | end 48 | end) 49 | end 50 | 51 | function Widget:Rename() 52 | local NewTitlePrompt = InputPrompt.new({Title = "Rename " .. self.WidgetObject.Title, Text = "Type in a new name:", Buttons = {"OK", "Cancel"}, InputField = InputField.new({Placeholder = "New name", Text = self.WidgetObject.Title, NoDropdown = true, Unpausable = true})}) 53 | NewTitlePrompt:Clicked(function(p) 54 | if p == 2 then return end 55 | self.WidgetObject.Title = NewTitlePrompt.Input.Text 56 | end) 57 | end 58 | 59 | -- ID, Title, Enabled, NoTitlebarMenu, DockState, OverrideRestore 60 | function Widget.new(Arguments) 61 | local self = GUIFrame.new(Arguments) 62 | setmetatable(self, Widget) 63 | self.ID = self.Arguments.ID or game:GetService("HttpService"):GenerateGUID(false) 64 | local title = self.Arguments.Title 65 | if not title then 66 | title = self.Arguments.ID 67 | if not title then 68 | Unnamed += 1 69 | title = "Unnamed #" .. tostring(Unnamed) 70 | end 71 | end 72 | self.Arguments.DockState = self.Arguments.DockState or Enum.InitialDockState.Float 73 | -- really dumb but its gotta be a boolean 74 | if not self.Arguments.Enabled then self.Arguments.Enabled = false end 75 | if not self.Arguments.OverrideRestore then self.Arguments.OverrideRestore = false end 76 | self.WidgetObject = plugin:CreateDockWidgetPluginGui(self.ID, DockWidgetPluginGuiInfo.new(self.Arguments.DockState, self.Arguments.Enabled, self.Arguments.OverrideRestore, 300, 500, 50, 50)) 77 | self.WidgetObject.Title = title 78 | self.BackgroundFrame = BackgroundFrame.new(nil, self.WidgetObject) 79 | self.InputFrame = Instance.new("Frame", self.WidgetObject) 80 | self.InputFrame.BackgroundTransparency = 1 81 | self.InputFrame.Size = UDim2.new(1,0,1,0) 82 | self.InputFrame.ZIndex = 100 83 | self.InputFrame.Name = "InputFrame" 84 | local FixPosition = false 85 | local FixPage = nil 86 | self.InputFrame.MouseMoved:Connect(function() 87 | if not FixPosition then return end 88 | FixPosition = false 89 | local MousePos = self.WidgetObject:GetRelativeMousePosition() 90 | FixPage.TabFrame.Position = UDim2.new(0,MousePos.X + FixPage.InitialX + self.TitlebarMenu.ScrollingMenu.CanvasPosition.X, 0,0) 91 | self.TitlebarMenu:BeingDragged(FixPage.ID) 92 | self.TitlebarMenu:FixPageLayout() 93 | end) 94 | InputManager.AddInput(self.InputFrame) 95 | if not self.Arguments.NoTitlebarMenu then self.TitlebarMenu = TitlebarMenu.new({ID = self.ID}, self.WidgetObject) end 96 | self.WidgetObject.PluginDragDropped:Connect(function() 97 | if(GV.SelectedPage and self.TitlebarMenu) then 98 | self.TitlebarMenu:RecievePage(GV.SelectedPage) 99 | FixPosition = true 100 | FixPage = GV.SelectedPage 101 | self.TitlebarMenu:SetActive(GV.SelectedPage.ID) 102 | GV.SelectedPage = nil 103 | end 104 | end) 105 | for _, v in pairs(GV.TitleBarButtons) do 106 | v:CreateCopy(self.TitlebarMenu) 107 | end 108 | self.Parent = self.WidgetObject 109 | self.Content = self.WidgetObject 110 | self.Index = #GV.PluginWidgets+1 111 | GV.PluginWidgets[self.Index] = self 112 | return self 113 | end 114 | 115 | return Widget -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/Button.lua: -------------------------------------------------------------------------------- 1 | local Button = {} 2 | Button.__index = Button 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 7 | local TextboxMod = require(GV.ObjectsDir.Textbox) 8 | local GUIObject = require(GV.ObjectsDir.GUIObject) 9 | setmetatable(Button,GUIObject) 10 | 11 | Button.Images = { 12 | border = "http://www.roblox.com/asset/?id=10460485555", 13 | bg = "http://www.roblox.com/asset/?id=10460051857", 14 | selected = "http://www.roblox.com/asset/?id=10460676787" 15 | } 16 | 17 | function Button:SetDisabled(State) 18 | self.Disabled = State 19 | if self.Disabled then 20 | self.CursorIcon = "rbxasset://SystemCursors/Forbidden" 21 | self.Button.ImageTransparency, self.Textbox.TextTransparency = 0.5, 0.5 22 | else 23 | self.CursorIcon = "rbxasset://SystemCursors/PointingHand" 24 | self.Button.ImageTransparency, self.Textbox.TextTransparency = 0, 0 25 | end 26 | end 27 | 28 | function Button:ToggleDisable() 29 | self:SetDisabled(not self.Disabled) 30 | end 31 | 32 | function Button:Clicked(func) 33 | self.Action = func 34 | end 35 | 36 | function Button:Pressed(func) 37 | self.PressedAction = func 38 | end 39 | 40 | function Button:Released(func) 41 | self.ReleasedAction = func 42 | end 43 | 44 | -- Text/Textbox, ButtonSize, Disabled 45 | function Button.new(Arguments, Parent) 46 | local self = GUIObject.new(Arguments, Parent) 47 | setmetatable(self,Button) 48 | self.TextboxTable = nil 49 | -- creating a frame to hold the button 50 | self.ButtonFrame = Instance.new("Frame", self.Parent) 51 | self.ButtonFrame.BackgroundTransparency = 1 52 | self.ButtonFrame.Name = "ButtonFrame" 53 | self.ButtonFrame.Size = UDim2.new(1,0,1,0) 54 | 55 | self.Button = Instance.new("ImageButton", self.ButtonFrame) 56 | 57 | -- set up a textbox for the button 58 | local Textbox = self.Arguments.Textbox or self.Arguments.Text 59 | if type(Textbox) == "string" then 60 | self.TextboxTable = TextboxMod.new({Text = Textbox}, self.Button) 61 | else 62 | self.TextboxTable = Textbox 63 | Textbox:Move(self.Button, true) 64 | end 65 | self.Textbox = self.TextboxTable.Textbox 66 | self.Textbox.ZIndex = 1 67 | 68 | local Size = util.GetScale(self.Arguments.ButtonSize) 69 | if Size then self.Button.Size = UDim2.new(Size.Scale,Size.Offset,1,0) 70 | else 71 | local function sync() 72 | self.Button.Size = UDim2.new(0,self.Textbox.TextBounds.X+1.5*self.Textbox.TextSize, 1, 0) 73 | end 74 | self.Textbox.Changed:Connect(function(p) 75 | if p == "TextBounds" then sync() end 76 | end) 77 | end 78 | self.Button.Position = UDim2.new(0.5, 0, 0, 0) 79 | self.Button.AnchorPoint = Vector2.new(0.5,0) 80 | self.Button.BackgroundTransparency = 1 81 | self.Button.Image = self.Images.border 82 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.DialogButtonBorder) 83 | self.Button.ScaleType = Enum.ScaleType.Slice 84 | self.Button.SliceCenter = Rect.new(7,7,156,36) 85 | self.Button.Name = "Button" 86 | 87 | self.ButtonBackground = Instance.new("ImageLabel", self.Button) 88 | self.ButtonBackground.Name = "ButtonBackground" 89 | self.ButtonBackground.BackgroundTransparency = 1 90 | self.ButtonBackground.Size = UDim2.new(1,0,1,0) 91 | self.ButtonBackground.Image = self.Images.bg 92 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button) 93 | self.ButtonBackground.ScaleType = Enum.ScaleType.Slice 94 | self.ButtonBackground.SliceCenter = Rect.new(7,7,156,36) 95 | self.ButtonBackground.ZIndex = 0 96 | 97 | self.Toggleable = false 98 | local Pressed = false 99 | self.Button.MouseMoved:Connect(function() 100 | GV.PluginObject:GetMouse().Icon = self.CursorIcon 101 | if self.Disabled or Pressed or self.Toggleable then return end 102 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder, Enum.StudioStyleGuideModifier.Hover) 103 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Hover) 104 | end) 105 | self.Button.MouseLeave:Connect(function() 106 | task.wait(0) 107 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Arrow" 108 | if self.Disabled or self.Toggleable then return end 109 | if Pressed and self.ReleasedAction then self.ReleasedAction() end 110 | Pressed = false 111 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder) 112 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button) 113 | end) 114 | 115 | self.Button.MouseButton1Down:Connect(function() 116 | if self.Disabled or self.Toggleable then return end 117 | if self.PressedAction then self.PressedAction() end 118 | Pressed = true 119 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder, Enum.StudioStyleGuideModifier.Pressed) 120 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button, Enum.StudioStyleGuideModifier.Pressed) 121 | end) 122 | 123 | self.Button.MouseButton1Up:Connect(function() 124 | if self.Disabled or self.Toggleable then return end 125 | if self.ReleasedAction then self.ReleasedAction() end 126 | Pressed = false 127 | ThemeManager.ColorSync(self.Button, "ImageColor3", Enum.StudioStyleGuideColor.ButtonBorder) 128 | ThemeManager.ColorSync(self.ButtonBackground, "ImageColor3", Enum.StudioStyleGuideColor.Button) 129 | end) 130 | 131 | self.Button.MouseButton1Click:Connect(function() 132 | if not self.Disabled then 133 | if self.Action then self.Action(self.Value) end 134 | end 135 | end) 136 | 137 | self:SetDisabled(self.Arguments.Disabled) 138 | self.Object = self.Button 139 | self.MainMovable = self.ButtonFrame 140 | return self 141 | end 142 | 143 | return Button -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/Page.lua: -------------------------------------------------------------------------------- 1 | local Page = {} 2 | Page.__index = Page 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local InputManager = require(GV.ManagersDir.InputManager) 7 | local GUIFrame = require(GV.FramesDir.GUIFrame) 8 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 9 | setmetatable(Page,GUIFrame) 10 | local PageNum = 0 11 | GV.PluginPages = {} 12 | 13 | function Page:SetState(State) 14 | self.Open = State 15 | self.Content.Visible = State 16 | local Transparency = 1 17 | local OppositeTransparency = 0 18 | if State then Transparency, OppositeTransparency = 0, 1 end 19 | self.TabFrame.BackgroundTransparency, self.TopBorder.BackgroundTransparency, self.LeftBorder.BackgroundTransparency, self.RightBorder.BackgroundTransparency = Transparency, Transparency, Transparency, Transparency 20 | self.Tab.BackgroundTransparency = OppositeTransparency 21 | self.TabFrame.ZIndex, self.Tab.ZIndex, self.TopBorder.ZIndex, self.LeftBorder.ZIndex, self.RightBorder.ZIndex = OppositeTransparency + 2, OppositeTransparency + 2, OppositeTransparency + 2, OppositeTransparency + 2, OppositeTransparency + 2 22 | if State then 23 | ThemeManager.ColorSync(self.Tab, "TextColor3", Enum.StudioStyleGuideColor.MainText) 24 | else 25 | ThemeManager.ColorSync(self.Tab, "TextColor3", Enum.StudioStyleGuideColor.TitlebarText,nil,nil,nil,true) 26 | end 27 | end 28 | 29 | -- Name, TitlebarMenu, Open, TabSize, ID 30 | function Page.new(Arguments, Parent) 31 | local self = GUIFrame.new(Arguments, Parent) 32 | self.TitlebarMenu = self.Arguments.TitlebarMenu or self.Parent.TitlebarMenu 33 | setmetatable(self,Page) 34 | PageNum += 1 35 | self.ID = self.Arguments.ID or self.Arguments.Name 36 | self.TabFrame = Instance.new("Frame", self.TitlebarMenu.TabContainer) 37 | self.TabFrame.Name = PageNum 38 | self.TabFrame.BorderSizePixel = 0 39 | ThemeManager.ColorSync(self.TabFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.MainBackground) 40 | self.Tab = Instance.new("TextButton", self.TabFrame) 41 | self.Tab.Size = UDim2.new(1, 0, 0, 24) 42 | ThemeManager.ColorSync(self.Tab, "BackgroundColor3", Enum.StudioStyleGuideColor.Titlebar,nil,nil,nil,true) 43 | self.Tab.BorderSizePixel = 0 44 | self.Tab.Font = Enum.Font.SourceSans 45 | self.Tab.Text = self.Arguments.Name 46 | self.Tab.TextSize = 14 47 | self.Tab.Name = "Tab" 48 | self.InsideWidget = true 49 | if not self.Arguments.TabSize then 50 | local function sync() 51 | self.TabFrame.Size = UDim2.new(0,self.Tab.TextBounds.X+1.5*self.Tab.TextSize, 0, 24) 52 | end 53 | self.Tab.Changed:Connect(function(p) 54 | if p == "TextBounds" then sync() end 55 | end) 56 | sync() 57 | else 58 | self.TabFrame.Size = UDim2.new(0,self.Arguments.TabSize,0,30) 59 | end 60 | self.Tab.MouseButton1Down:Connect(function(x) 61 | if self.TabDragging then return end 62 | GV.SelectedPage = self 63 | self.TitlebarMenu:SetActive(self.ID) 64 | self.TabDragging = true 65 | self.InitialX = self.TabFrame.Position.X.Offset - x - self.TitlebarMenu.ScrollingMenu.CanvasPosition.X 66 | end) 67 | InputManager.AddInputEvent("InputEnded", function(p) 68 | if not self.TabDragging or p.UserInputType ~= Enum.UserInputType.MouseButton1 then return end 69 | GV.SelectedPage = nil 70 | self.TabDragging = false 71 | self.TitlebarMenu:FixPageLayout() 72 | end) 73 | InputManager.AddInputEvent("MouseEnter", function() 74 | if not self.TabDragging and self.InsideWidget then return end 75 | self.TitlebarMenu:AddPage(self) 76 | self.InsideWidget = true 77 | GV.SelectedPage = nil 78 | self.TabDragging = false 79 | self.TitlebarMenu:FixPageLayout() 80 | end) 81 | local PreviousMouseX = 0 82 | InputManager.AddInputEvent("MouseMoved", function(x) 83 | PreviousMouseX = x 84 | if not self.TabDragging then return end 85 | self.TabFrame.Position = UDim2.new(0,x + self.InitialX + self.TitlebarMenu.ScrollingMenu.CanvasPosition.X,0,0) 86 | if self.InsideWidget then self.TitlebarMenu:BeingDragged(self.ID) end 87 | end) 88 | self.TitlebarMenu.ScrollingMenu.Changed:Connect(function(p) 89 | if not p == "CanvasPosition" or not self.TabDragging then return end 90 | self.TabFrame.Position = UDim2.new(0,PreviousMouseX + self.InitialX + self.TitlebarMenu.ScrollingMenu.CanvasPosition.X,0,0) 91 | if self.InsideWidget then self.TitlebarMenu:BeingDragged(self.ID) end 92 | end) 93 | InputManager.AddInputEvent("MouseLeave", function() 94 | if not self.TabDragging then return end 95 | self.TabDragging = false 96 | self.InsideWidget = false 97 | GV.PluginObject:StartDrag({}) 98 | self.TitlebarMenu:RemovePage(self) 99 | end) 100 | ThemeManager.ColorSync(self.Tab, "TextColor3", Enum.StudioStyleGuideColor.TitlebarText,nil,nil,nil,true) 101 | self.TopBorder = Instance.new("Frame", self.TabFrame) 102 | self.TopBorder.Size = UDim2.new(1,0,0,1) 103 | self.TopBorder.BorderSizePixel = 0 104 | self.TopBorder.Name = "TopBorder" 105 | ThemeManager.ColorSync(self.TopBorder, "BackgroundColor3", Enum.StudioStyleGuideColor.RibbonTabTopBar, nil, true, nil, true) 106 | self.LeftBorder = Instance.new("Frame", self.TabFrame) 107 | self.LeftBorder.Size = UDim2.new(0,1,0,24) 108 | self.LeftBorder.BorderSizePixel = 0 109 | self.LeftBorder.Name = "LeftBorder" 110 | ThemeManager.ColorSync(self.LeftBorder, "BackgroundColor3", Enum.StudioStyleGuideColor.Border) 111 | self.RightBorder = Instance.new("Frame", self.TabFrame) 112 | self.RightBorder.Size = UDim2.new(0,1,0,24) 113 | self.RightBorder.Position = UDim2.new(1,0,0,0) 114 | self.RightBorder.BorderSizePixel = 0 115 | self.RightBorder.Name = "RightBorder" 116 | ThemeManager.ColorSync(self.RightBorder, "BackgroundColor3", Enum.StudioStyleGuideColor.Border) 117 | self.Content = Instance.new("Frame", self.TitlebarMenu.ContentContainers) 118 | self.Content.BackgroundTransparency = 1 119 | self.Content.Size = UDim2.new(1,0,1,0) 120 | self.Content.Name = self.ID 121 | self.TitlebarMenu:AddPage(self) 122 | if self.Arguments.Open then self.TitlebarMenu:SetActive(self.ID) else self:SetState(false) end 123 | GV.PluginPages[#GV.PluginPages+1] = self 124 | return self 125 | end 126 | 127 | return Page -------------------------------------------------------------------------------- /src/rblxgui/lib/Frames/TitlebarMenu.lua: -------------------------------------------------------------------------------- 1 | local StarterPlayer = game:GetService("StarterPlayer") 2 | local TitlebarMenu = {} 3 | TitlebarMenu.__index = TitlebarMenu 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local GUIFrame = require(GV.FramesDir.GUIFrame) 6 | local util = require(GV.MiscDir.GUIUtil) 7 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 8 | setmetatable(TitlebarMenu,GUIFrame) 9 | GV.PluginTitlebarMenus = {} 10 | 11 | function TitlebarMenu:RecievePage(Page) 12 | Page.TabFrame.Parent = self.TabContainer 13 | Page.Content.Parent = self.ContentContainers 14 | Page.TitlebarMenu = self 15 | Page.InsideWidget = true 16 | Page.Parent = self.TitlebarMenu 17 | self:AddPage(Page) 18 | end 19 | 20 | function TitlebarMenu:GetIDIndex(ID) 21 | for i,v in pairs(self.Pages) do if v.ID == ID then return i end end 22 | end 23 | 24 | function TitlebarMenu:GetIDTab(ID) 25 | return self.Pages[self:GetIDIndex(ID)] 26 | end 27 | 28 | function TitlebarMenu:AddPage(Page) 29 | self:FixPageLayout() 30 | if #self.Pages > 0 then 31 | local LatestPage = self.Pages[#self.Pages] 32 | Page.TabFrame.Position = UDim2.new(0,LatestPage.TabFrame.Position.X.Offset + LatestPage.TabFrame.Size.X.Offset,0,0) 33 | else 34 | Page.TabFrame.Position = UDim2.new(0,0,0,0) 35 | end 36 | self.ScrollingMenu.CanvasSize = UDim2.new(0,Page.TabFrame.Position.X.Offset + Page.TabFrame.Size.X.Offset,0,0) 37 | self.Pages[#self.Pages+1] = Page 38 | end 39 | 40 | function TitlebarMenu:RemovePage(Page) 41 | table.remove(self.Pages, self:GetIDIndex(Page.ID)) 42 | self.ScrollingMenu.CanvasSize = UDim2.new(0,self.ScrollingMenu.CanvasSize.Width.Offset - Page.TabFrame.Size.X.Offset,0,0) 43 | self:FixPageLayout() 44 | end 45 | 46 | function TitlebarMenu:SetActive(ID) 47 | for _, v in pairs(self.Pages) do 48 | v:SetState(v.ID == ID) 49 | end 50 | end 51 | 52 | function TitlebarMenu:FixPageLayout(IgnoreID) 53 | local PreviousPageSize = 0 54 | for _, v in pairs(self.Pages) do 55 | if IgnoreID ~= v.ID then 56 | v.TabFrame.Position = UDim2.new(0,PreviousPageSize,0,0) 57 | end 58 | PreviousPageSize += v.TabFrame.Size.X.Offset 59 | end 60 | end 61 | 62 | function TitlebarMenu:MovePage(ID, Index, IgnoreID) 63 | local PageIndex = self:GetIDIndex(ID) 64 | if PageIndex == Index then return end 65 | local Page = self.Pages[PageIndex] 66 | table.remove(self.Pages, PageIndex) 67 | table.insert(self.Pages, Index, Page) 68 | if IgnoreID then self:FixPageLayout(ID) end 69 | end 70 | 71 | function TitlebarMenu:BeingDragged(ID) 72 | local tab = self:GetIDTab(ID) 73 | local xpos = tab.TabFrame.Position.X.Offset + tab.TabFrame.Size.X.Offset / 2 74 | for i, v in pairs(self.Pages) do 75 | if v.ID ~=ID and xpos >= v.TabFrame.Position.X.Offset and xpos < v.TabFrame.Position.X.Offset + v.TabFrame.Size.X.Offset then 76 | self:MovePage(ID, i, true) 77 | end 78 | end 79 | end 80 | -- ID 81 | function TitlebarMenu.new(Arguments, Parent) 82 | local self = GUIFrame.new(Arguments, Parent) 83 | self.ID = self.Arguments.ID or game:GetService("HttpService"):GenerateGUID(false) 84 | setmetatable(self,TitlebarMenu) 85 | self.TitlebarMenu = Instance.new("Frame", self.Parent) 86 | self.TitlebarMenu.Name = "TitlebarMenu" 87 | self.TitlebarMenu.Size = UDim2.new(1,0,0,24) 88 | ThemeManager.ColorSync(self.TitlebarMenu, "BackgroundColor3", Enum.StudioStyleGuideColor.Titlebar,nil,nil,nil,true) 89 | self.TitlebarMenu.BorderSizePixel = 0 90 | self.ButtonsFrame = Instance.new("Frame", self.TitlebarMenu) 91 | self.ButtonsFrame.Size = UDim2.new(0,0,0,24) 92 | self.ButtonsFrame.ZIndex = 3 93 | ThemeManager.ColorSync(self.ButtonsFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.Titlebar,nil,nil,nil,true) 94 | self.ButtonsFrame.BorderSizePixel = 0 95 | self.ButtonsFrame.Name = "ButtonsFrame" 96 | local ButtonsFrameBorder = Instance.new("Frame", self.ButtonsFrame) 97 | ButtonsFrameBorder.Position = UDim2.new(0,0,1,-1) 98 | ButtonsFrameBorder.Size = UDim2.new(1,0,0,1) 99 | ButtonsFrameBorder.BorderSizePixel = 0 100 | ThemeManager.ColorSync(ButtonsFrameBorder, "BackgroundColor3", Enum.StudioStyleGuideColor.Border,nil,nil,nil,true) 101 | ButtonsFrameBorder.Name = "Border" 102 | ButtonsFrameBorder.ZIndex = 5 103 | self.ButtonContainer = Instance.new("Frame", self.ButtonsFrame) 104 | self.ButtonContainer.BackgroundTransparency = 1 105 | self.ButtonContainer.BorderSizePixel = 0 106 | self.ButtonContainer.Size = UDim2.new(1,0,1,0) 107 | self.ButtonContainer.Name = "ButtonContainer" 108 | local ButtonContainerLayout = Instance.new("UIListLayout", self.ButtonContainer) 109 | ButtonContainerLayout.FillDirection = Enum.FillDirection.Horizontal 110 | ButtonContainerLayout.SortOrder = Enum.SortOrder.LayoutOrder 111 | self.ScrollingMenu = Instance.new("ScrollingFrame", self.TitlebarMenu) 112 | self.ScrollingMenu.BackgroundTransparency = 1 113 | self.ScrollingMenu.Position = UDim2.new(1,0,0,0) 114 | self.ScrollingMenu.AnchorPoint = Vector2.new(1,0) 115 | self.ScrollingMenu.Size = UDim2.new(1,0,1,0) 116 | self.ScrollingMenu.CanvasSize = UDim2.new(0,0,0,0) 117 | self.ScrollingMenu.ScrollBarThickness = 0 118 | self.ScrollingMenu.ScrollingDirection = Enum.ScrollingDirection.X 119 | self.ScrollingMenu.ZIndex = 2 120 | self.ScrollingMenu.ClipsDescendants = false 121 | ButtonContainerLayout.Changed:Connect(function(p) 122 | if p ~= "AbsoluteContentSize" then return end 123 | self.ButtonsFrame.Size = UDim2.new(0,ButtonContainerLayout.AbsoluteContentSize.X, 1,0) 124 | self.ScrollingMenu.Size = UDim2.new(1,-ButtonContainerLayout.AbsoluteContentSize.X,1,0) 125 | end) 126 | self.TabContainer = Instance.new("Frame", self.ScrollingMenu) 127 | self.TabContainer.BackgroundTransparency = 1 128 | self.TabContainer.Size = UDim2.new(1,0,1,0) 129 | self.TabContainer.ZIndex = 2 130 | self.TabContainer.Name = "TabContainer" 131 | --local TabContainerPadding = Instance.new("UIPadding", self.TabContainer) 132 | --TabContainerPadding.PaddingLeft, TabContainerPadding.PaddingRight = UDim.new(0,5), UDim.new(0,5) 133 | local TabContainerBorder = Instance.new("Frame", self.TitlebarMenu) 134 | TabContainerBorder.Name = "Border" 135 | TabContainerBorder.Position = UDim2.new(0,0,1,-1) 136 | TabContainerBorder.Size = UDim2.new(1,0,0,1) 137 | TabContainerBorder.BorderSizePixel = 0 138 | TabContainerBorder.ZIndex = 2 139 | ThemeManager.ColorSync(TabContainerBorder, "BackgroundColor3", Enum.StudioStyleGuideColor.Border) 140 | self.ContentContainers = Instance.new("Frame", self.Parent) 141 | self.ContentContainers.Name = "Content" 142 | self.ContentContainers.BackgroundTransparency = 1 143 | self.ContentContainers.Position = UDim2.new(0,0,0,24) 144 | self.ContentContainers.Size = UDim2.new(1,0,1,-24) 145 | self.Pages = {} 146 | self.Content = self.Parent 147 | GV.PluginTitlebarMenus[#GV.PluginTitlebarMenus+1] = self 148 | return self 149 | end 150 | 151 | return TitlebarMenu -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![rblxguibanner|690x215](assets/rblxguibanner.png)](https://github.com/xa1on/rblxguilib) 2 |
3 | 💾 Github | 📩 Discord 4 |
5 | 6 | 7 |
8 | Hosts a wide variety of GUI Elements made for dockable widgets in order to improve GUI workflow and provide a uniform look and feel for plugins. 9 |
10 | 11 |
 
12 | 13 | ## Overview 14 | 15 | [RBLXGUI](https://github.com/xa1on/rblxguilib) is an open-source GUI library for plugins inspired by [Studio Widgets](https://github.com/Roblox/StudioWidgets). 16 | 17 | **Warning**: RBLXGUI completely overhauls wigets. if you want something more visually customizable rather than the basic Studio aesthetic, this is probably not for you. 18 | 19 | ### Please contribute! 20 | This was a solo project and any help improving or keeping the library up to date would be greatly appreciated! 21 | 22 |

Getting Started

23 | 24 | In order to install this library, drag the [latest release](https://github.com/xa1on/rblxguilib/releases) into your plugin folder. 25 | 26 | You can also clone the repo and build the project with [rojo](https://rojo.space). 27 | 28 | ```bash 29 | rojo build --output "C:\Users\[Username]\AppData\Local\Roblox\Plugins\[Plugin Name].rbxmx" 30 | ``` 31 | 32 | Another way to install the library is by using [HttpService](https://www.robloxdev.com/api-reference/class/HttpService) to pull the contents directly from this github project into module scripts. Make sure you have http service from `Game Settings` enabled in order for this to work. 33 | 34 | ```Lua 35 | --Modified to support nesting 36 | local http = game:GetService("HttpService") 37 | local req = http:GetAsync("https://api.github.com/repos/xa1on/rblxguilib/contents/src") 38 | local jsonSrc = http:JSONDecode(req) 39 | 40 | local targetFolder = Instance.new("Folder") 41 | targetFolder.Name = "StudioWidgets" 42 | targetFolder.Parent = game.Workspace 43 | 44 | function loopdir(json, folder) 45 | for i = 1, #json do 46 | local file = json[i] 47 | if file.type == "file" then 48 | local name = file.name:sub(1, #file.name-4) 49 | local module = targetFolder:FindFirstChild(name) or Instance.new("ModuleScript") 50 | module.Name = name 51 | module.Source = http:GetAsync(file.download_url) 52 | module.Parent = folder 53 | elseif file.type == "dir" then 54 | local dir = http:GetAsync(`https://api.github.com/repos/xa1on/rblxguilib/contents/{file.path}`) 55 | local dirJson = http:JSONDecode(dir) 56 | local dirFolder = Instance.new("Folder") 57 | dirFolder.Name = file.name 58 | dirFolder.Parent = folder 59 | loopdir(dirJson, dirFolder) 60 | end 61 | end 62 | end 63 | 64 | loopdir(jsonSrc, targetFolder) 65 | ``` 66 | (Credit to the [StudioWidgets](https://github.com/Roblox/StudioWidgets) repo for the import code) 67 | 68 |

Files

69 | 70 | ### Frames 71 | | Element | Description | 72 | | --- | --- | 73 | | [GUIFrame.lua](src/rblxgui/lib/Frames/GUIFrame.lua) | Class for all frame elements | 74 | | [BackgroundFrame.lua](src/rblxgui/lib/Frames/BackgroundFrame.lua) | Creates a frame that syncs its color to the current studio theme | 75 | | [ListFrame.lua](src/rblxgui/lib/Frames/ListFrame.lua) | A uniform frame that goes in ScrollingFrames used to house objects | 76 | | [Page.lua](src/rblxgui/lib/Frames/Page.lua) | Creates a page tab in a widget's TitlebarMenu | 77 | | [PluginWidget.lua](src/rblxgui/lib/Frames/PluginWidget.lua) | Creates a rblxgui widget | 78 | | [ScrollingFrame.lua](src/rblxgui/lib/Frames/ScrollingFrame.lua) | A self-scaling ScrollingFrame | 79 | | [Section.lua](src/rblxgui/lib/Frames/Section.lua) | A collapsible frame used to house objects | 80 | | [TitlebarMenu.lua](src/rblxgui/lib/Frames/TitlebarMenu.lua) | Menu on widgets that contains it's pages and TitlebarButtons | 81 | 82 | ### Objects 83 | | Element | Description | 84 | | --- | --- | 85 | | [GUIObject.lua](src/rblxgui/lib/Objects/GUIObject.lua) | Class for all object elements | 86 | | [Button.lua](src/rblxgui/lib/Objects/Button.lua) | Creates a Button | 87 | | [Checkbox.lua](src/rblxgui/lib/Objects/Checkbox.lua) | Toggleable checkbox object that returns true and false | 88 | | [ColorInput.lua](src/rblxgui/lib/Objects/ColorInput.lua) | Object used to input colors using RGB values or ColorPropmt | 89 | | [InputField.lua](src/rblxgui/lib/Objects/InputField.lua) | TextBox object with a filtered dropdown menu | 90 | | [InstanceInputFrame.lua](src/rblxgui/lib/Objects/InstanceInputFrame.lua) | InputField for adding selected workspace objects | 91 | | [KeybindInputFrame.lua](src/rblxgui/lib/Objects/KeybindInputFrame.lua) | InputField for keybinds | 92 | | [Labeled.lua](src/rblxgui/lib/Objects/Labeled.lua) | Text object that acts as a label for other objects | 93 | | [ProgressBar.lua](src/rblxgui/lib/Objects/ProgressBar.lua) | Bar that fills up to represent progress | 94 | | [Slider.lua](src/rblxgui/lib/Objects/Slider.lua) | Adjustable slider that returns number values | 95 | | [Textbox.lua](src/rblxgui/lib/Objects/Textbox.lua) | Creates a TextLabel object | 96 | | [TitlebarButton.lua](src/rblxgui/lib/Objects/TitlebarButton.lua) | Creates a TitlebarMenu Tab that acts as a button | 97 | | [ViewButton.lua](src/rblxgui/lib/Objects/ViewButton.lua) | Creates a TitlebarButton that allows users to editing widgets, layouts, and themes | 98 | 99 | ### Prompts 100 | | Element | Description | 101 | | --- | --- | 102 | | [Prompt.lua](src/rblxgui/lib/Propmts/Prompt.lua) | Creates a widget that acts as a prompt window and class for all prompt elements | 103 | | [ColorPrompt.lua](src/rblxgui/lib/Propmts/ColorPrompt.lua) | TextPrompt window that allows user to edit colors | 104 | | [InputPrompt.lua](src/rblxgui/lib/Propmts/InputPrompt.lua) | TextPrompt window with an InputField | 105 | | [TextPrompt.lua](src/rblxgui/lib/Propmts/TextPrompt.lua) | Prompt with text and buttons | 106 | 107 | ### Managers 108 | | File | Description | 109 | | --- | --- | 110 | | [EventManager.lua](src/rblxgui/lib/Managers/EventManager.lua) | Manages plugin events | 111 | | [InputManager.lua](src/rblxgui/lib/Managers/InputManager.lua) | Keyyboard/mouse input event manager for rblxgui elements | 112 | | [KeybindManager.lua](src/rblxgui/lib/Managers/KeyindManager.lua) | Keybind Manager for KeybindInputObjects | 113 | | [LayoutManager.lua](src/rblxgui/lib/Managers/LayoutManager.lua) | Layout manager for plugin widget/page layouts in studio | 114 | | [ThemeManager.lua](src/rblxgui/lib/Managers/ThemeManager.lua) | Theme manager for rblxgui element colors | 115 | 116 | ### Misc 117 | | File | Description | 118 | | --- | --- | 119 | | [GUIElement.lua](src/rblxgui/lib/GUIElement.lua) | Class for all GUI Elements | 120 | | [GUIUtil.lua](src/rblxgui/lib/Misc/GUIUtil.lua) | ModuleScript that contains utility functions that dont fit the other categories | 121 | | [PluginGlobalVariables.lua](src/rblxgui/lib/PluginGlobalVariables.lua) | ModuleScript that consolidates all variables used globally in the library | 122 | 123 | ## Documentation 124 | No documentation at the moment, but you should be able to see how everything works in the [Example Script](src/Example.client.lua). 125 | 126 | If anyone actually plans on using this, DM me on [Twitter](https://twitter.com/xalondzn) or Discord (@xa1on) if you have any further questions or if you just want to show off what you made. 127 | 128 | ## Final Notes 129 | A lot of my code may be a bit messy and unorganized but I hope you can bear with me since this is my first big project with lua and I feel like a grew a lot in the process of making this. In the future, I might plan on using Fusion to help make this library a bit better to work with. 130 | 131 | ## License 132 | Available under the Apache 2.0 license. See [LICENSE](LICENSE) for details. 133 | -------------------------------------------------------------------------------- /src/rblxgui/lib/Managers/KeybindManager.lua: -------------------------------------------------------------------------------- 1 | local InputService = game:GetService("UserInputService") 2 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 3 | local util = require(GV.MiscDir.GUIUtil) 4 | local InputManager = require(GV.ManagersDir.InputManager) 5 | local EventManager = require(GV.ManagersDir.EventManager) 6 | 7 | local m = {} 8 | 9 | m.Keys = { 10 | LeftControl = "Ctrl", LeftAlt = "Alt", LeftShift = "Shift", QuotedDouble = '"', Hash = "#", Dollar = "$" , Percent = "%", Ampersand = "&", Quote = "'", LeftParenthesis = "(", RightParenthesis = ")", Asterisk = "*",Plus = "+", Comma = ",", Minus = "-", Period = ".", Slash = "/", Zero = "0", One = "1", Two = "2", Three = "3", Four = "4", Five = "5", Six = "6", Seven = "7", Eight = "8", Nine = "9", Colon = ":", Semicolon = ";", LessThan = "<", Equals = "=", GreaterThan = ">", Question = "?", At = "@", LeftBracket = "[", BackSlash = "\\", RightBracket = "]", Caret = "^", Underscore = "_", Backquote = "`", LeftCurly = "{", Pipe = "|", RightCurly = "}", Tilde = "~", Delete = "Del", Up = "↑", Down = "↓", Right = "→", Left = "←", PageUp = "PgUp", PageDown = "PgDown", Euro = "€" 11 | } 12 | 13 | function m.FilterKeyCode(KeycodeName) 14 | if KeycodeName == "RightControl" then KeycodeName = "LeftControl" 15 | elseif KeycodeName == "RightAlt" then KeycodeName = "LeftAlt" 16 | elseif KeycodeName == "RightShift" then KeycodeName = "LeftShift" end 17 | return KeycodeName 18 | end 19 | 20 | function m.RecallKeyName(KeycodeName) 21 | KeycodeName = m.FilterKeyCode(KeycodeName) 22 | KeycodeName = KeycodeName:gsub("Keypad", "") 23 | if m.Keys[KeycodeName] then 24 | return m.Keys[KeycodeName] 25 | end 26 | return KeycodeName 27 | end 28 | 29 | function m.GenerateKeybindName(Keybind) 30 | if type(Keybind) == "string" then Keybind = {Keybind} end 31 | if #Keybind < 1 then return "" end 32 | local GeneratedName = m.RecallKeyName(Keybind[1]) 33 | for i, v in pairs(Keybind) do 34 | if i ~= 1 then 35 | GeneratedName = GeneratedName .. "+" .. m.RecallKeyName(v) 36 | end 37 | end 38 | return GeneratedName 39 | end 40 | 41 | function m.GenerateKeybindList(Keybinds) 42 | if type(Keybinds) == "string" then Keybinds = {{Keybinds}} end 43 | if #Keybinds < 1 then return "" end 44 | local GeneratedList = m.GenerateKeybindName(Keybinds[1]) 45 | for i, v in pairs(Keybinds) do 46 | if i ~= 1 and #v > 0 then 47 | GeneratedList = GeneratedList .. ", " .. m.GenerateKeybindName(v) 48 | end 49 | end 50 | return GeneratedList 51 | end 52 | 53 | 54 | 55 | m.Keybinds = {} 56 | m.ActiveKeybinds = {} 57 | 58 | function m.UpdateKeybinds(Name, Args) 59 | m.Keybinds[Name] = Args 60 | end 61 | 62 | function m.TableContains(Table, Contains) 63 | for _, v in pairs(Table) do if v == Contains then return true end end 64 | return false 65 | end 66 | 67 | function m.TableContainsTable(Table1, Table2) 68 | if #Table1 < #Table2 or #Table2 < 1 then return false end 69 | for _, v in pairs(Table2) do 70 | if not m.TableContains(Table1, v) then 71 | return false 72 | end 73 | end 74 | return true 75 | end 76 | 77 | function m.CheckKeybinds(Keys, Holdable, KeycodeName) 78 | local ContainsKeybind = false 79 | for _, Input in pairs(m.Keybinds) do 80 | ContainsKeybind = false 81 | for _, Keybind in pairs(Input.Keybinds) do 82 | if not Holdable and not Input.Holdable then 83 | if #Keys > 0 and #Keys == #Keybind and m.TableContainsTable(Keys, Keybind) then 84 | ContainsKeybind = true 85 | break 86 | end 87 | end 88 | if Holdable and Input.Holdable and m.TableContainsTable(Keys, Keybind) and KeycodeName and m.TableContains(Keybind, KeycodeName) then 89 | ContainsKeybind = true 90 | end 91 | end 92 | if not ContainsKeybind then continue end 93 | m.ActiveKeybinds[#m.ActiveKeybinds+1] = Input 94 | if Input.PressedAction then Input.PressedAction() end 95 | end 96 | end 97 | 98 | function m.CheckActive(KeycodeName) 99 | local IndexShift = 0 100 | local ContainsRemoved = false 101 | for Index, Input in pairs(m.ActiveKeybinds) do 102 | if Input.Holdable and KeycodeName then 103 | ContainsRemoved = false 104 | for _, Keybind in pairs(Input.Keybinds) do 105 | if m.TableContains(Keybind, KeycodeName) then 106 | ContainsRemoved = true 107 | break 108 | end 109 | end 110 | if not ContainsRemoved then 111 | continue 112 | end 113 | end 114 | if Input.ReleasedAction then Input.ReleasedAction() end 115 | table.remove(m.ActiveKeybinds, Index - IndexShift) 116 | IndexShift += 1 117 | end 118 | 119 | end 120 | 121 | 122 | m.FocusFunction = {} 123 | m.FocusedInputField = {} 124 | 125 | function m.FocusInputField(Name, selfobj, EditBind, RemoveBind, Unfocus) 126 | if m.FocusedInputField.Name and m.FocusedInputField.Name ~= Name then m.Unfocus() end 127 | m.FocusedInputField = {Name = Name, Unrestricted = selfobj.Unrestricted, EditBind = EditBind, RemoveBind = RemoveBind, Unfocus = Unfocus} 128 | for i, v in pairs(m.FocusedInputField) do 129 | if type(v) == "function" then 130 | m.FocusFunction[i] = function(...) 131 | return v(selfobj, ...) 132 | end 133 | end 134 | end 135 | end 136 | 137 | function m.Unfocus(ForceClose) 138 | if m.FocusFunction.Unfocus and m.FocusFunction.Unfocus(ForceClose) then 139 | m.FocusFunction = {} 140 | end 141 | end 142 | 143 | 144 | --Keys being pressed down 145 | local CurrentKeys = {} 146 | local CompleteBind = false 147 | 148 | local function InputBegan(p) 149 | if p.UserInputType == Enum.UserInputType.MouseButton1 or p.UserInputType == Enum.UserInputType.MouseButton2 then m.Unfocus() return end 150 | if p.UserInputType ~= Enum.UserInputType.Keyboard then return end 151 | local KeycodeName = m.FilterKeyCode(p.KeyCode.Name) 152 | local KeyName = m.RecallKeyName(p.KeyCode.Name) 153 | for _, v in pairs(CurrentKeys) do 154 | if v == KeycodeName then return end 155 | end 156 | m.CheckActive(KeycodeName) 157 | if KeyName == "Backspace" and m.FocusFunction.RemoveBind then m.FocusFunction.RemoveBind() return end 158 | if KeyName == "Escape" and m.FocusFunction.Unfocus then m.Unfocus() return end 159 | CurrentKeys[#CurrentKeys+1] = KeycodeName 160 | m.CheckKeybinds(CurrentKeys, true, KeycodeName) 161 | if not m.FocusFunction.EditBind or not m.FocusedInputField.Unrestricted then 162 | if CompleteBind then return end 163 | if KeyName ~= "Ctrl" and KeyName ~= "Alt" and KeyName ~= "Shift" then 164 | CompleteBind = true 165 | if m.FocusFunction.EditBind then 166 | m.FocusFunction.EditBind(util.CopyTable(CurrentKeys), true) 167 | return 168 | end 169 | end 170 | end 171 | m.CheckKeybinds(CurrentKeys) 172 | if m.FocusFunction.EditBind then m.FocusFunction.EditBind(util.CopyTable(CurrentKeys), false) end 173 | end 174 | 175 | local function InputEnded(p) 176 | if p.UserInputType ~= Enum.UserInputType.Keyboard then return end 177 | local KeycodeName = m.FilterKeyCode(p.KeyCode.Name) 178 | local KeyName = m.RecallKeyName(KeycodeName) 179 | local IndexShift = 0; 180 | m.CheckActive(KeycodeName) 181 | for i, v in pairs(CurrentKeys) do 182 | if v == KeycodeName then 183 | if not m.FocusedInputField.Unrestricted then 184 | if KeyName ~= "Ctrl" and KeyName ~= "Alt" and KeyName ~= "Shift" then 185 | CompleteBind = false 186 | end 187 | elseif (not CompleteBind) or #CurrentKeys ~= 1 then 188 | if m.FocusFunction.EditBind and not CompleteBind then m.FocusFunction.EditBind(util.CopyTable(CurrentKeys), true)end 189 | CompleteBind = true 190 | table.remove(CurrentKeys, i - IndexShift) 191 | if #CurrentKeys == 0 then CompleteBind = false end 192 | return 193 | else 194 | CompleteBind = false 195 | end 196 | table.remove(CurrentKeys, i - IndexShift) 197 | IndexShift += 1 198 | end 199 | end 200 | if m.FocusFunction.EditBind and not CompleteBind then m.FocusFunction.EditBind(util.CopyTable(CurrentKeys), false) end 201 | end 202 | 203 | 204 | InputManager.AddInputEvent("InputBegan", InputBegan) 205 | InputManager.AddInputEvent("InputEnded", InputEnded) 206 | InputManager.AddInputEvent("MouseLeave", m.Unfocus) 207 | EventManager.AddConnection(InputService.InputBegan, InputBegan) 208 | EventManager.AddConnection(InputService.InputEnded, InputEnded) 209 | 210 | return m -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/Example.client.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | [RBLXGUILib] 3 | something#7597 4 | todo: 5 | 6 | ]]-- 7 | 8 | -- loads the library(plugin object, plugin id) 9 | local gui = require(script.Parent.rblxgui.initialize)(plugin, "rblxgui") 10 | 11 | -- plugin toolbar 12 | toolbar = plugin:CreateToolbar("rblxgui") 13 | 14 | -- widget 15 | -- ID, Title, Enabled, NoTitlebarMenu, DockState, OverrideRestore 16 | local widget = gui.PluginWidget.new({ 17 | ID = "rblxgui", 18 | Enabled = true, 19 | DockState = Enum.InitialDockState.Left 20 | }) 21 | 22 | -- toolbar button to toggle the widget 23 | local b_toggle = toolbar:CreateButton("","open widget","") 24 | b_toggle.Click:Connect(function() widget.Content.Enabled = not widget.Content.Enabled end) 25 | local b_resetlayout = toolbar:CreateButton("", "reset layout", "") 26 | b_resetlayout.Click:Connect(function() gui.LayoutManager.ResetLayout() end) 27 | 28 | 29 | -- page: 30 | -- Name, TitlebarMenu, Open, TabSize, ID 31 | local mainpage = gui.Page.new({ 32 | Name = "MAIN", 33 | TitlebarMenu = widget.TitlebarMenu, 34 | Open = true 35 | }) 36 | 37 | -- view button(edit layouts and widgets) 38 | -- 39 | gui.ViewButton.new() 40 | 41 | local randommenu = plugin:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "Random Menu") 42 | randommenu.Name = "Random Menu" 43 | randommenu:AddNewAction("1", "Option 1", "rbxasset://textures/loading/robloxTiltRed.png") 44 | randommenu:AddNewAction("2", "Option 2", "rbxasset://textures/loading/robloxTilt.png") 45 | local subMenu = plugin:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "C", "rbxasset://textures/explosion.png") 46 | subMenu.Name = "Sub Menu" 47 | subMenu:AddNewAction("ActionD", "D", "rbxasset://textures/whiteCircle.png") 48 | subMenu:AddNewAction("ActionE", "E", "rbxasset://textures/icon_ROBUX.png") 49 | randommenu:AddMenu(subMenu) 50 | 51 | -- title bar button(button on the titlebar of widgets with titlebars) 52 | -- Name, TabSize, Disabled, PluginMenu 53 | local titlebarbutton = gui.TitlebarButton.new({ 54 | Name = "BUTTON", 55 | PluginMenu = randommenu 56 | }) 57 | titlebarbutton:Clicked(function() 58 | print("Titlebar button pressed!") 59 | end) 60 | 61 | titlebarbutton:SelectedAction(function(SelectedAction) 62 | if SelectedAction then 63 | print("Selected Action:", SelectedAction.Text, "with ActionId:", SelectedAction.ActionId) 64 | else 65 | print("User did not select an action!") 66 | end 67 | end) 68 | 69 | 70 | gui.Page.new({Name = "SETTINGS"}, widget) 71 | gui.Page.new({Name = "PAGE1"}, widget) 72 | gui.Page.new({Name = "PAGE2"}, widget) 73 | gui.Page.new({Name = "PAGE3"}, widget) 74 | gui.Page.new({Name = "PAGE4"}, widget) 75 | 76 | -- scrolling frame(lets you scroll through the gui): 77 | -- BarSize 78 | local mainframe = gui.ScrollingFrame.new(nil, mainpage.Content) 79 | -- sets mainframe as the main element(everything will go here by default unless you specify a parent) 80 | mainframe:SetMain() 81 | 82 | -- textbox: 83 | -- Text, Font, Alignment, TextSize 84 | gui.Textbox.new({ 85 | Text = "Welcome to rblxgui!", 86 | Font = Enum.Font.SourceSansBold, 87 | Alignment = Enum.TextXAlignment.Center 88 | }) 89 | 90 | -- listframe(contains stuff): 91 | -- Name, Height 92 | local acoolframe = gui.ListFrame.new({ 93 | Name = "cool new frame" 94 | }) 95 | gui.Textbox.new({ 96 | Text = "welcome to rblxgui!" 97 | }, acoolframe.Content) 98 | gui.Textbox.new({ 99 | Text = "WELCOME TO RBLXGUI!", 100 | Font = Enum.Font.SourceSansBold 101 | }, acoolframe.Content) 102 | 103 | -- buttons: 104 | -- Text/Textbox, ButtonSize, Disabled 105 | local button1 = gui.Button.new({ 106 | Text = "hi" 107 | }) 108 | button1:Clicked(function() print("hi") end) 109 | local button2 = gui.Button.new({ 110 | Text = "Hello", 111 | ButtonSize = 1 112 | }, button1.Parent) 113 | button2:Clicked(function() print("Hello") button1:ToggleDisable() end) 114 | 115 | 116 | 117 | -- using a list frame to add padding between elements 118 | gui.ListFrame.new({ 119 | Height = 5 120 | }) 121 | 122 | -- sections: 123 | -- Text, Open, Parent 124 | local buttonsection = gui.Section.new({ 125 | Text = "Buttons" 126 | }) 127 | -- setting the section to main (saves time having to type out the section for every button) 128 | buttonsection:SetMain() 129 | 130 | -- textbox inside button for custom text 131 | local fancybuttonlabel = gui.Textbox.new({ 132 | Text = "fancier button", 133 | Font = Enum.Font.Arcade 134 | }) 135 | local button2 = gui.Button.new({ 136 | Textbox = fancybuttonlabel 137 | }) 138 | button2.Object.MouseButton1Click:Connect(function() 139 | -- textprompt: 140 | -- Title, Textbox, Buttons 141 | local textprompt = gui.TextPrompt.new({ 142 | Title = "The Fancy Button", 143 | Text = "Hello!", 144 | Buttons = {"Hi!", "Hello!"} 145 | }) 146 | textprompt:Clicked(function(p) 147 | print(p) 148 | end) 149 | end) 150 | 151 | -- using frames to move a button 152 | local frame1 = gui.ListFrame.new({ 153 | Name = "the first frame" 154 | }) 155 | local frame2 = gui.ListFrame.new({ 156 | Name = "the second frame" 157 | }) 158 | 159 | local button3 = gui.Button.new({ 160 | Text = "press to go down" 161 | }, frame1.Content) 162 | local buttonup = true 163 | button3:Clicked(function() 164 | if buttonup then 165 | button3:Move(frame2.Content) 166 | button3.Textbox.Text = "press to go up" 167 | else 168 | button3:Move(frame1.Content) 169 | button3.Textbox.Text = "press to go down" 170 | end 171 | print("im in "..button3.Parent.Name.."!") 172 | buttonup = not buttonup 173 | end) 174 | 175 | mainframe:SetMain() 176 | local newsection = gui.Section.new({ 177 | Text = "section with a section inside it", 178 | Open = true 179 | }) 180 | local sectionwithin = gui.Section.new({ 181 | Text = "another section", 182 | Open = true 183 | }, newsection.Content) 184 | gui.Textbox.new({ 185 | Text = "test" 186 | }, gui.ListFrame.new(nil, sectionwithin.Content).Content) 187 | local testbutton = gui.Button.new({ 188 | Text = "test" 189 | }, gui.ListFrame.new(nil, sectionwithin.Content).Content) 190 | testbutton:Clicked(function() 191 | local inputprompt = gui.InputPrompt.new({ 192 | Title = "Input Prompt title", 193 | Text = "hey, this is an inputprompt", 194 | Input = "hi" 195 | }) 196 | inputprompt:Clicked(function(p) 197 | print("option " .. p .. " chosen") 198 | print("entered text:" .. inputprompt.InputField.Value) 199 | end) 200 | end) 201 | 202 | 203 | -- inputfields 204 | -- Placeholder, CurrentItem/Value, Items, InputSize, NoDropdown, NoFiltering, DisableEditing, ClearText, Disabled 205 | gui.InputField.new({ 206 | CurrentItem = "default text", 207 | Items = { 208 | { 209 | Name = "bob", 210 | Value = "Bob" 211 | }, "Steve" 212 | } 213 | }) 214 | 215 | -- Labeled objects 216 | -- Textbox, LabelSize, Objects 217 | local inpfield = gui.Labeled.new({ 218 | Text = "another input", 219 | Objects = gui.InputField.new({ 220 | Placeholder = "placeholder" 221 | }) 222 | }) 223 | inpfield.Object:AddItems({ 224 | "1", 225 | "2", 226 | "remove", 227 | { 228 | Name = "1 thousand", 229 | Value = 1000 230 | } 231 | }) 232 | inpfield.Object:RemoveItem("remove") 233 | for i=4,100 do 234 | inpfield.Object:AddItem(i) 235 | end 236 | inpfield.Object:Changed(function(text) 237 | print(text) 238 | end) 239 | 240 | -- toggleable buttons 241 | -- Textbox, ButtonSize, Value, Disabled 242 | local togglebutton1 = gui.ToggleableButton.new({ 243 | Text = "toggle next button" 244 | }) 245 | local togglebutton2 = gui.ToggleableButton.new({ 246 | Text = "Untoggle previous button", 247 | Value = true 248 | }) 249 | togglebutton1:Clicked(function(p) if p then togglebutton2:SetValue(false) end end) 250 | togglebutton2:Clicked(function(p) if p then togglebutton1:SetValue(false) end end) 251 | 252 | -- instanceinputfield 253 | -- Value/CurrentItem, Items, InputSize, NoDropdown, NoFiltering, DisabledEditing, ClearText, Disabled 254 | local instanceinpfield = gui.InstanceInputField.new({ 255 | Items = { 256 | { 257 | Value = { 258 | game:GetService("Lighting"), 259 | game:GetService("MaterialService") 260 | }, 261 | Name = "Lighting/MaterialService combo" 262 | }, workspace,{ 263 | game:GetService("ReplicatedFirst"), 264 | game:GetService("ReplicatedStorage") 265 | } 266 | } 267 | }) 268 | gui.Labeled.new({ 269 | Text = "an instance", 270 | Object = instanceinpfield 271 | }) 272 | instanceinpfield:Changed(function(result) 273 | for _, v in pairs(result) do 274 | print(v:GetFullName()) 275 | end 276 | end) 277 | instanceinpfield:DropdownToggled(function(p) 278 | print("dropdown has beeen toggled") 279 | print(p) 280 | end) 281 | 282 | 283 | -- keybindinputfield 284 | -- PressedAction, ReleasedAction, Holdable, Unrestricted, Bind/CurrentBind, Items/Binds, InputSize, NoDropdown, NoFiltering, DisabledEditing, ClearText, Disabled 285 | gui.Labeled.new({ 286 | Text = "keybind", 287 | Object = gui.KeybindInputField.new({ 288 | PressedAction = function() print("keybind1 pressed!") end, 289 | ReleasedAction = function() print("keybind1 released!") end, 290 | CurrentBind = { 291 | {"N"}, 292 | {"LeftShift", "T"} 293 | }, 294 | Binds = { 295 | { 296 | Value = { 297 | {"U"}, 298 | {"LeftShift", "L"} 299 | } 300 | },{ 301 | Value = { 302 | {"N"}, 303 | {"LeftShift", "K"} 304 | } 305 | },{ 306 | Name = "Default", 307 | Value = { 308 | {"N"}, 309 | {"LeftShift", "T"} 310 | }, 311 | } 312 | } 313 | }) 314 | }) 315 | 316 | local keybindinpfield2 = gui.Labeled.new({ 317 | Text = "another keybind", 318 | Object = gui.KeybindInputField.new({Holdable = true, Unrestricted = true}) 319 | }) 320 | keybindinpfield2.Object:Pressed(function() 321 | print("second keybind pressed!") 322 | end) 323 | keybindinpfield2.Object:Released(function() 324 | print("second keybind released!") 325 | end) 326 | 327 | -- checkbox 328 | -- Value, Disabled 329 | local checkbox = gui.Labeled.new({ 330 | Text = "checkbox", 331 | LabelSize = 0.5, 332 | Object = gui.Checkbox.new({ 333 | Value = true 334 | }) 335 | }) 336 | checkbox.Object:Clicked(function(p) 337 | print(p) 338 | keybindinpfield2:SetDisabled(not p) 339 | end) 340 | 341 | local toggle_checkbox = gui.Checkbox.new() 342 | gui.Labeled.new({ 343 | Text = "Disable checkbox", 344 | LabelSize = 0.5, 345 | Object = toggle_checkbox 346 | }) 347 | toggle_checkbox:Clicked(function(p) 348 | checkbox:SetDisabled(p) 349 | end) 350 | 351 | -- slider 352 | -- Min, Max, Value, Increment, SliderSize, Disabled 353 | local labeledslider = gui.Labeled.new({ 354 | Text = "Labled Slider", 355 | Objects = { 356 | { 357 | Object = gui.InputField.new({ 358 | Value = 50, 359 | InputSize = 1, 360 | NoDropdown = true, 361 | DisableEditing = true 362 | }), 363 | Name = "display", 364 | Size = UDim.new(0,30) 365 | },{ 366 | Object = gui.Slider.new({ 367 | Min = 0, 368 | Max = 100, 369 | Value = 50, 370 | Increment = 1 371 | }), 372 | Name = "slider" 373 | } 374 | } 375 | }) 376 | 377 | -- progressbar 378 | -- BarSize, Value, Disabled 379 | local progressbar = gui.ProgressBar.new({ 380 | Value = 0.5 381 | }) 382 | 383 | labeledslider.slider:Changed(function(p) 384 | labeledslider.display:SetValue(p) 385 | progressbar:SetValue(p/100) 386 | end) 387 | 388 | local toggle_checkbox2 = gui.Checkbox.new() 389 | gui.Labeled.new({ 390 | Text = "Disable Slider", 391 | LabelSize = 0.5, 392 | Object = toggle_checkbox2 393 | }) 394 | toggle_checkbox2:Clicked(function(p) 395 | labeledslider:SetDisabled(p) 396 | progressbar:SetDisabled(p) 397 | end) 398 | 399 | local colorinput = gui.ColorInput.new({ 400 | Color = gui.ThemeManager.DefaultAccentColor, 401 | NoPause = true 402 | }) 403 | colorinput:SetValue(gui.ThemeManager.AccentColor) 404 | gui.Labeled.new({ 405 | Text = "Color Input", 406 | LabelSize = 0.5, 407 | Object = colorinput 408 | }) 409 | 410 | -- dumps the gui into workspace for debugging 411 | local dumpbutton = gui.Button.new({Text = "Dump GUI into workspace"}) 412 | dumpbutton:Clicked(function() 413 | print("Dumping GUI") 414 | gui.GUIUtil.DumpGUI(widget.Content) 415 | end) 416 | 417 | gui.LayoutManager.RecallSave() -------------------------------------------------------------------------------- /src/rblxgui/lib/Prompts/ColorPrompt.lua: -------------------------------------------------------------------------------- 1 | local ColorPrompt = {} 2 | ColorPrompt.__index = ColorPrompt 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local Prompt = require(GV.PromptsDir.Prompt) 7 | local InputField = require(GV.ObjectsDir.InputField) 8 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 9 | local Button = require(GV.ObjectsDir.Button) 10 | 11 | setmetatable(ColorPrompt, Prompt) 12 | 13 | ColorPrompt.Images = { 14 | PalateIndicator = "http://www.roblox.com/asset/?id=10773265480", 15 | HueIndicator = "http://www.roblox.com/asset/?id=9666389442" 16 | } 17 | 18 | function ColorPrompt:UpdatePreview() 19 | self.ColorGradient.Color = ColorSequence.new{ 20 | ColorSequenceKeypoint.new(0,Color3.new(1,1,1)), 21 | ColorSequenceKeypoint.new(1,Color3.fromHSV(self.HSVValue.H,1,1)) 22 | } 23 | self.ColorPreview.BackgroundColor3 = self.Value 24 | end 25 | 26 | function ColorPrompt:SetPalatePos(X,Y) 27 | self.PalateIndicator.Position = UDim2.fromScale(X,Y) 28 | self.HSVValue.S = X 29 | self.HSVValue.V = 1-Y 30 | self:SetValue(Color3.fromHSV(self.HSVValue.H, self.HSVValue.S, self.HSVValue.V),false,true) 31 | self:UpdatePreview() 32 | end 33 | 34 | function ColorPrompt:SetHuePos(Y) 35 | self.LeftHueIndicator.Position = UDim2.fromScale(0,Y) 36 | self.RightHueIndicator.Position = UDim2.fromScale(1,Y) 37 | self.HSVValue.H = 1-Y 38 | self:SetValue(Color3.fromHSV(self.HSVValue.H, self.HSVValue.S, self.HSVValue.V),false,true) 39 | self:UpdatePreview() 40 | end 41 | 42 | function ColorPrompt:SetValue(Value, IgnoreText, IgnoreHSV) 43 | self.Value = Value or self.Value 44 | local hue, sat, val = self.Value:ToHSV() 45 | if not IgnoreHSV then 46 | self.HSVValue = {H = hue, S = sat, V = val} 47 | end 48 | self.PalateIndicator.Position = UDim2.fromScale(self.HSVValue.S, 1-self.HSVValue.V) 49 | self.LeftHueIndicator.Position = UDim2.fromScale(0,1-self.HSVValue.H) 50 | self.RightHueIndicator.Position = UDim2.fromScale(1,1-self.HSVValue.H) 51 | if not IgnoreText then 52 | self.RGBInput.Input.Text = util.Color3ToText(self.Value) 53 | self.HexInput.Input.Text = "#"..self.Value:ToHex() 54 | end 55 | if self.ChangedAction then self.ChangedAction(self.Value) end 56 | self:UpdatePreview() 57 | end 58 | 59 | function ColorPrompt:Changed(func) 60 | self.ChangedAction = func 61 | end 62 | 63 | function ColorPrompt:Done(func) 64 | self.DoneAction = func 65 | end 66 | 67 | -- Color/Value 68 | function ColorPrompt.new(Arguments) 69 | Arguments.Title = "Pick a Color" 70 | Arguments.Width = 430 71 | Arguments.Height = 315 72 | local self = Prompt.new(Arguments) 73 | setmetatable(self,ColorPrompt) 74 | self.ColorComponents = Instance.new("Frame", self.Parent) 75 | self.ColorComponents.Name = "ColorComponents" 76 | self.ColorComponents.BackgroundTransparency = 1 77 | self.ColorComponents.Position = UDim2.fromOffset(15,30) 78 | self.ColorComponents.Size = UDim2.fromOffset(285,255) 79 | self.ColorPalate = Instance.new("Frame", self.ColorComponents) 80 | self.ColorPalate.Name = "ColorPalate" 81 | self.ColorPalate.Size = UDim2.fromOffset(255,255) 82 | self.ColorPalate.BackgroundTransparency = 1 83 | self.ColorGraidentFrame = Instance.new("Frame", self.ColorComponents) 84 | self.ColorGraidentFrame.Size = UDim2.fromOffset(255,255) 85 | self.ColorGraidentFrame.BackgroundColor3 = Color3.new(1,1,1) 86 | self.ColorGraidentFrame.BorderSizePixel = 0 87 | self.ColorGradient = Instance.new("UIGradient", self.ColorGraidentFrame) 88 | self.LightnessGradientFrame = Instance.new("Frame", self.ColorComponents) 89 | self.LightnessGradientFrame.Size = UDim2.fromOffset(255,255) 90 | self.LightnessGradientFrame.BackgroundColor3 = Color3.new(1,1,1) 91 | self.LightnessGradientFrame.BackgroundTransparency = 0 92 | self.LightnessGradientFrame.BorderSizePixel = 0 93 | self.LightnessGradient = Instance.new("UIGradient", self.LightnessGradientFrame) 94 | self.LightnessGradient.Color = ColorSequence.new({ 95 | ColorSequenceKeypoint.new(0, Color3.new(0)), 96 | ColorSequenceKeypoint.new(1, Color3.new(0)), 97 | }) 98 | self.LightnessGradient.Transparency = NumberSequence.new({ 99 | NumberSequenceKeypoint.new(0, 0), 100 | NumberSequenceKeypoint.new(1, 1), 101 | }) 102 | self.LightnessGradient.Rotation = -90 103 | self.PalateIndicator = Instance.new("ImageLabel", self.ColorPalate) 104 | self.PalateIndicator.Name = "PalateIndicator" 105 | self.PalateIndicator.Image = self.Images.PalateIndicator 106 | self.PalateIndicator.AnchorPoint = Vector2.new(0.5, 0.5) 107 | self.PalateIndicator.BackgroundTransparency = 1 108 | self.PalateIndicator.Size = UDim2.fromOffset(15,15) 109 | self.PalateIndicator.ZIndex = 2 110 | local MouseDownPalate = false 111 | self.ColorPalate.InputBegan:Connect(function(p) 112 | if p.UserInputType == Enum.UserInputType.MouseButton1 then 113 | self:SetPalatePos((p.Position.X-self.ColorPalate.AbsolutePosition.X)/self.ColorPalate.AbsoluteSize.X, (p.Position.Y-self.ColorPalate.AbsolutePosition.Y)/self.ColorPalate.AbsoluteSize.Y) 114 | MouseDownPalate = true 115 | end 116 | end) 117 | self.ColorPalate.InputEnded:Connect(function(p) 118 | if p.UserInputType == Enum.UserInputType.MouseButton1 then 119 | MouseDownPalate = false 120 | end 121 | end) 122 | self.HueGradientFrame = Instance.new("Frame", self.ColorComponents) 123 | self.HueGradientFrame.Name = "HueGradient" 124 | self.HueGradientFrame.AnchorPoint = Vector2.new(1, 0) 125 | self.HueGradientFrame.BackgroundColor3 = Color3.fromRGB(255, 255, 255) 126 | self.HueGradientFrame.BorderSizePixel = 0 127 | self.HueGradientFrame.Position = UDim2.fromScale(1, 0) 128 | self.HueGradientFrame.Size = UDim2.new(0, 20, 1, 0) 129 | 130 | self.HueGradient = Instance.new("UIGradient", self.HueGradientFrame) 131 | self.HueGradient.Name = "UIGradient" 132 | self.HueGradient.Color = ColorSequence.new({ 133 | ColorSequenceKeypoint.new(0, Color3.fromRGB(255, 0, 0)), 134 | ColorSequenceKeypoint.new(1/6, Color3.fromRGB(255, 0, 255)), 135 | ColorSequenceKeypoint.new(1/3, Color3.fromRGB(0, 0, 255)), 136 | ColorSequenceKeypoint.new(0.5, Color3.fromRGB(0, 255, 255)), 137 | ColorSequenceKeypoint.new(2/3, Color3.fromRGB(0, 255, 0)), 138 | ColorSequenceKeypoint.new(5/6, Color3.fromRGB(255, 255, 0)), 139 | ColorSequenceKeypoint.new(1, Color3.fromRGB(255, 0, 0)), 140 | }) 141 | self.HueGradient.Rotation = 90 142 | 143 | self.LeftHueIndicator = Instance.new("ImageLabel", self.HueGradientFrame) 144 | self.LeftHueIndicator.Name = "LeftIndicator" 145 | self.LeftHueIndicator.Image = self.Images.HueIndicator 146 | ThemeManager.ColorSync(self.LeftHueIndicator, "ImageColor3", Enum.StudioStyleGuideColor.MainText) 147 | self.LeftHueIndicator.AnchorPoint = Vector2.new(1, 0.5) 148 | self.LeftHueIndicator.BackgroundTransparency = 1 149 | self.LeftHueIndicator.Rotation = -90 150 | self.LeftHueIndicator.Size = UDim2.fromOffset(10, 10) 151 | 152 | self.RightHueIndicator = Instance.new("ImageLabel", self.HueGradientFrame) 153 | self.RightHueIndicator.Name = "RightIndicator" 154 | self.RightHueIndicator.Image = self.Images.HueIndicator 155 | ThemeManager.ColorSync(self.RightHueIndicator, "ImageColor3", Enum.StudioStyleGuideColor.MainText) 156 | self.RightHueIndicator.AnchorPoint = Vector2.new(0, 0.5) 157 | self.RightHueIndicator.BackgroundTransparency = 1 158 | self.RightHueIndicator.Rotation = 90 159 | self.RightHueIndicator.Size = UDim2.fromOffset(10, 10) 160 | 161 | local MouseDownHueGradient = false 162 | self.HueGradientFrame.InputBegan:Connect(function(p) 163 | if p.UserInputType == Enum.UserInputType.MouseButton1 then 164 | self:SetHuePos(math.clamp((p.Position.Y-self.HueGradientFrame.AbsolutePosition.Y)/self.HueGradientFrame.AbsoluteSize.Y,0,1)) 165 | MouseDownHueGradient = true 166 | end 167 | end) 168 | self.HueGradientFrame.InputEnded:Connect(function(p) 169 | if p.UserInputType == Enum.UserInputType.MouseButton1 then 170 | MouseDownHueGradient = false 171 | end 172 | end) 173 | 174 | self.Parent.MouseMoved:Connect(function(x,y) 175 | if MouseDownPalate then 176 | self:SetPalatePos(math.clamp((x-self.ColorPalate.AbsolutePosition.X)/self.ColorPalate.AbsoluteSize.X, 0, 1), math.clamp((y-self.ColorPalate.AbsolutePosition.Y)/self.ColorPalate.AbsoluteSize.Y, 0, 1)) 177 | elseif MouseDownHueGradient then 178 | self:SetHuePos(math.clamp((y-self.HueGradientFrame.AbsolutePosition.Y)/self.HueGradientFrame.AbsoluteSize.Y, 0, 1)) 179 | end 180 | end) 181 | 182 | self.ColorPickerOptions = Instance.new("Frame", self.Parent) 183 | self.ColorPickerOptions.Name = "Color PIcker Options" 184 | self.ColorPickerOptions.BackgroundTransparency = 1 185 | self.ColorPickerOptions.Position = UDim2.fromOffset(315, 30) 186 | self.ColorPickerOptions.Size = UDim2.fromOffset(100, 250) 187 | 188 | self.ColorPreview = Instance.new("Frame", self.ColorPickerOptions) 189 | self.ColorPreview.Name = "ColorPreview" 190 | self.ColorPreview.AnchorPoint = Vector2.new(0.5, 0.5) 191 | ThemeManager.ColorSync(self.ColorPreview, "BorderColor3", Enum.StudioStyleGuideColor.Border) 192 | self.ColorPreview.Position = UDim2.fromOffset(50, 42) 193 | self.ColorPreview.Size = UDim2.fromOffset(75, 75) 194 | 195 | self.RGBInput = InputField.new({NoDropdown = true, ClearBackground = true, Unpausable = true}, self.ColorPickerOptions) 196 | self.RGBInput.Name = "RGBInput" 197 | self.RGBInput.InputFieldContainer.AnchorPoint = Vector2.new(0.5,0.5) 198 | self.RGBInput.InputFieldContainer.Position = UDim2.fromOffset(50,97) 199 | self.RGBInput.InputFieldContainer.Size = UDim2.new(0,100,0,20) 200 | self.RGBInput.InputFieldFrame.Size = UDim2.new(1,0,1,0) 201 | self.RGBInput.Input.TextXAlignment = Enum.TextXAlignment.Center 202 | self.RGBInput:Changed(function(p) 203 | self:SetValue(util.TextToColor3(p), true) 204 | end) 205 | self.RGBInput:LostFocus(function(p) 206 | self:SetValue(util.TextToColor3(p)) 207 | self.RGBInput.Input.TextXAlignment = Enum.TextXAlignment.Center 208 | end) 209 | self.RGBInput:GainedFocus(function() 210 | self.RGBInput.Input.TextXAlignment = Enum.TextXAlignment.Left 211 | ThemeManager.ColorSync(self.RGBInput.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 212 | end) 213 | 214 | self.HexInput = InputField.new({NoDropdown = true, ClearBackground = true, Unpausable = true}, self.ColorPickerOptions) 215 | self.HexInput.Name = "HexInput" 216 | self.HexInput.InputFieldContainer.AnchorPoint = Vector2.new(0.5,0.5) 217 | self.HexInput.InputFieldContainer.Position = UDim2.fromOffset(50,122) 218 | self.HexInput.InputFieldContainer.Size = UDim2.new(0,100,0,20) 219 | self.HexInput.InputFieldFrame.Size = UDim2.new(1,0,1,0) 220 | self.HexInput.Input.TextXAlignment = Enum.TextXAlignment.Center 221 | self.HexInput:Changed(function(p) 222 | local newhex = string.match(p:gsub('#',''), "^%x%x%x%x%x%x$") 223 | if newhex then self:SetValue(Color3.fromHex(newhex), true) end 224 | end) 225 | self.HexInput:LostFocus(function(p) 226 | local newhex = string.match(p:gsub('#',''), "^%x%x%x%x%x%x$") 227 | if newhex then self:SetValue(Color3.fromHex(newhex)) 228 | else self:SetValue() end 229 | self.HexInput.Input.TextXAlignment = Enum.TextXAlignment.Center 230 | end) 231 | self.HexInput:GainedFocus(function() 232 | self.HexInput.Input.TextXAlignment = Enum.TextXAlignment.Left 233 | end) 234 | 235 | self.OKButton = Button.new({Text = "OK", ButtonSize = 1, Unpausable = true}, self.ColorPickerOptions) 236 | self.OKButton.ButtonFrame.AnchorPoint = Vector2.new(0.5,0.5) 237 | self.OKButton.ButtonFrame.Size = UDim2.fromOffset(100,25) 238 | self.OKButton.ButtonFrame.Position = UDim2.fromOffset(50,210) 239 | 240 | self.OKButton:Clicked(function() 241 | self:Destroy() 242 | if self.DoneAction then self.DoneAction(self.Value) end 243 | end) 244 | 245 | self.CancelButton = Button.new({Text = "Cancel", ButtonSize = 1, Unpausable = true}, self.ColorPickerOptions) 246 | self.CancelButton.ButtonFrame.AnchorPoint = Vector2.new(0.5,0.5) 247 | self.CancelButton.ButtonFrame.Size = UDim2.fromOffset(100,25) 248 | self.CancelButton.ButtonFrame.Position = UDim2.fromOffset(50,235) 249 | 250 | self.CancelButton:Clicked(function() 251 | self:Destroy() 252 | if self.DoneAction then self.DoneAction(self.OriginalValue) end 253 | end) 254 | self:OnWindowClose(function() 255 | self:Destroy() 256 | if self.DoneAction then self.DoneAction(self.OriginalValue) end 257 | end) 258 | 259 | self:SetValue(self.Arguments.Value or self.Arguments.Color or Color3.new(1,1,1)) 260 | self.OriginalValue = self.Value 261 | return self 262 | end 263 | 264 | return ColorPrompt -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/ViewButton.lua: -------------------------------------------------------------------------------- 1 | local ChangeHistoryService = game:GetService("ChangeHistoryService") 2 | local GuiService = game:GetService("GuiService") 3 | local ViewButton = {} 4 | ViewButton.__index = ViewButton 5 | 6 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 7 | local util = require(GV.MiscDir.GUIUtil) 8 | local TitlebarButton = require(GV.ObjectsDir.TitlebarButton) 9 | local InputPrompt = require(GV.PromptsDir.InputPrompt) 10 | local InputField = require(GV.ObjectsDir.InputField) 11 | local ColorInput = require(GV.ObjectsDir.ColorInput) 12 | local Labeled = require(GV.ObjectsDir.Labeled) 13 | local TextPrompt = require(GV.PromptsDir.TextPrompt) 14 | local PluginWidget = require(GV.FramesDir.PluginWidget) 15 | local LayoutManager = require(GV.ManagersDir.LayoutManager) 16 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 17 | setmetatable(ViewButton,TitlebarButton) 18 | 19 | local RefreshedMenus = {} 20 | 21 | function ViewButton:CreateThemeEditor(func) 22 | local NewThemePrompt = TextPrompt.new({Title = "Edit Theme", Buttons = {"Save", "Cancel"}, NoPause = true}) 23 | local ThemeColorInput = Labeled.new({ 24 | Object = ColorInput.new({ 25 | Color = ThemeManager.DefaultThemeColor, 26 | NoPause = true 27 | }), 28 | Text = "Theme Color", 29 | LabelSize = 0.5 30 | }, 31 | NewThemePrompt.TextPromptContainer) 32 | ThemeColorInput.Object:SetValue(ThemeManager.ThemeColor) 33 | ThemeColorInput.Object:Changed(function(p) 34 | ThemeManager.ReloadTheme(p, ThemeManager.CurrentAccent) 35 | end) 36 | ThemeColorInput.MainFrame.Size = UDim2.new(1,0,0,28) 37 | local AccentColorInput = Labeled.new({ 38 | Object = ColorInput.new({ 39 | Color = ThemeManager.DefaultAccentColor, 40 | NoPause = true 41 | }), 42 | Text = "Accent Color", 43 | LabelSize = 0.5 44 | }, 45 | NewThemePrompt.TextPromptContainer) 46 | AccentColorInput.Object:SetValue(ThemeManager.AccentColor) 47 | AccentColorInput.Object:Changed(function(p) 48 | ThemeManager.ReloadTheme(ThemeManager.CurrentTheme, p) 49 | end) 50 | AccentColorInput.MainFrame.Size = UDim2.new(1,0,0,28) 51 | NewThemePrompt.Textbox:Destroy() 52 | NewThemePrompt.TextFrame.Size = UDim2.new(0,0,0,10) 53 | NewThemePrompt.ButtonsFrame.Parent = nil 54 | NewThemePrompt.ButtonsFrame.Parent = NewThemePrompt.TextPromptContainer 55 | NewThemePrompt:Clicked(function(p) if func then func(p) end end) 56 | end 57 | 58 | function ViewButton:LoadWidgetOption(Widget, i) 59 | local WidgetTitle = Widget.WidgetObject.Title 60 | local WidgetMenuObject = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), tostring(i) .. ': "' .. WidgetTitle .. '"') 61 | WidgetMenuObject.Name = '"' .. WidgetTitle .. '" Widget Menu' 62 | local ToggleAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Toggle", "", nil, false) 63 | local RenameAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Rename", "", nil, false) 64 | local DeleteAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Delete", "", nil, false) 65 | ToggleAction.Triggered:Connect(function() 66 | Widget.WidgetObject.Enabled = not Widget.WidgetObject.Enabled 67 | end) 68 | RenameAction.Triggered:Connect(function() 69 | Widget:Rename() 70 | end) 71 | DeleteAction.Triggered:Connect(function() 72 | Widget:Delete() 73 | end) 74 | WidgetMenuObject:AddAction(ToggleAction) 75 | WidgetMenuObject:AddAction(RenameAction) 76 | WidgetMenuObject:AddSeparator() 77 | WidgetMenuObject:AddAction(DeleteAction) 78 | ToggleAction.Parent = WidgetMenuObject 79 | RenameAction.Parent = WidgetMenuObject 80 | DeleteAction.Parent = WidgetMenuObject 81 | return WidgetMenuObject 82 | end 83 | 84 | function ViewButton:LoadLayoutOption(Layout, i) 85 | if not Layout.Name then Layout.Name = "Unnamed" end 86 | local SavedLayouts = GV.PluginObject:GetSetting(GV.PluginID.."SavedGUILayouts") or {} 87 | local LayoutMenuObject = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), tostring(i) .. ': "' .. Layout.Name .. '"') 88 | LayoutMenuObject.Name = '"' .. Layout.Name .. '" Layout Menu' 89 | local UseLayoutAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Use", "", nil, false) 90 | local SaveAsAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Save As", "", nil, false) 91 | local RenameAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Rename", "", nil, false) 92 | local DeleteAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Delete", "", nil, false) 93 | UseLayoutAction.Triggered:Connect(function() 94 | local OverridePrompt = TextPrompt.new({Title = "Override Layout", Text = "Are you sure you want to override the current GUI layout?", Buttons = {"Yes", "No"}}) 95 | OverridePrompt:Clicked(function(p) 96 | if p == 2 or p == 0 then return end 97 | LayoutManager.RecallLayout(Layout) 98 | end) 99 | end) 100 | SaveAsAction.Triggered:Connect(function() 101 | local CurrentLayout = LayoutManager.GetLayout() 102 | CurrentLayout.Name = Layout.Name 103 | SavedLayouts[i] = CurrentLayout 104 | GV.PluginObject:SetSetting(GV.PluginID.."SavedGUILayouts", SavedLayouts) 105 | end) 106 | RenameAction.Triggered:Connect(function() 107 | local RenamePrompt = InputPrompt.new({Title = "Rename Layout ", Text = "Type in a new name:", Buttons = {"OK", "Cancel"}, InputField = InputField.new({Placeholder = "New name", Value = Layout.Name, NoDropdown = true, Unpausable = true})}) 108 | RenamePrompt:Clicked(function(p) 109 | if p == 2 or p == 0 then return end 110 | Layout.Name = RenamePrompt.Input.Text 111 | SavedLayouts[i] = Layout 112 | GV.PluginObject:SetSetting(GV.PluginID.."SavedGUILayouts", SavedLayouts) 113 | end) 114 | end) 115 | DeleteAction.Triggered:Connect(function() 116 | local DeletePrompt = TextPrompt.new({Title = "Delete " .. Layout.Name, Text = 'Are you sure you want to delete "' .. Layout.Name .. '"?', Buttons = {"Yes", "No"}}) 117 | DeletePrompt:Clicked(function(p) 118 | if p == 2 or p == 0 then return end 119 | table.remove(SavedLayouts, i) 120 | GV.PluginObject:SetSetting(GV.PluginID.."SavedGUILayouts", SavedLayouts) 121 | end) 122 | end) 123 | LayoutMenuObject:AddAction(UseLayoutAction) 124 | LayoutMenuObject:AddAction(SaveAsAction) 125 | LayoutMenuObject:AddAction(RenameAction) 126 | LayoutMenuObject:AddSeparator() 127 | LayoutMenuObject:AddAction(DeleteAction) 128 | UseLayoutAction.Parent = LayoutMenuObject 129 | SaveAsAction.Parent = LayoutMenuObject 130 | RenameAction.Parent = LayoutMenuObject 131 | DeleteAction.Parent = LayoutMenuObject 132 | return LayoutMenuObject 133 | end 134 | 135 | function ViewButton:LoadThemeOption(Theme, i) 136 | local SavedThemes = GV.PluginObject:GetSetting("SavedGUIThemes") or ThemeManager.PreinstalledThemes 137 | local ThemeMenuObject = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), tostring(i) .. ': "' .. Theme.Name .. '"') 138 | ThemeMenuObject.Name = '"' .. Theme.Name .. '" Theme Menu' 139 | local UseThemeAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Use", "", nil, false) 140 | local EditAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Edit", "", nil, false) 141 | local RenameAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Rename", "", nil, false) 142 | local DeleteAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Delete", "", nil, false) 143 | UseThemeAction.Triggered:Connect(function() 144 | local OverridePrompt = TextPrompt.new({Title = "Override Theme", Text = "Are you sure you want to override the current GUI theme?", Buttons = {"Yes", "No"}}) 145 | OverridePrompt:Clicked(function(p) 146 | if p == 2 or p == 0 then return end 147 | ThemeManager.UpdateTheme(util.TableToColor3(Theme.Theme), util.TableToColor3(Theme.Accent)) 148 | end) 149 | end) 150 | EditAction.Triggered:Connect(function() 151 | self:CreateThemeEditor(function(p) 152 | if p == 2 or p == 0 then ThemeManager.ReloadTheme(ThemeManager.ThemeColor, ThemeManager.AccentColor) return end 153 | ThemeManager.UpdateTheme() 154 | SavedThemes[i] = {["Name"] = Theme.Name, ["Theme"] = util.Color3ToTable(ThemeManager.ThemeColor), ["Accent"] = util.Color3ToTable(ThemeManager.AccentColor)} 155 | GV.PluginObject:SetSetting("SavedGUIThemes", SavedThemes) 156 | end) 157 | end) 158 | RenameAction.Triggered:Connect(function() 159 | local RenamePrompt = InputPrompt.new({Title = "Rename Theme", Text = "Type in a new name:", Buttons = {"OK", "Cancel"}, InputField = InputField.new({Placeholder = "New name", Value = Theme.Name, NoDropdown = true, Unpausable = true})}) 160 | RenamePrompt:Clicked(function(p) 161 | if p == 2 or p == 0 then return end 162 | Theme.Name = RenamePrompt.Input.Text 163 | SavedThemes[i] = Theme 164 | GV.PluginObject:SetSetting("SavedGUIThemes", SavedThemes) 165 | end) 166 | end) 167 | DeleteAction.Triggered:Connect(function() 168 | local DeletePrompt = TextPrompt.new({Title = "Delete " .. Theme.Name, Text = 'Are you sure you want to delete "' .. Theme.Name .. '"?', Buttons = {"Yes", "No"}}) 169 | DeletePrompt:Clicked(function(p) 170 | if p == 2 or p == 0 then return end 171 | table.remove(SavedThemes, i) 172 | GV.PluginObject:SetSetting("SavedGUIThemes", SavedThemes) 173 | end) 174 | end) 175 | ThemeMenuObject:AddAction(UseThemeAction) 176 | ThemeMenuObject:AddAction(EditAction) 177 | ThemeMenuObject:AddAction(RenameAction) 178 | ThemeMenuObject:AddSeparator() 179 | ThemeMenuObject:AddAction(DeleteAction) 180 | UseThemeAction.Parent = ThemeMenuObject 181 | EditAction.Parent = ThemeMenuObject 182 | RenameAction.Parent = ThemeMenuObject 183 | DeleteAction.Parent = ThemeMenuObject 184 | return ThemeMenuObject 185 | end 186 | 187 | function ViewButton:CreateMenu() 188 | self.PluginMenu = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "View Menu") 189 | self.PluginMenu.Name = "View Menu" 190 | 191 | -- Saved Layouts Menu 192 | self.LayoutsMenu = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "Layouts") 193 | self.LayoutsMenu.Name = "Layout Menu" 194 | local SaveCurrentLayout = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Save Layout", "", nil, false) 195 | SaveCurrentLayout.Triggered:Connect(function() 196 | local SavedLayouts = GV.PluginObject:GetSetting(GV.PluginID.."SavedGUILayouts") or {} 197 | local NamePrompt = InputPrompt.new({Title = "Name Layout ", Text = "Type in a name for this layout:", Buttons = {"OK", "Cancel"}, InputField = InputField.new({Placeholder = "New name", NoDropdown = true, Unpausable = true})}) 198 | NamePrompt:Clicked(function(p) 199 | if p == 2 or p == 0 then return end 200 | local NewLayout = LayoutManager.GetLayout() 201 | NewLayout.Name = NamePrompt.Input.Text 202 | SavedLayouts[#SavedLayouts+1] = NewLayout 203 | GV.PluginObject:SetSetting(GV.PluginID.."SavedGUILayouts", SavedLayouts) 204 | end) 205 | end) 206 | local ResetLayoutAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Reset Layout", "", nil, false) 207 | ResetLayoutAction.Triggered:Connect(function() 208 | local OverridePrompt = TextPrompt.new({Title = "Override Layout", Text = "Are you sure you want to override the current GUI layout?", Buttons = {"Yes", "No"}}) 209 | OverridePrompt:Clicked(function(p) 210 | if p == 2 or p == 0 then return end 211 | LayoutManager.ResetLayout() 212 | end) 213 | end) 214 | self.LayoutsMenu:AddAction(SaveCurrentLayout) 215 | self.LayoutsMenu:AddAction(ResetLayoutAction) 216 | self.LayoutsMenu:AddSeparator() 217 | SaveCurrentLayout.Parent = self.LayoutsMenu 218 | ResetLayoutAction.Parent = self.LayoutsMenu 219 | self.PluginMenu:AddMenu(self.LayoutsMenu) 220 | 221 | -- Widgets Menu 222 | self.WidgetsMenu = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "Widgets") 223 | self.WidgetsMenu.Name = "Widget Menu" 224 | local CreateNewWindowAction = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "Create New Window", "", nil, false) 225 | CreateNewWindowAction.Triggered:Connect(function() 226 | PluginWidget.new({Enabled = true}) 227 | end) 228 | self.WidgetsMenu:AddAction(CreateNewWindowAction) 229 | self.WidgetsMenu:AddSeparator() 230 | CreateNewWindowAction.Parent = self.WidgetsMenu 231 | self.LayoutsMenu:AddMenu(self.WidgetsMenu) 232 | self.LayoutsMenu:AddSeparator() 233 | 234 | -- Appearance/Themes 235 | self.ThemesMenu = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "Themes") 236 | self.ThemesMenu.Name = "Themes Menu" 237 | local NewTheme = GV.PluginObject:CreatePluginAction(game:GetService("HttpService"):GenerateGUID(false), "New Theme", "", nil, false) 238 | NewTheme.Triggered:Connect(function() 239 | self:CreateThemeEditor(function(p) 240 | if p == 2 or p == 0 then ThemeManager.ReloadTheme(ThemeManager.ThemeColor, ThemeManager.AccentColor) return end 241 | ThemeManager.UpdateTheme() 242 | local NamePrompt = InputPrompt.new({Title = "Name Layout ", Text = "Type in a name for this theme:", Buttons = {"OK", "Cancel"}, InputField = InputField.new({Placeholder = "New name", NoDropdown = true, Unpausable = true})}) 243 | NamePrompt:Clicked(function(p) 244 | if p == 2 or p == 0 then return end 245 | local SavedThemes = GV.PluginObject:GetSetting("SavedGUIThemes") or ThemeManager.PreinstalledThemes 246 | SavedThemes[#SavedThemes+1] = {Name = NamePrompt.Input.Text, Theme = util.Color3ToTable(ThemeManager.CurrentTheme), Accent = util.Color3ToTable(ThemeManager.CurrentAccent)} 247 | GV.PluginObject:SetSetting("SavedGUIThemes", SavedThemes) 248 | end) 249 | end) 250 | end) 251 | self.ThemesMenu:AddAction(NewTheme) 252 | self.ThemesMenu:AddSeparator() 253 | self.PluginMenu:AddMenu(self.ThemesMenu) 254 | 255 | end 256 | 257 | function ViewButton:RefreshMenu() 258 | for _, v in pairs(RefreshedMenus) do 259 | v:Destroy() 260 | end 261 | RefreshedMenus = {} 262 | for i,Widget in pairs(GV.PluginWidgets) do 263 | local LoadedOption = self:LoadWidgetOption(Widget, i) 264 | RefreshedMenus[#RefreshedMenus+1] = LoadedOption 265 | self.WidgetsMenu:AddMenu(LoadedOption) 266 | end 267 | local SavedLayouts = GV.PluginObject:GetSetting(GV.PluginID.."SavedGUILayouts") or {} 268 | for i,Layout in pairs(SavedLayouts) do 269 | local LoadedOption = self:LoadLayoutOption(Layout, i) 270 | RefreshedMenus[#RefreshedMenus+1] = LoadedOption 271 | self.LayoutsMenu:AddMenu(LoadedOption) 272 | end 273 | local SavedThemes = GV.PluginObject:GetSetting("SavedGUIThemes") or ThemeManager.PreinstalledThemes 274 | for i,Theme in pairs(SavedThemes) do 275 | local LoadedTheme = self:LoadThemeOption(Theme, i) 276 | RefreshedMenus[#RefreshedMenus+1] = LoadedTheme 277 | self.ThemesMenu:AddMenu(LoadedTheme) 278 | end 279 | end 280 | 281 | function ViewButton.new() 282 | local self = TitlebarButton.new({Name = "VIEW"}) 283 | setmetatable(self,ViewButton) 284 | self:CreateMenu() 285 | self:Clicked(function() 286 | self:RefreshMenu() 287 | end) 288 | return self 289 | end 290 | 291 | return ViewButton -------------------------------------------------------------------------------- /src/rblxgui/lib/Objects/InputField.lua: -------------------------------------------------------------------------------- 1 | local InputField = {} 2 | InputField.__index = InputField 3 | 4 | local GV = require(script.Parent.Parent.PluginGlobalVariables) 5 | local util = require(GV.MiscDir.GUIUtil) 6 | local GUIObject = require(GV.ObjectsDir.GUIObject) 7 | local ScrollingFrame = require(GV.FramesDir.ScrollingFrame) 8 | local KeybindManager = require(GV.ManagersDir.KeybindManager) 9 | local ThemeManager = require(GV.ManagersDir.ThemeManager) 10 | local InputManager = require(GV.ManagersDir.InputManager) 11 | setmetatable(InputField,GUIObject) 12 | 13 | local RightClickMenu = GV.PluginObject:CreatePluginMenu(game:GetService("HttpService"):GenerateGUID(false), "RightClickMenu - InputField") 14 | RightClickMenu.Name = "InputField Right-Click Menu" 15 | RightClickMenu:AddNewAction("Edit", "Edit") 16 | RightClickMenu:AddNewAction("Clear", "Clear Input") 17 | 18 | 19 | InputField.Images = { 20 | Down = "http://www.roblox.com/asset/?id=10027472547" 21 | } 22 | 23 | function InputField:SetDisabled(State) 24 | self.Disabled = State 25 | if self.Disabled then 26 | if self.DropdownOpen then self:SetDropdown(false) end 27 | self.InputFieldFrame.BackgroundTransparency, self.Input.TextTransparency, self.DropdownButton.BackgroundTransparency = 0.5,0.5,0.5 28 | else 29 | self.InputFieldFrame.BackgroundTransparency, self.Input.TextTransparency, self.DropdownButton.BackgroundTransparency = 0,0,0 30 | end 31 | if self.TextboxEditable then 32 | self.Input.TextEditable = not State 33 | end 34 | end 35 | 36 | function InputField:ToggleDisable() 37 | self:SetDisabled(not self.Disabled) 38 | end 39 | 40 | function InputField:ToggleDropdown() 41 | self:SetDropdown(not self.DropdownOpen) 42 | end 43 | 44 | function InputField:SetDropdown(State) 45 | self.DropdownOpen = State 46 | self.DropdownFrame.Visible = State 47 | if State then 48 | self.Parent.ZIndex = 2 49 | self.InputFieldFrame.ZIndex = 3 50 | self.DropdownButton.ZIndex = 3 51 | self.DropdownImage.ZIndex = 3 52 | self.Input.ZIndex = 4 53 | 54 | else 55 | self.Parent.ZIndex = 0 56 | self.InputFieldFrame.ZIndex = 0 57 | self.DropdownImage.ZIndex = 0 58 | self.DropdownButton.ZIndex = 0 59 | self.Input.ZIndex = 0 60 | 61 | end 62 | if self.DropdownAction then self.DropdownAction(State) end 63 | end 64 | 65 | function InputField.GenerateInstanceList(Instances) 66 | if typeof(Instances) == "Instance" then Instances = {Instances} end 67 | local GeneratedList = Instances[1].Name 68 | for i, v in pairs(Instances) do 69 | if i ~= 1 then 70 | GeneratedList = GeneratedList .. ", " .. v.Name 71 | end 72 | end 73 | return GeneratedList 74 | end 75 | 76 | function InputField.GetItemInfo(Item) 77 | local ItemInfo = Item or "" 78 | if not (typeof(ItemInfo) == "table") then ItemInfo = {Value = Item, Name = Item} end 79 | if (not ItemInfo.Value) and (not ItemInfo.Name) then ItemInfo = {Value = ItemInfo} end 80 | ItemInfo.Value = ItemInfo.Value or ItemInfo.Name 81 | ItemInfo.Name = ItemInfo.Name or ItemInfo.Value 82 | if typeof(ItemInfo.Name) ~= "string" and typeof(ItemInfo.Name) ~= "number" then 83 | if typeof(ItemInfo.Value) == "table" then 84 | if #ItemInfo.Value < 1 then return {Value = "", Name = ""} end 85 | if typeof(ItemInfo.Value[1]) == "Instance" then 86 | ItemInfo.Name = InputField.GenerateInstanceList(ItemInfo.Value) 87 | else 88 | ItemInfo.Name = nil 89 | end 90 | elseif typeof(ItemInfo.Value) == "Instance" then 91 | ItemInfo.Name = ItemInfo.Value.Name 92 | ItemInfo.Value = {ItemInfo.Value} 93 | elseif typeof(ItemInfo.Value) == "EnumItem" then 94 | ItemInfo.Name = ItemInfo.Value.Name 95 | else 96 | ItemInfo.Name = tostring(ItemInfo.Value) 97 | end 98 | end 99 | return ItemInfo 100 | end 101 | 102 | function InputField:AddItem(Item, Action) 103 | local ItemInfo = self.GetItemInfo(Item) 104 | local ItemButton = Instance.new("TextButton", self.DropdownScroll.Content) 105 | ItemButton.Name = ItemInfo.Name 106 | ItemButton.Size = UDim2.new(1,0,0,20) 107 | ItemButton.BorderSizePixel = 0 108 | ThemeManager.ColorSync(ItemButton, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 109 | ItemButton.Text = "" 110 | local ItemLabel = Instance.new("TextLabel", ItemButton) 111 | ItemLabel.BackgroundTransparency = 1 112 | ThemeManager.ColorSync(ItemLabel, "TextColor3", Enum.StudioStyleGuideColor.MainText) 113 | ItemLabel.Font = Enum.Font.SourceSans 114 | ItemLabel.TextSize = 14 115 | ItemLabel.Text = ItemInfo.Name 116 | ItemLabel.AnchorPoint = Vector2.new(0.5,0.5) 117 | ItemLabel.Position = UDim2.new(0.5,0,0.5,0) 118 | ItemLabel.Size = UDim2.new(1,-8,0,14) 119 | ItemButton.ZIndex = 2 120 | ItemLabel.ZIndex = 2 121 | ItemLabel.TextXAlignment = Enum.TextXAlignment.Left 122 | util.HoverIcon(ItemButton) 123 | self.DropdownButton.MouseButton1Click:Connect(function() if not self.Disabled then ItemButton.Visible = true end end) 124 | self.Input.Changed:Connect(function(p) 125 | if p == "Text" and self.Filtering then 126 | if self.Input.Text == "" or string.sub(ItemInfo.Name, 1, string.len(self.Input.Text)) == self.Input.Text then 127 | ItemButton.Visible = true 128 | else 129 | ItemButton.Visible = false 130 | end 131 | end 132 | end) 133 | ItemButton.MouseButton1Click:Connect(function() 134 | if self.Disabled then return end 135 | self:SetDropdown(false) 136 | self.SelectedItem = true 137 | self.Value = ItemInfo.Value 138 | self.Input.Text = ItemInfo.Name 139 | if Action then 140 | Action() 141 | end 142 | end) 143 | ItemButton.MouseEnter:Connect(function() 144 | task.wait(0) 145 | if self.Disabled then return end 146 | if self.ItemEnterAction then self.ItemEnterAction(ItemInfo.Value) end 147 | end) 148 | ItemButton.MouseLeave:Connect(function() 149 | if self.Disabled then return end 150 | if self.ItemLeaveAction then self.ItemLeaveAction(ItemInfo.Value) end 151 | end) 152 | end 153 | 154 | function InputField:AddItems(Items, Action) 155 | for _, v in pairs(Items) do self:AddItem(v, Action) end 156 | end 157 | 158 | function InputField:ClearItems() 159 | for _, v in pairs(self.DropdownScroll.Content:GetChildren()) do 160 | if v:IsA("TextButton") then v:Destroy() end 161 | end 162 | end 163 | 164 | function InputField:RemoveItem(Item) 165 | local Target = self.DropdownScroll.Content:FindFirstChild(Item) 166 | if Target then 167 | Target:Destroy() 168 | end 169 | end 170 | 171 | function InputField:RemoveItems(Items) 172 | for _, v in pairs(Items) do self:RemoveItem(v) end 173 | end 174 | 175 | function InputField:SetValue(Item) 176 | local ItemInfo = self.GetItemInfo(Item) 177 | if self.Value == ItemInfo.Value then return end 178 | self.SelectedItem = true 179 | self.Value = ItemInfo.Value 180 | self.Input.Text = ItemInfo.Name or "" 181 | end 182 | 183 | function InputField:Changed(func) 184 | self.Action = func 185 | end 186 | 187 | function InputField:MouseEnterItem(func) 188 | self.ItemEnterAction = func 189 | end 190 | 191 | function InputField:MouseLeaveItem(func) 192 | self.ItemLeaveAction = func 193 | end 194 | 195 | function InputField:DropdownToggled(func) 196 | self.DropdownAction = func 197 | end 198 | 199 | function InputField:LostFocus(func) 200 | self.LostFocusAction = func 201 | end 202 | 203 | function InputField:GainedFocus(func) 204 | self.FocusedAction = func 205 | end 206 | 207 | -- Placeholder, Value, Items, InputSize, NoDropdown, NoFiltering, DisableEditing, ClearBackground, ClearText, Disabled 208 | function InputField.new(Arguments, Parent) 209 | local self = GUIObject.new(Arguments, Parent) 210 | setmetatable(self,InputField) 211 | self.DefaultEmpty = "" 212 | self.Action = nil 213 | self.Filtering = not self.Arguments.NoFiltering 214 | self.InputFieldContainer = Instance.new("Frame", self.Parent) 215 | self.InputFieldContainer.BackgroundTransparency = 1 216 | self.InputFieldContainer.Name = "InputFieldContainer" 217 | self.InputFieldFrame = Instance.new("Frame", self.InputFieldContainer) 218 | self.InputFieldFrame.BackgroundTransparency = 1 219 | local Size = util.GetScale(self.Arguments.InputSize) or UDim.new(1,-12) 220 | self.InputFieldFrame.Size = UDim2.new(Size.Scale,Size.Offset,0,20) 221 | self.InputFieldFrame.Position = UDim2.new(0.5,0,0.5,0) 222 | self.InputFieldFrame.AnchorPoint = Vector2.new(0.5,0.5) 223 | self.InputFieldFrame.Name = "InputFieldFrame" 224 | if self.Arguments.ClearBackground then 225 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.MainBackground) 226 | ThemeManager.ColorSync(self.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.MainBackground) 227 | else 228 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 229 | ThemeManager.ColorSync(self.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 230 | end 231 | self.Input = Instance.new("TextBox", self.InputFieldFrame) 232 | self.Input.TextTruncate = Enum.TextTruncate.AtEnd 233 | self.Input.BackgroundTransparency = 1 234 | if self.Arguments.NoDropdown then self.Input.Size = UDim2.new(1,-10,1,0) else self.Input.Size = UDim2.new(1,-30,1,0) end 235 | self.Input.Font = Enum.Font.SourceSans 236 | self.Input.TextSize = 14 237 | if self.Arguments.Placeholder then self.Input.PlaceholderText = self.Arguments.Placeholder end 238 | self.Input.TextXAlignment = Enum.TextXAlignment.Left 239 | self.Input.Position = UDim2.new(0,5,0,0) 240 | self.Input.ClearTextOnFocus = self.Arguments.ClearText 241 | self.Input.Name = "Input" 242 | self.Input.Changed:Connect(function(p) 243 | if p == "Text" then 244 | if not self.SelectedItem and not self.IgnoreText then 245 | self.Value = self.Input.Text 246 | end 247 | self.SelectedItem = false 248 | if self.Value == "" then self.Value = self.DefaultEmpty end 249 | if self.Action then 250 | self.Action(self.Value) 251 | end 252 | end 253 | end) 254 | self.Focusable = true 255 | self.TextEditable = true 256 | if self.Arguments.DisableEditing then 257 | self.Input.TextEditable = false 258 | self.TextboxEditable = false 259 | self.Focusable = false 260 | self.TextEditable = false 261 | end 262 | ThemeManager.ColorSync(self.Input, "TextColor3", Enum.StudioStyleGuideColor.MainText) 263 | ThemeManager.ColorSync(self.Input, "PlaceholderColor3", Enum.StudioStyleGuideColor.DimmedText) 264 | self.MouseInInput = false 265 | self.InputFieldFrame.MouseMoved:Connect(function() 266 | self.MouseInInput = true 267 | if not self.Disabled and not self.Input:IsFocused() and not self.Focused then 268 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder, Enum.StudioStyleGuideModifier.Hover) 269 | if self.Arguments.ClearBackground then 270 | ThemeManager.ColorSync(self.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBorder, Enum.StudioStyleGuideModifier.Hover) 271 | end 272 | elseif self.Focusable then 273 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Forbidden" 274 | end 275 | end) 276 | self.InputFieldFrame.MouseLeave:Connect(function() 277 | self.MouseInInput = false 278 | if not self.Disabled and not self.Input:IsFocused() and not self.Focused then 279 | if self.Arguments.ClearBackground then 280 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.MainBackground) 281 | ThemeManager.ColorSync(self.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.MainBackground) 282 | else 283 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 284 | end 285 | end 286 | GV.PluginObject:GetMouse().Icon = "rbxasset://SystemCursors/Arrow" 287 | end) 288 | self.Input.Focused:Connect(function() 289 | KeybindManager.Unfocus() 290 | if not self.Disabled and self.Focusable then 291 | if self.FocusedAction then self.FocusedAction(self.Value) end 292 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder, Enum.StudioStyleGuideModifier.Selected, true) 293 | ThemeManager.ColorSync(self.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 294 | else 295 | self.Input:ReleaseFocus() 296 | end 297 | end) 298 | self.Input.FocusLost:Connect(function() 299 | if self.Focusable then 300 | if self.LostFocusAction then self.LostFocusAction(self.Value) end 301 | if self.Arguments.ClearBackground then 302 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.MainBackground) 303 | ThemeManager.ColorSync(self.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.MainBackground) 304 | else 305 | ThemeManager.ColorSync(self.InputFieldFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 306 | ThemeManager.ColorSync(self.InputFieldFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 307 | end 308 | end 309 | end) 310 | self.DropdownButton = Instance.new("TextButton", self.InputFieldFrame) 311 | if self.Arguments.NoDropdown then self.DropdownButton.Visible = false end 312 | self.DropdownButton.Text = "" 313 | ThemeManager.ColorSync(self.DropdownButton, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 314 | self.DropdownButton.BorderSizePixel = 0 315 | self.DropdownButton.Size = UDim2.new(0, 20, 0, 20) 316 | self.DropdownButton.AnchorPoint = Vector2.new(1,0) 317 | self.DropdownButton.Position = UDim2.new(1, 0, 0, 0) 318 | self.DropdownButton.Name = "DropdownButton" 319 | util.HoverIcon(self.DropdownButton) 320 | self.DropdownButton.MouseButton1Click:Connect(function() if not self.Disabled then self:ToggleDropdown() end end) 321 | self.MouseInDropdownButton = false 322 | self.DropdownButton.MouseEnter:Connect(function() self.MouseInDropdownButton = true end) 323 | self.DropdownButton.MouseLeave:Connect(function() self.MouseInDropdownButton = false end) 324 | self.DropdownImage = Instance.new("ImageLabel", self.DropdownButton) 325 | self.DropdownImage.Name = "Dropdown Image" 326 | self.DropdownImage.AnchorPoint = Vector2.new(0.5,0.5) 327 | self.DropdownImage.BackgroundTransparency = 1 328 | self.DropdownImage.Position = UDim2.new(0.5,0,0.5,0) 329 | self.DropdownImage.Size = UDim2.new(0,4.5,0,4.5) 330 | self.DropdownImage.Image = self.Images.Down 331 | self.DropdownFrame = Instance.new("Frame", self.InputFieldFrame) 332 | self.DropdownFrame.Size = UDim2.new(1,0,0,0) 333 | self.DropdownFrame.Position = UDim2.new(0,0,1,0) 334 | ThemeManager.ColorSync(self.DropdownFrame, "BackgroundColor3", Enum.StudioStyleGuideColor.InputFieldBackground) 335 | ThemeManager.ColorSync(self.DropdownFrame, "BorderColor3", Enum.StudioStyleGuideColor.InputFieldBorder) 336 | self.DropdownFrame.Visible = false 337 | self.DropdownFrame.Name = "DropdownFrame" 338 | self.MouseInDropdownMenu = false 339 | self.DropdownFrame.MouseEnter:Connect(function() self.MouseInDropdownMenu = true end) 340 | self.DropdownFrame.MouseLeave:Connect(function() self.MouseInDropdownMenu = false end) 341 | self.DropdownFrame.ZIndex = 2 342 | self.DropdownScroll = ScrollingFrame.new({BarSize = 10}, self.DropdownFrame) 343 | self:SetDropdown(false) 344 | self.DropdownMaxY = 100 345 | local function syncframe() 346 | if self.DropdownScroll.Layout.AbsoluteContentSize.Y > self.DropdownMaxY then 347 | self.DropdownFrame.Size = UDim2.new(1,0,0,self.DropdownMaxY) 348 | return 349 | end 350 | self.DropdownFrame.Size = UDim2.new(1,0,0,self.DropdownScroll.Layout.AbsoluteContentSize.Y) 351 | end 352 | self.DropdownScroll.Layout.Changed:Connect(function(p) 353 | if p == "AbsoluteContentSize" then syncframe() end 354 | end) 355 | syncframe() 356 | InputManager.AddInputEvent("InputBegan", function(p) 357 | task.wait(0) 358 | if self.DropdownOpen and p.UserInputType == Enum.UserInputType.MouseButton1 and not self.MouseInDropdownMenu and not self.MouseInDropdownButton then 359 | self:SetDropdown(false) 360 | end 361 | if self.TextEditable and p.UserInputType == Enum.UserInputType.MouseButton2 and self.MouseInInput then 362 | local Response = RightClickMenu:ShowAsync() 363 | if Response then 364 | if Response.Text == "Clear Input" then self.Input.Text = "" 365 | elseif Response.Text == "Edit" then self.Input:CaptureFocus() end 366 | end 367 | end 368 | end) 369 | local Value = self.Arguments.Value or self.Arguments.CurrentItem or "" 370 | self:SetValue(Value) 371 | if self.Arguments.Items then self:AddItems(self.Arguments.Items) end 372 | self:SetDisabled(self.Arguments.Disabled) 373 | self.Object = self.Input 374 | self.MainMovable = self.InputFieldContainer 375 | return self 376 | end 377 | 378 | return InputField --------------------------------------------------------------------------------