Dex Final Version - Lua
Dex Final Version - Lua
com/LorekeeperZinnia/Dex
--[[
New Dex
Final Version
Developed by Moon
Modified for Infinite Yield
Dex is a debugging suite designed to help the user debug games and find any
potential vulnerabilities.
If you want more info, you can join the server: https://discord.io/zinnia
Note that very limited to no support will be provided.
]]
local nodes = {}
local selection
local clonerefs = cloneref or function(...) return ... end
local EmbeddedModules = {
Explorer = function()
--[[
Explorer App Module
-- Common Locals
local Main,Lib,Apps,Settings -- Main Containers
local Explorer, Properties, ScriptViewer, Notebook -- Major Apps
local API,RMD,env,service,plr,create,createSimple -- Main Locals
API = data.API
RMD = data.RMD
env = data.env
service = data.service
plr = data.plr
create = data.create
createSimple = data.createSimple
end
addObject = function(root)
if nodes[root] then return end
-- Nil Handling
if not par then
if nilMap[root] then
nilCons[root] = nilCons[root] or {
connectSignal(root.ChildAdded,addObject),
connectSignal(root.AncestryChanged,moveObject),
}
par = nilNode
isNil = true
else
return
end
elseif nilMap[rootParObj] or par == nilNode then
nilMap[root] = true
nilCons[root] = nilCons[root] or {
connectSignal(root.ChildAdded,addObject),
connectSignal(root.AncestryChanged,moveObject),
}
isNil = true
end
table.insert(par,pos,newNode)
else
par[#par+1] = newNode
par.Sorted = nil
end
-- Nil Handling
if isNil then
nilMap[obj] = true
nilCons[obj] = nilCons[obj] or {
connectSignal(obj.ChildAdded,addObject),
connectSignal(obj.AncestryChanged,moveObject),
}
end
end
removeObject = function(root)
local node = nodes[root]
if not node then return end
-- Nil Handling
if nilMap[node.Obj] then
moveObject(node.Obj)
return
end
moveObject = function(obj)
local node = nodes[obj]
if not node then return end
-- Nil Handling
if not newPar then
if nilMap[obj] then
newPar = nilNode
else
return
end
elseif nilMap[newPar.Obj] or newPar == nilNode then
nilMap[obj] = true
nilCons[obj] = nilCons[obj] or {
connectSignal(obj.ChildAdded,addObject),
connectSignal(obj.AncestryChanged,moveObject),
}
end
if oldPar then
local parPos = table.find(oldPar,node)
if parPos then table.remove(oldPar,parPos) end
end
node.Id = nil
node.Parent = newPar
table.insert(newPar,pos,node)
else
newPar[#newPar+1] = node
newPar.Sorted = nil
end
Explorer.ViewWidth = 0
Explorer.Index = 0
Explorer.EntryIndent = 20
Explorer.FreeWidth = 32
Explorer.GuiElems = {}
Explorer.InitRenameBox = function()
renameBox = create({{1,"TextBox",
{BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),Bo
rderColor3=Color3.new(0.062745101749897,0.51764708757401,1),BorderMode=2,ClearTextO
nFocus=false,Font=3,Name="RenameBox",PlaceholderColor3=Color3.new(0.69803923368454,
0.69803923368454,0.69803923368454),Position=UDim2.new(0,26,0,2),Size=UDim2.new(0,20
0,0,16),Text="",TextColor3=Color3.new(1,1,1),TextSize=14,TextXAlignment=0,Visible=f
alse,ZIndex=2}}})
renameBox.Parent = Explorer.Window.GuiElems.Content.List
renameBox.FocusLost:Connect(function()
if not renamingNode then return end
renameBox.Focused:Connect(function()
renameBox.SelectionStart = 1
renameBox.CursorPosition = #renameBox.Text + 1
end)
end
Explorer.SetRenamingNode = function(node)
renamingNode = node
renameBox.Text = tostring(node.Obj)
renameBox:CaptureFocus()
Explorer.Refresh()
end
Explorer.SetSortingEnabled = function(val)
sortingEnabled = val
Settings.Explorer.Sorting = val
end
Explorer.UpdateView = function()
local maxNodes = math.ceil(treeFrame.AbsoluteSize.Y / 20)
local maxX = treeFrame.AbsoluteSize.X
local totalWidth = Explorer.ViewWidth + Explorer.FreeWidth
scrollV.VisibleSpace = maxNodes
scrollV.TotalSpace = #tree + 1
scrollH.VisibleSpace = maxX
scrollH.TotalSpace = totalWidth
renameBox.Size = UDim2.new(0,maxX-100,0,16)
Explorer.Index = scrollV.Index
end
end
Explorer.NodeSorter = function(a,b)
if a.Del or b.Del then return false end -- Ghost node
Explorer.Update = function()
table.clear(tree)
local maxNameWidth,maxDepth,count = 0,1,1
local nameCache = {}
local font = Enum.Font.SourceSans
local size = Vector2.new(math.huge,20)
local useNameWidth = Settings.Explorer.UseNameWidth
local tSort = table.sort
local sortFunc = Explorer.NodeSorter
local isSearching = (expanded == Explorer.SearchExpanded)
local textServ = service.TextService
if useNameWidth then
local nameWidth = n.NameWidth
if not nameWidth then
local objName = tostring(n.Obj)
nameWidth = nameCache[objName]
if not nameWidth then
nameWidth =
getTextSize(textServ,objName,14,font,size).X
nameCache[objName] = nameWidth
end
n.NameWidth = nameWidth
end
if nameWidth > maxNameWidth then
maxNameWidth = nameWidth
end
end
tree[count] = n
count = count + 1
if expanded[n] and #n > 0 then
recur(n,depth)
end
end
end
recur(nodes[game],1)
-- Nil Instances
if env.getnilinstances then
if not (isSearching and not searchResults[nilNode]) then
tree[count] = nilNode
count = count + 1
if expanded[nilNode] then
recur(nilNode,2)
end
end
end
Explorer.MaxNameWidth = maxNameWidth
Explorer.MaxDepth = maxDepth
Explorer.ViewWidth = useNameWidth and Explorer.EntryIndent*maxDepth +
maxNameWidth + 26 or Explorer.EntryIndent*maxDepth + 226
Explorer.UpdateView()
end
Explorer.StartDrag = function(offX,offY)
if Explorer.Dragging then return end
Explorer.Dragging = true
for i = 1,#listEntries do
local entry = listEntries[i]
if Lib.CheckMouseInGui(entry) then
dragOutline.Position =
UDim2.new(0,entry.Indent.Position.X.Offset-scrollH.Index,0,entry.Position.Y.Offset)
dragOutline.Size = UDim2.new(0,entry.Size.X.Offset-
entry.Indent.Position.X.Offset,0,20)
dragOutline.Visible = true
return
end
end
dragOutline.Visible = false
end
move()
mouseEvent = input.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
move()
end
end)
releaseEvent = input.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
newGui:Destroy()
dragOutline:Destroy()
Explorer.Dragging = false
for i = 1,#listEntries do
if Lib.CheckMouseInGui(listEntries[i]) then
local node = tree[i + Explorer.Index]
if node then
if selection.Map[node] then return end
local newPar = node.Obj
local sList = selection.List
for i = 1,#sList do
local n = sList[i]
pcall(function() n.Obj.Parent =
newPar end)
end
Explorer.ViewNode(sList[1])
end
break
end
end
end
end)
end
Explorer.NewListEntry = function(index)
local newEntry = entryTemplate:Clone()
newEntry.Position = UDim2.new(0,0,0,20*(index-1))
newEntry.InputBegan:Connect(function(input)
local node = tree[index + Explorer.Index]
if not node or selection.Map[node] or input.UserInputType ~=
Enum.UserInputType.MouseMovement then return end
newEntry.Indent.BackgroundColor3 = Settings.Theme.Button
newEntry.Indent.BorderSizePixel = 0
newEntry.Indent.BackgroundTransparency = 0
end)
newEntry.InputEnded:Connect(function(input)
local node = tree[index + Explorer.Index]
if not node or selection.Map[node] or input.UserInputType ~=
Enum.UserInputType.MouseMovement then return end
newEntry.Indent.BackgroundTransparency = 1
end)
newEntry.MouseButton1Down:Connect(function()
end)
newEntry.MouseButton1Up:Connect(function()
end)
newEntry.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
local releaseEvent,mouseEvent
releaseEvent =
clonerefs(game:GetService("UserInputService")).InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
end
end)
mouseEvent =
clonerefs(game:GetService("UserInputService")).InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
local deltaX = mouse.X - startX
local deltaY = mouse.Y - startY
local dist = math.sqrt(deltaX^2 + deltaY^2)
if dist > 5 then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
isRenaming = false
Explorer.StartDrag(listOffsetX,listOffsetY)
end
end
end)
end
end)
newEntry.MouseButton2Down:Connect(function()
end)
newEntry.Indent.Expand.InputBegan:Connect(function(input)
local node = tree[index + Explorer.Index]
if not node or input.UserInputType ~=
Enum.UserInputType.MouseMovement then return end
Explorer.MiscIcons:DisplayByKey(newEntry.Indent.Expand.Icon,
expanded[node] and "Collapse_Over" or "Expand_Over")
end)
newEntry.Indent.Expand.InputEnded:Connect(function(input)
local node = tree[index + Explorer.Index]
if not node or input.UserInputType ~=
Enum.UserInputType.MouseMovement then return end
Explorer.MiscIcons:DisplayByKey(newEntry.Indent.Expand.Icon,
expanded[node] and "Collapse" or "Expand")
end)
newEntry.Indent.Expand.MouseButton1Down:Connect(function()
local node = tree[index + Explorer.Index]
if not node or #node == 0 then return end
newEntry.Parent = treeFrame
return newEntry
end
Explorer.Refresh = function()
local maxNodes = math.max(math.ceil((treeFrame.AbsoluteSize.Y) / 20),0)
for i = 1,maxNodes do
local entry = listEntries[i]
if not listEntries[i] then entry = Explorer.NewListEntry(i)
listEntries[i] = entry Explorer.ClickSystem:Add(entry) end
entry.Visible = true
entry.Position = UDim2.new(0,-
scrollH.Index,0,entry.Position.Y.Offset)
entry.Size = UDim2.new(0,Explorer.ViewWidth,0,20)
entry.Indent.EntryName.Text = tostring(node.Obj)
entry.Indent.Position = UDim2.new(0,depth,0,0)
entry.Indent.Size = UDim2.new(1,-depth,1,0)
entry.Indent.EntryName.TextTruncate =
(Settings.Explorer.UseNameWidth and Enum.TextTruncate.None or
Enum.TextTruncate.AtEnd)
if selection.Map[node] then
entry.Indent.BackgroundColor3 =
Settings.Theme.ListSelection
entry.Indent.BorderSizePixel = 0
entry.Indent.BackgroundTransparency = 0
else
if Lib.CheckMouseInGui(entry) then
entry.Indent.BackgroundColor3 =
Settings.Theme.Button
else
entry.Indent.BackgroundTransparency = 1
end
end
Explorer.PerformUpdate = function(instant)
updateDebounce = true
Lib.FastWait(not instant and 0.1)
if not updateDebounce then return end
updateDebounce = false
if not Explorer.Window:IsVisible() then return end
Explorer.Update()
Explorer.Refresh()
end
Explorer.ForceUpdate = function(norefresh)
updateDebounce = false
Explorer.Update()
if not norefresh then Explorer.Refresh() end
end
Explorer.PerformRefresh = function()
refreshDebounce = true
Lib.FastWait(0.1)
refreshDebounce = false
if updateDebounce or not Explorer.Window:IsVisible() then return end
Explorer.Refresh()
end
Explorer.IsNodeVisible = function(node)
if not node then return end
Explorer.NodeDepth = function(node)
local depth = 0
Explorer.SetupConnections = function()
if descendantAddedCon then descendantAddedCon:Disconnect() end
if descendantRemovingCon then descendantRemovingCon:Disconnect() end
if itemChangedCon then itemChangedCon:Disconnect() end
if Main.Elevated then
descendantAddedCon = game.DescendantAdded:Connect(addObject)
descendantRemovingCon =
game.DescendantRemoving:Connect(removeObject)
else
descendantAddedCon = game.DescendantAdded:Connect(function(obj)
pcall(addObject,obj) end)
descendantRemovingCon =
game.DescendantRemoving:Connect(function(obj) pcall(removeObject,obj) end)
end
if Settings.Explorer.UseNameWidth then
itemChangedCon = game.ItemChanged:Connect(function(obj,prop)
if prop == "Parent" and nodes[obj] then
moveObject(obj)
elseif prop == "Name" and nodes[obj] then
nodes[obj].NameWidth = nil
end
end)
else
itemChangedCon = game.ItemChanged:Connect(function(obj,prop)
if prop == "Parent" and nodes[obj] then
moveObject(obj)
end
end)
end
end
Explorer.ViewNode = function(node)
if not node then return end
Explorer.MakeNodeVisible(node)
Explorer.ForceUpdate(true)
local visibleSpace = scrollV.VisibleSpace
Explorer.ViewObj = function(obj)
Explorer.ViewNode(nodes[obj])
end
Explorer.MakeNodeVisible = function(node,expandRoot)
if not node then return end
Explorer.ShowRightClick = function()
local context = Explorer.RightClickContext
context:Clear()
for i = 1, #sList do
local node = sList[i]
local class = node.Class
if not class then class = node.Obj.ClassName node.Class = class
end
local curClass = apiClasses[class]
while curClass and not presentClasses[curClass.Name] do
presentClasses[curClass.Name] = true
curClass = curClass.Superclass
end
end
context:AddRegistered("CUT")
context:AddRegistered("COPY")
context:AddRegistered("PASTE", emptyClipboard)
context:AddRegistered("DUPLICATE")
context:AddRegistered("DELETE")
context:AddRegistered("RENAME", #sList ~= 1)
context:AddDivider()
context:AddRegistered("GROUP")
context:AddRegistered("UNGROUP")
context:AddRegistered("SELECT_CHILDREN")
context:AddRegistered("JUMP_TO_PARENT")
context:AddRegistered("EXPAND_ALL")
context:AddRegistered("COLLAPSE_ALL")
context:AddDivider()
if expanded == Explorer.SearchExpanded then
context:AddRegistered("CLEAR_SEARCH_AND_JUMP_TO") end
if env.setclipboard then context:AddRegistered("COPY_PATH") end
context:AddRegistered("INSERT_OBJECT")
context:AddRegistered("SAVE_INST")
context:AddRegistered("CALL_FUNCTION")
context:AddRegistered("VIEW_CONNECTIONS")
context:AddRegistered("GET_REFERENCES")
context:AddRegistered("VIEW_API")
context:QueueDivider()
if presentClasses["TouchTransmitter"] then
context:AddRegistered("FIRE_TOUCHTRANSMITTER", firetouchinterest == nil) end
if presentClasses["ClickDetector"] then
context:AddRegistered("FIRE_CLICKDETECTOR", fireclickdetector == nil) end
if presentClasses["ProximityPrompt"] then
context:AddRegistered("FIRE_PROXIMITYPROMPT", fireproximityprompt == nil) end
if presentClasses["Player"] then
context:AddRegistered("SELECT_CHARACTER") end
if presentClasses["Players"] then
context:AddRegistered("SELECT_LOCAL_PLAYER") end
if presentClasses["LuaSourceContainer"] then
context:AddRegistered("VIEW_SCRIPT") end
if sMap[nilNode] then
context:AddRegistered("REFRESH_NIL")
context:AddRegistered("HIDE_NIL")
end
Explorer.InitRightClick = function()
local context = Lib.ContextMenu.new()
selection:SetTable(newSelection)
if #newSelection > 0 then
Explorer.ViewNode(newSelection[1])
end
end})
if nodes[model] then
selection:Set(nodes[model])
Explorer.ViewNode(nodes[model])
end
end})
for i = 1,#node do
local n = node[i]
newSelection[count] = n
ch[chCount] = n
count = count + 1
chCount = chCount + 1
end
for i = 1,#ch do
pcall(function() ch[i].Obj.Parent = par end)
end
node.Obj:Destroy()
end
selection:SetTable(newSelection)
if #newSelection > 0 then
Explorer.ViewNode(newSelection[1])
end
end})
for i = 1,#sList do
local node = sList[i]
for ind = 1,#node do
local cNode = node[ind]
if ind == 1 then Explorer.MakeNodeVisible(cNode) end
newSelection[count] = cNode
count = count + 1
end
end
selection:SetTable(newSelection)
if #newSelection > 0 then
Explorer.ViewNode(newSelection[1])
else
Explorer.Refresh()
end
end})
for i = 1,#sList do
local node = sList[i]
if node.Parent then
newSelection[count] = node.Parent
count = count + 1
end
end
selection:SetTable(newSelection)
if #newSelection > 0 then
Explorer.ViewNode(newSelection[1])
else
Explorer.Refresh()
end
end})
for i = 1,#sList do
local node = sList[i]
if isa(node.Obj,"BasePart") then
hrp.CFrame = node.Obj.CFrame +
Settings.Explorer.TeleportToOffset
break
elseif isa(node.Obj,"Model") then
if node.Obj.PrimaryPart then
hrp.CFrame = node.Obj.PrimaryPart.CFrame +
Settings.Explorer.TeleportToOffset
break
else
local part =
node.Obj:FindFirstChildWhichIsA("BasePart",true)
if part and nodes[part] then
hrp.CFrame = nodes[part].Obj.CFrame +
Settings.Explorer.TeleportToOffset
end
end
end
end
end})
for i = 1,#sList do
expand(sList[i])
end
Explorer.ForceUpdate()
end})
for i = 1,#sList do
expand(sList[i])
end
Explorer.ForceUpdate()
end})
for i = 1,#sList do
newSelection[count] = sList[i]
count = count + 1
end
selection:SetTable(newSelection)
Explorer.ClearSearch()
if #newSelection > 0 then
Explorer.ViewNode(newSelection[1])
end
end})
env.setclipboard(clth(Explorer.GetInstancePath(sList[1].Obj)))
elseif #sList > 1 then
local resList = {"{"}
local count = 2
for i = 1,#sList do
local path = "\
t"..clth(Explorer.GetInstancePath(sList[i].Obj))..","
if #path > 0 then
resList[count] = path
count = count+1
end
end
resList[count] = "}"
env.setclipboard(table.concat(resList,"\n"))
end
end})
end})
end})
end})
context:Register("VIEW_CONNECTIONS",{Name = "View Connections", OnClick
= function()
end})
end})
for i = 1,#sList do
local node = sList[i]
context:Register("FIRE_TOUCHTRANSMITTER",{Name = "Fire
TouchTransmitter", IconMap = Explorer.ClassIcons, Icon = 37, OnClick = function()
local hrp = plr.Character and
plr.Character:FindFirstChild("HumanoidRootPart")
if not hrp then return end
for _, v in ipairs(selection.List) do if v.Obj and
v.Obj:IsA("TouchTransmitter") then firetouchinterest(hrp, v.Obj.Parent, 0) end end
end})
for i = 1,#sList do
local node = sList[i]
if isa(node.Obj,"Player") and nodes[node.Obj.Character]
then
newSelection[count] = nodes[node.Obj.Character]
count = count + 1
end
end
selection:SetTable(newSelection)
if #newSelection > 0 then
Explorer.ViewNode(newSelection[1])
else
Explorer.Refresh()
end
end})
Explorer.RightClickContext = context
end
Explorer.HideNilInstances = function()
table.clear(nilMap)
local disconnectCon =
Instance.new("Folder").ChildAdded:Connect(function() end).Disconnect
for i,v in next,nilCons do
disconnectCon(v[1])
disconnectCon(v[2])
end
table.clear(nilCons)
for i = 1,#nilNode do
coroutine.wrap(removeObject)(nilNode[i].Obj)
end
Explorer.Update()
Explorer.Refresh()
end
Explorer.RefreshNilInstances = function()
if not env.getnilinstances then return end
for i = 1,#nilInsts do
local obj = nilInsts[i]
if obj ~= game then
nilMap[obj] = true
--newNilRoots[obj] = true
--nilMap = newNilMap
for i = 1,#nilInsts do
local obj = nilInsts[i]
local node = nodes[obj]
if not node then coroutine.wrap(addObject)(obj) end
end
--[[
-- Remove old root connections
for obj in next,nilRoots do
if not newNilRoots[obj] then
if not disconnect then disconnect = obj[1].Disconnect end
disconnect(obj[1])
disconnect(obj[2])
end
end
--nilMap = newNilMap
--Explorer.NilRoots = newNilRoots
Explorer.Update()
Explorer.Refresh()
end
Explorer.GetInstancePath = function(obj)
local ffc = game.FindFirstChild
local getCh = game.GetChildren
local path = ""
local curObj = obj
local ts = tostring
local match = string.match
local gsub = string.gsub
local tableFind = table.find
local useGetCh = Settings.Explorer.CopyPathUseGetChildren
local formatLuaString = Lib.FormatLuaString
while curObj do
if curObj == game then
path = "game"..path
break
end
path = indexName..path
curObj = parObj
end
return path
end
Explorer.InitInsertObject = function()
local context = Lib.ContextMenu.new()
context.SearchEnabled = true
context.MaxHeight = 400
context:ApplyTheme({
ContentColor = Settings.Theme.Main2,
OutlineColor = Settings.Theme.Outline1,
DividerColor = Settings.Theme.Outline1,
TextColor = Settings.Theme.Text,
HighlightColor = Settings.Theme.ButtonHover
})
local classes = {}
for i,class in next,API.Classes do
local tags = class.Tags
if not tags.NotCreatable and not tags.Service then
local rmdEntry = RMD.Classes[class.Name]
classes[#classes+1] = {class,rmdEntry and
rmdEntry.ClassCategory or "Uncategorized"}
end
end
table.sort(classes,function(a,b)
if a[2] ~= b[2] then
return a[2] < b[2]
else
return a[1].Name < b[1].Name
end
end)
Explorer.InsertObjectContext = context
end
--[[
Headers, Setups, Predicate, ObjectDefs
]]
Explorer.SearchFilters = { -- TODO: Use data table (so we can disable some if
funcs don't exist)
Comparison = {
["isa"] = function(argString)
local lower = string.lower
local find = string.find
local classQuery = string.split(argString)[1]
if not classQuery then return end
classQuery = lower(classQuery)
local className
for class,_ in pairs(API.Classes) do
local cName = lower(class)
if cName == classQuery then
className = class
break
elseif find(cName,classQuery,1,true) then
className = class
end
end
if not className then return end
return {
Headers = {"local isa = game.IsA"},
Predicate = "isa(obj,'"..className.."')"
}
end,
["remotes"] = function(argString)
return {
Headers = {"local isa = game.IsA"},
Predicate = "isa(obj,'RemoteEvent') or
isa(obj,'RemoteFunction')"
}
end,
["bindables"] = function(argString)
return {
Headers = {"local isa = game.IsA"},
Predicate = "isa(obj,'BindableEvent') or
isa(obj,'BindableFunction')"
}
end,
["rad"] = function(argString)
local num = tonumber(argString)
if not num then return end
return {
Headers = {"local isa = game.IsA", "local hrp =
service.Players.LocalPlayer.Character.HumanoidRootPart"},
Setups = {"local hrpPos = hrp.Position"},
ObjectDefs = {"local isBasePart =
isa(obj,'BasePart')"},
Predicate = "(isBasePart and (obj.Position-
hrpPos).Magnitude <= "..num..")"
}
end,
},
Specific = {
["players"] = function()
return function() return service.Players:GetPlayers() end
end,
["loadedmodules"] = function()
return env.getloadedmodules
end,
},
Default = function(argString,caseSensitive)
local cleanString = argString:gsub("\"","\\\""):gsub("\n","\\n")
if caseSensitive then
return {
Headers = {"local find = string.find"},
ObjectDefs = {"local objName = tostring(obj)"},
Predicate = "find(objName,\"" .. cleanString ..
"\",1,true)"
}
else
return {
Headers = {"local lower = string.lower","local find =
string.find","local tostring = tostring"},
ObjectDefs = {"local lowerName =
lower(tostring(obj))"},
Predicate = "find(lowerName,\"" ..
cleanString:lower() .. "\",1,true)"
}
end
end,
SpecificDefault = function(n)
return {
Headers = {},
ObjectDefs = {"local isSpec"..n.." = specResults["..n.."]
[node]"},
Predicate = "isSpec"..n
}
end,
}
Explorer.BuildSearchFunc = function(query)
local specFilterList,specMap = {},{}
local finalPredicate = ""
local rep = string.rep
local formatQuery = query:gsub("\\."," "):gsub('".-"',function(str)
return rep(" ",#str) end)
local headers = {}
local objectDefs = {}
local setups = {}
local find = string.find
local sub = string.sub
local lower = string.lower
local match = string.match
local ops = {
["("] = "(",
[")"] = ")",
["||"] = " or ",
["&&"] = " and "
}
local filterCount = 0
local compFilters = Explorer.SearchFilters.Comparison
local specFilters = Explorer.SearchFilters.Specific
local init = 1
local lastOp = nil
if dat.ObjectDefs then
local t = dat.ObjectDefs
for i = 1,#t do
objectDefs[t[i]] = true
end
end
if dat.Setups then
local t = dat.Setups
for i = 1,#t do
setups[t[i]] = true
end
end
finalPredicate = finalPredicate..dat.Predicate
end
local found = {}
local foundData = {}
local find = string.find
local sub = string.sub
count = count+1
init = y+1
x,y,extra = find(str,pattern,init,true)
end
end
local start = tick()
findAll(formatQuery,'&&')
findAll(formatQuery,"||")
findAll(formatQuery,"(")
findAll(formatQuery,")")
table.sort(found)
table.insert(found,#formatQuery+1)
for i = 1,#found do
local nextInd = found[i]
local nextData = foundData[nextInd] or {1}
local op = ops[nextData[2]]
local term = sub(query,init,nextInd-1)
term = match(term,"^%s*(.-)%s*$") or "" -- Trim
processFilter(Explorer.SearchFilters.Default(qTerm,true))
else
local x,y = find(term,"%S+")
if x then
local first = sub(term,x,y)
local specifier = sub(first,1,1) == "/" and
lower(sub(first,2))
local compFunc = specifier and
compFilters[specifier]
local specFunc = specifier and
specFilters[specifier]
if compFunc then
local argStr = sub(term,y+2)
local ret = compFunc(inQuotes(argStr) or
argStr)
if ret then
processFilter(ret)
else
finalPredicate =
finalPredicate.."false"
end
elseif specFunc then
local argStr = sub(term,y+2)
local ret = specFunc(inQuotes(argStr) or
argStr)
if ret then
if not specMap[term] then
specFilterList[#specFilterList + 1] = ret
specMap[term] =
#specFilterList
end
processFilter(Explorer.SearchFilters.SpecificDefault(specMap[term]))
else
finalPredicate =
finalPredicate.."false"
end
else
processFilter(Explorer.SearchFilters.Default(term))
end
end
end
end
if op then
finalPredicate = finalPredicate..op
if op == "(" and (#term > 0 or lastOp == ")") then --
Handle bracket glitch
return
else
lastOp = op
end
end
init = nextInd+nextData[1]
end
%s
local function search(root)
%s
%s
if %s then
expandTable[node] = 0
searchResults[node] = true
if not expandedpar then
local parnode = node.Parent
while parnode and (not searchResults[parnode] or
expandTable[parnode] == 0) do
expandTable[parnode] = true
searchResults[parnode] = true
parnode = parnode.Parent
end
expandedpar = true
end
end
local funcStr =
template:format(finalHeaders,finalSetups,finalObjectDefs,finalPredicate)
local s,func = pcall(loadstring,funcStr)
if not s or not func then return nil,specFilterList end
return func(),specFilterList
end
Explorer.DoSearch = function(query)
table.clear(Explorer.SearchExpanded)
table.clear(searchResults)
expanded = (#query == 0 and Explorer.Expanded or
Explorer.SearchExpanded)
searchFunc = nil
if find(lower(tostring(obj)),lowerQuery,1,true) then
expandTable[node] = 0
searchResults[node] = true
if not expandedpar then
local parnode = node.Parent
while parnode and (not
searchResults[parnode] or expandTable[parnode] == 0) do
expanded[parnode] = true
searchResults[parnode] = true
parnode = parnode.Parent
end
expandedpar = true
end
end
if Main.Elevated then
local start = tick()
searchFunc,specFilters = Explorer.BuildSearchFunc(query)
--print("BUILD SEARCH",tick()-start)
else
searchFunc = defaultSearch
end
if specFilters then
table.clear(specResults)
for i = 1,#specFilters do -- Specific search filers that
returns list of matches
local resMap = {}
specResults[i] = resMap
local objs = specFilters[i]()
for c = 1,#objs do
local node = nodes[objs[c]]
if node then
resMap[node] = true
end
end
end
end
if searchFunc then
local start = tick()
searchFunc(nodes[game])
searchFunc(nilNode)
--warn(tick()-start)
end
end
Explorer.ForceUpdate()
end
Explorer.ClearSearch = function()
Explorer.GuiElems.SearchBar.Text = ""
expanded = Explorer.Expanded
searchFunc = nil
end
Explorer.InitSearch = function()
local searchBox = Explorer.GuiElems.ToolBar.SearchFrame.SearchBox
Explorer.GuiElems.SearchBar = searchBox
Lib.ViewportTextBox.convert(searchBox)
searchBox.FocusLost:Connect(function()
Explorer.DoSearch(searchBox.Text)
end)
end
Explorer.InitEntryTemplate = function()
entryTemplate = create({
{1,"TextButton",
{AutoButtonColor=false,BackgroundColor3=Color3.new(0,0,0),BackgroundTransparency=1,
BorderColor3=Color3.new(0,0,0),Font=3,Name="Entry",Position=UDim2.new(0,1,0,1),Size
=UDim2.new(0,250,0,20),Text="",TextSize=14,}},
{2,"Frame",
{BackgroundColor3=Color3.new(0.04313725605607,0.35294118523598,0.68627452850342),Ba
ckgroundTransparency=1,BorderColor3=Color3.new(0.33725491166115,0.49019610881805,0.
73725491762161),BorderSizePixel=0,Name="Indent",Parent={1},Position=UDim2.new(0,20,
0,0),Size=UDim2.new(1,-20,1,0),}},
{3,"TextLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Font=3,Name="EntryName
",Parent={2},Position=UDim2.new(0,26,0,0),Size=UDim2.new(1,-
26,1,0),Text="Workspace",TextColor3=Color3.new(0.86274516582489,0.86274516582489,0.
86274516582489),TextSize=14,TextXAlignment=0,}},
{4,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,ClipsDescendants=true,
Font=3,Name="Expand",Parent={2},Position=UDim2.new(0,-
20,0,0),Size=UDim2.new(0,20,0,20),Text="",TextSize=14,}},
{5,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxassetid://
5642383285",ImageRectOffset=Vector2.new(144,16),ImageRectSize=Vector2.new(16,16),Na
me="Icon",Parent={4},Position=UDim2.new(0,2,0,2),ScaleType=4,Size=UDim2.new(0,16,0,
16),}},
{6,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxasset://
textures/
ClassImages.png",ImageRectOffset=Vector2.new(304,0),ImageRectSize=Vector2.new(16,16
),Name="Icon",Parent={2},Position=UDim2.new(0,4,0,2),ScaleType=4,Size=UDim2.new(0,1
6,0,16),}},
})
if button == 1 then
if combo == 2 then
if node.Obj:IsA("LuaSourceContainer") then
ScriptViewer.ViewScript(node.Obj)
elseif #node > 0 and expanded[node] ~= 0 then
expanded[node] = not expanded[node]
Explorer.Update()
end
end
if Properties.SelectObject(node.Obj) then
sys.IsRenaming = false
return
end
sys.IsRenaming = selection.Map[node]
if Lib.IsShiftDown() then
if not selection.Piviot then return end
Explorer.Refresh()
end)
sys.OnRelease:Connect(function(item,combo,button)
local ind = table.find(listEntries,item)
if not ind then return end
local node = tree[ind + Explorer.Index]
if not node then return end
if button == 1 then
if selection.Map[node] and not Lib.IsShiftDown() and not
Lib.IsCtrlDown() then
selection.ShiftSet = {}
selection:Set(node)
selection.Piviot = node
Explorer.Refresh()
end
local id = sys.ClickId
Lib.FastWait(sys.ComboTime)
if combo == 1 and id == sys.ClickId and sys.IsRenaming and
selection.Map[node] then
Explorer.SetRenamingNode(node)
end
elseif button == 2 then
Explorer.ShowRightClick()
end
end)
Explorer.ClickSystem = sys
end
Explorer.InitDelCleaner = function()
coroutine.wrap(function()
local fw = Lib.FastWait
while true do
local processed = false
local c = 0
for _,node in next,nodes do
if node.HasDel then
local delInd
for i = 1,#node do
if node[i].Del then
delInd = i
break
end
end
if delInd then
for i = delInd+1,#node do
local cn = node[i]
if not cn.Del then
node[delInd] = cn
delInd = delInd+1
end
end
for i = delInd,#node do
node[i] = nil
end
end
node.HasDel = false
processed = true
fw()
end
c = c + 1
if c > 10000 then
c = 0
fw()
end
end
if processed and not refreshDebounce then
Explorer.PerformRefresh() end
fw(0.5)
end
end)()
end
Explorer.UpdateSelectionVisuals = function()
local holder = Explorer.SelectionVisualsHolder
local isa = game.IsA
local clone = game.Clone
if not holder then
holder = Instance.new("ScreenGui")
holder.Name = "ExplorerSelections"
holder.DisplayOrder = Main.DisplayOrders.Core
Lib.ShowGui(holder)
Explorer.SelectionVisualsHolder = holder
Explorer.SelectionVisualCons = {}
-- Updates theme
for i,v in pairs(Explorer.SelectionVisualGui:GetChildren()) do
v.BackgroundColor3 = Color3.fromRGB(0, 170, 255)
end
Explorer.Init = function()
Explorer.ClassIcons =
Lib.IconMap.newLinear("rbxasset://textures/ClassImages.png",16,16)
Explorer.MiscIcons = Main.MiscIcons
clipboard = {}
selection = Lib.Set.new()
selection.ShiftSet = {}
selection.Changed:Connect(Properties.ShowExplorerProps)
Explorer.Selection = selection
Explorer.InitRightClick()
Explorer.InitInsertObject()
Explorer.SetSortingEnabled(Settings.Explorer.Sorting)
Explorer.Expanded = setmetatable({},{__mode = "k"})
Explorer.SearchExpanded = setmetatable({},{__mode = "k"})
expanded = Explorer.Expanded
toolBar = explorerItems.ToolBar
treeFrame = explorerItems.List
Explorer.GuiElems.ToolBar = toolBar
Explorer.GuiElems.TreeFrame = treeFrame
scrollV = Lib.ScrollBar.new()
scrollV.WheelIncrement = 3
scrollV.Gui.Position = UDim2.new(1,-16,0,23)
scrollV:SetScrollFrame(treeFrame)
scrollV.Scrolled:Connect(function()
Explorer.Index = scrollV.Index
Explorer.Refresh()
end)
scrollH = Lib.ScrollBar.new(true)
scrollH.Increment = 5
scrollH.WheelIncrement = Explorer.EntryIndent
scrollH.Gui.Position = UDim2.new(0,0,1,-16)
scrollH.Scrolled:Connect(function()
Explorer.Refresh()
end)
Explorer.InitEntryTemplate()
toolBar.Parent = window.GuiElems.Content
treeFrame.Parent = window.GuiElems.Content
explorerItems.ScrollCorner.Parent = window.GuiElems.Content
scrollV.Gui.Parent = window.GuiElems.Content
scrollH.Gui.Parent = window.GuiElems.Content
-- Window events
window.GuiElems.Main:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
if Explorer.Active then
Explorer.UpdateView()
Explorer.Refresh()
end
end)
window.OnActivate:Connect(function()
Explorer.Active = true
Explorer.UpdateView()
Explorer.Update()
Explorer.Refresh()
end)
window.OnRestore:Connect(function()
Explorer.Active = true
Explorer.UpdateView()
Explorer.Update()
Explorer.Refresh()
end)
window.OnDeactivate:Connect(function() Explorer.Active = false end)
window.OnMinimize:Connect(function() Explorer.Active = false end)
-- Settings
autoUpdateSearch = Settings.Explorer.AutoUpdateSearch
-- Fill in nodes
nodes[game] = {Obj = game}
expanded[nodes[game]] = true
-- Nil Instances
if env.getnilinstances then
nodes[nilNode.Obj] = nilNode
end
Explorer.SetupConnections()
return Explorer
end
API = data.API
RMD = data.RMD
env = data.env
service = data.service
plr = data.plr
create = data.create
createSimple = data.createSimple
end
Properties.GuiElems = {}
Properties.Index = 0
Properties.ViewWidth = 0
Properties.MinInputWidth = 100
Properties.EntryIndent = 16
Properties.EntryOffset = 4
Properties.NameWidthCache = {}
Properties.SubPropCache = {}
Properties.ClassLists = {}
Properties.SearchText = ""
Properties.ExpandableTypes = {
["Vector2"] = true,
["Vector3"] = true,
["UDim"] = true,
["UDim2"] = true,
["CFrame"] = true,
["Rect"] = true,
["PhysicalProperties"] = true,
["Ray"] = true,
["NumberRange"] = true,
["Faces"] = true,
["Axes"] = true,
}
Properties.ExpandableProps = {
["Sound.SoundId"] = true
}
Properties.CollapsedCategories = {
["Surface Inputs"] = true,
["Surface"] = true
}
Properties.ConflictSubProps = {
["Vector2"] = {"X","Y"},
["Vector3"] = {"X","Y","Z"},
["UDim"] = {"Scale","Offset"},
["UDim2"] = {"X","X.Scale","X.Offset","Y","Y.Scale","Y.Offset"},
["CFrame"] = {"Position","Position.X","Position.Y","Position.Z",
"RightVector","RightVector.X","RightVector.Y","RightVector.Z",
"UpVector","UpVector.X","UpVector.Y","UpVector.Z",
"LookVector","LookVector.X","LookVector.Y","LookVector.Z"},
["Rect"] = {"Min.X","Min.Y","Max.X","Max.Y"},
["PhysicalProperties"] =
{"Density","Elasticity","ElasticityWeight","Friction","FrictionWeight"},
["Ray"] =
{"Origin","Origin.X","Origin.Y","Origin.Z","Direction","Direction.X","Direction.Y",
"Direction.Z"},
["NumberRange"] = {"Min","Max"},
["Faces"] = {"Back","Bottom","Front","Left","Right","Top"},
["Axes"] = {"X","Y","Z"}
}
Properties.ConflictIgnore = {
["BasePart"] = {
["ResizableFaces"] = true
}
}
Properties.RoundableTypes = {
["float"] = true,
["double"] = true,
["Color3"] = true,
["UDim"] = true,
["UDim2"] = true,
["Vector2"] = true,
["Vector3"] = true,
["NumberRange"] = true,
["Rect"] = true,
["NumberSequence"] = true,
["ColorSequence"] = true,
["Ray"] = true,
["CFrame"] = true
}
Properties.TypeNameConvert = {
["number"] = "double",
["boolean"] = "bool"
}
Properties.ToNumberTypes = {
["int"] = true,
["int64"] = true,
["float"] = true,
["double"] = true
}
Properties.DefaultPropValue = {
string = "",
bool = false,
double = 0,
UDim = UDim.new(0,0),
UDim2 = UDim2.new(0,0,0,0),
BrickColor = BrickColor.new("Medium stone grey"),
Color3 = Color3.new(1,1,1),
Vector2 = Vector2.new(0,0),
Vector3 = Vector3.new(0,0,0),
NumberSequence = NumberSequence.new(1),
ColorSequence = ColorSequence.new(Color3.new(1,1,1)),
NumberRange = NumberRange.new(0),
Rect = Rect.new(0,0,0,0)
}
Properties.AllowedAttributeTypes =
{"string","boolean","number","UDim","UDim2","BrickColor","Color3","Vector2","Vector
3","NumberSequence","ColorSequence","NumberRange","Rect"}
Properties.StringToValue = function(prop,str)
local typeData = prop.ValueType
local typeName = typeData.Name
return nil
end
Properties.ValueToString = function(prop,val)
local typeData = prop.ValueType
local typeName = typeData.Name
return tostring(val)
end
Properties.GetIndexableProps = function(obj,classData)
if not Main.Elevated then
if not pcall(function() return obj.ClassName end) then return nil
end
end
local result = {}
local count = 1
local props = classData.Properties
for i = 1,#props do
local prop = props[i]
if not ignoreProps[prop.Name] then
local s = pcall(function() return obj[prop.Name] end)
if s then
result[count] = prop
count = count + 1
end
end
end
return result
end
Properties.FindFirstObjWhichIsA = function(class)
local classList = Properties.ClassLists[class] or {}
if classList and #classList > 0 then
return classList[1]
end
return nil
end
Properties.ComputeConflicts = function(p)
local maxConflictCheck = Settings.Properties.MaxConflictCheck
local sList = Explorer.Selection.List
local classLists = Properties.ClassLists
local stringSplit = string.split
local t_clear = table.clear
local conflictIgnore = Properties.ConflictIgnore
local conflictMap = {}
local propList = p and {p} or props
if p then
local gName = p.Class.."."..p.Name
autoUpdateObjs[gName] = nil
local subProps = Properties.ConflictSubProps[p.ValueType.Name] or
{}
for i = 1,#subProps do
autoUpdateObjs[gName.."."..subProps[i]] = nil
end
else
table.clear(autoUpdateObjs)
end
local checked = 0
local subProps = Properties.ConflictSubProps[typeName] or
{}
local subPropCount = #subProps
local toCheck = subPropCount + 1
local conflictsFound = 0
local indexNames = {}
local ignored = conflictIgnore[propClass] and
conflictIgnore[propClass][propName]
local truthyCheck = (typeName == "PhysicalProperties")
local isAttribute = prop.IsAttribute
local isMultiType = prop.MultiType
t_clear(conflictMap)
local firstValSub =
firstVal
local propValSub =
propVal
for j = 1,#indexes do
if not firstValSub
or not propValSub then break end -- PhysicalProperties
local indexName =
indexes[j]
firstValSub =
firstValSub[indexName]
propValSub =
propValSub[indexName]
end
conflictMap[mapInd] = true
conflictsFound =
conflictsFound + 1
end
end
end
checked = checked + 1
if checked == maxConflictCheck then break end
end
if p then
Properties.Refresh()
end
end
table.clear(props)
for i = 1,#sList do
local node = sList[i]
local obj = node.Obj
local class = node.Class
if not class then class = obj.ClassName node.Class = class end
for i = 1,#apiProps do
local prop = apiProps[i]
local tags = prop.Tags
if (not tags.Deprecated or showDeprecated) and
(not tags.Hidden or showHidden) then
props[propCount] = prop
propCount = propCount + 1
end
end
foundClasses[APIClassName] = true
end
apiClass = apiClass.Superclass
end
table.sort(props,function(a,b)
if a.Category ~= b.Category then
return (categoryOrder[a.Category] or 9999) <
(categoryOrder[b.Category] or 9999)
else
local aOrder = (RMDCustomOrders[a.Class] and
RMDCustomOrders[a.Class][a.Name]) or 9999999
local bOrder = (RMDCustomOrders[b.Class] and
RMDCustomOrders[b.Class][b.Name]) or 9999999
if aOrder ~= bOrder then
return aOrder < bOrder
else
return lower(a.Name) < lower(b.Name)
end
end
end)
Properties.Update()
Properties.Refresh()
end
Properties.UpdateView = function()
local maxEntries = math.ceil(propsFrame.AbsoluteSize.Y / 23)
local maxX = propsFrame.AbsoluteSize.X
local totalWidth = Properties.ViewWidth + Properties.MinInputWidth
scrollV.VisibleSpace = maxEntries
scrollV.TotalSpace = #viewList + 1
scrollH.VisibleSpace = maxX
scrollH.TotalSpace = totalWidth
Properties.Index = scrollV.Index
end
end
Properties.MakeSubProp = function(prop,subName,valueType,displayName)
local subProp = {}
for i,v in pairs(prop) do
subProp[i] = v
end
subProp.RootType = subProp.RootType or subProp.ValueType
subProp.ValueType = valueType
subProp.SubName = subProp.SubName and (subProp.SubName..subName) or
subName
subProp.DisplayName = displayName
return subProp
end
return result
end
Properties.Update = function()
table.clear(viewList)
local visible
if searchText and depth == 1 then
if find(lower(propName),searchText,1,true) then
visible = true
end
else
visible = true
end
if isFirstScaleType then
local nameArr = subName and
stringSplit(subName,".")
local displayName = prop.DisplayName or
(nameArr and nameArr[#nameArr]) or propName
local nameWidth = nameWidthCache[displayName]
if not nameWidth then nameWidth =
getTextSize(textServ,displayName,14,font,size).X nameWidthCache[displayName] =
nameWidth end
viewList[count] = prop
count = count + 1
inputProp = nil
Properties.ViewWidth = maxWidth + 9 + Properties.EntryOffset
Properties.UpdateView()
end
Properties.NewPropEntry = function(index)
local newEntry = Properties.EntryTemplate:Clone()
local nameFrame = newEntry.NameFrame
local valueFrame = newEntry.ValueFrame
local newCheckbox = Lib.Checkbox.new(1)
newCheckbox.Gui.Position = UDim2.new(0,3,0,3)
newCheckbox.Gui.Parent = valueFrame
newCheckbox.OnInput:Connect(function()
local prop = viewList[index + Properties.Index]
if not prop then return end
nameFrame.Expand.InputBegan:Connect(function(input)
local prop = viewList[index + Properties.Index]
if not prop or input.UserInputType ~=
Enum.UserInputType.MouseMovement then return end
Main.MiscIcons:DisplayByKey(newEntry.NameFrame.Expand.Icon,
expanded[fullName] and "Collapse_Over" or "Expand_Over")
end)
nameFrame.Expand.InputEnded:Connect(function(input)
local prop = viewList[index + Properties.Index]
if not prop or input.UserInputType ~=
Enum.UserInputType.MouseMovement then return end
Main.MiscIcons:DisplayByKey(newEntry.NameFrame.Expand.Icon,
expanded[fullName] and "Collapse" or "Expand")
end)
nameFrame.Expand.MouseButton1Down:Connect(function()
local prop = viewList[index + Properties.Index]
if not prop then return end
nameFrame.PropName.InputBegan:Connect(function(input)
local prop = viewList[index + Properties.Index]
if not prop then return end
if input.UserInputType == Enum.UserInputType.MouseMovement and
not nameFrame.PropName.TextFits then
local fullNameFrame = Properties.FullNameFrame
local nameArr = string.split(prop.Class.."."..prop.Name..
(prop.SubName or ""),".")
local dispName = prop.DisplayName or nameArr[#nameArr]
local sizeX =
service.TextService:GetTextSize(dispName,14,Enum.Font.SourceSans,Vector2.new(math.h
uge,20)).X
fullNameFrame.TextLabel.Text = dispName
--fullNameFrame.Position =
UDim2.new(0,Properties.EntryIndent*(prop.Depth or 1) +
Properties.EntryOffset,0,23*(index-1))
fullNameFrame.Size = UDim2.new(0,sizeX + 4,0,22)
fullNameFrame.Visible = true
Properties.FullNameFrameIndex = index
Properties.FullNameFrameAttach.SetData(fullNameFrame,
{Target = nameFrame})
Properties.FullNameFrameAttach.Enable()
end
end)
nameFrame.PropName.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement and
Properties.FullNameFrameIndex == index then
Properties.FullNameFrame.Visible = false
Properties.FullNameFrameAttach.Disable()
end
end)
valueFrame.ValueBox.MouseButton1Down:Connect(function()
local prop = viewList[index + Properties.Index]
if not prop then return end
Properties.SetInputProp(prop,index)
end)
valueFrame.ColorButton.MouseButton1Down:Connect(function()
local prop = viewList[index + Properties.Index]
if not prop then return end
Properties.SetInputProp(prop,index,"color")
end)
valueFrame.RightButton.MouseButton1Click:Connect(function()
local prop = viewList[index + Properties.Index]
if not prop then return end
nameFrame.ToggleAttributes.MouseButton1Click:Connect(function()
Settings.Properties.ShowAttributes = not
Settings.Properties.ShowAttributes
Properties.ShowExplorerProps()
end)
newEntry.RowButton.MouseButton1Click:Connect(function()
Properties.DisplayAddAttributeWindow()
end)
newEntry.EditAttributeButton.MouseButton1Down:Connect(function()
local prop = viewList[index + Properties.Index]
if not prop then return end
Properties.DisplayAttributeContext(prop)
end)
valueFrame.SoundPreview.ControlButton.MouseButton1Click:Connect(function()
if Properties.PreviewSound and Properties.PreviewSound.Playing
then
Properties.SetSoundPreview(false)
else
local soundObj = Properties.FindFirstObjWhichIsA("Sound")
if soundObj then Properties.SetSoundPreview(soundObj) end
end
end)
valueFrame.SoundPreview.InputBegan:Connect(function(input)
if input.UserInputType ~= Enum.UserInputType.MouseButton1 then
return end
local releaseEvent,mouseEvent
releaseEvent =
service.UserInputService.InputEnded:Connect(function(input)
if input.UserInputType ~= Enum.UserInputType.MouseButton1
then return end
releaseEvent:Disconnect()
mouseEvent:Disconnect()
end)
mouseEvent =
service.UserInputService.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
then
update(input)
end
end)
end)
newEntry.Parent = propsFrame
return {
Gui = newEntry,
GuiElems = {
NameFrame = nameFrame,
ValueFrame = valueFrame,
PropName = nameFrame.PropName,
ValueBox = valueFrame.ValueBox,
Expand = nameFrame.Expand,
ColorButton = valueFrame.ColorButton,
ColorPreview = valueFrame.ColorButton.ColorPreview,
Gradient = valueFrame.ColorButton.ColorPreview.UIGradient,
EnumArrow = valueFrame.EnumArrow,
Checkbox = valueFrame.Checkbox,
RightButton = valueFrame.RightButton,
RightButtonIcon = iconFrame,
RowButton = newEntry.RowButton,
EditAttributeButton = newEntry.EditAttributeButton,
ToggleAttributes = nameFrame.ToggleAttributes,
SoundPreview = valueFrame.SoundPreview,
SoundPreviewSlider =
valueFrame.SoundPreview.TimeLine.Slider
}
}
end
Properties.GetSoundPreviewEntry = function()
for i = 1,#viewList do
if viewList[i] == Properties.SoundPreviewProp then
return propEntries[i - Properties.Index]
end
end
end
Properties.SetSoundPreview = function(soundObj,noplay)
local sound = Properties.PreviewSound
if not sound then
sound = Instance.new("Sound")
sound.Name = "Preview"
sound.Paused:Connect(function()
local entry = Properties.GetSoundPreviewEntry()
if entry then
Main.MiscIcons:DisplayByKey(entry.GuiElems.SoundPreview.ControlButton.Icon, "Play")
end
end)
sound.Resumed:Connect(function() Properties.Refresh() end)
sound.Ended:Connect(function()
local entry = Properties.GetSoundPreviewEntry()
if entry then entry.GuiElems.SoundPreviewSlider.Position =
UDim2.new(0,-4,0,-8) end
Properties.Refresh()
end)
sound.Parent = window.Gui
Properties.PreviewSound = sound
end
coroutine.wrap(function()
local previewTime = tick()
Properties.SoundPreviewTime = previewTime
while previewTime == Properties.SoundPreviewTime and
sound.Playing do
local entry = Properties.GetSoundPreviewEntry()
if entry then
local tl = sound.TimeLength
local perc = sound.TimePosition/(tl == 0 and 1
or tl)
entry.GuiElems.SoundPreviewSlider.Position =
UDim2.new(perc,-4,0,-8)
end
Lib.FastWait()
end
end)()
Properties.Refresh()
end
end
Properties.DisplayAttributeContext = function(prop)
local context = Properties.AttributeContext
if not context then
context = Lib.ContextMenu.new()
context.Iconless = true
context.Width = 80
end
context:Clear()
context:Show()
end
Properties.DisplayAddAttributeWindow = function(editAttr)
local win = Properties.AddAttributeWindow
if not win then
win = Lib.Window.new()
win.Alignable = false
win.Resizable = false
win:SetTitle("Add Attribute")
win:SetSize(200,130)
nameBox.TextBox:GetPropertyChangedSignal("Text"):Connect(function()
saveButton:SetDisabled(#nameBox:GetText() == 0)
end)
saveButton.Text = "Save"
saveButton.Position = UDim2.new(0,5,1,-25)
saveButton.Size = UDim2.new(0,92,0,20)
saveButton.OnClick:Connect(function()
local name = nameBox:GetText()
if #name > 100 then
errorLabel.Text = "Error: Name over 100 chars"
return
elseif name:sub(1,3) == "RBX" then
errorLabel.Text = "Error: Name begins with 'RBX'"
return
end
Settings.Properties.ShowAttributes = true
Properties.SetProp(attrProp,Properties.DefaultPropValue[valType.Name],true,Properti
es.EditingAttribute)
Properties.ShowExplorerProps()
win:Close()
end)
win:Add(saveButton,"SaveButton")
Properties.AddAttributeWindow = win
end
Properties.EditingAttribute = editAttr
win:SetTitle(editAttr and "Edit Attribute "..editAttr.AttributeName or
"Add Attribute")
win.Elements.Error.Text = ""
win.Elements.NameBox:SetText("")
win.Elements.SaveButton:SetDisabled(true)
win.Elements.TypeChooser:SetSelected(1)
win:Show()
end
Properties.IsTextEditable = function(prop)
local typeData = prop.ValueType
local typeName = typeData.Name
Properties.DisplayEnumDropdown = function(entryIndex)
local context = Properties.EnumContext
if not context then
context = Lib.ContextMenu.new()
context.Iconless = true
context.MaxHeight = 200
context.ReverseYOffset = 22
Properties.EnumDropdown = context
end
local sorted = {}
for name,enum in next,enum:GetEnumItems() do
sorted[#sorted+1] = enum
end
table.sort(sorted,function(a,b) return a.Name < b.Name end)
context:Clear()
for i = 1,#sorted do
local enumItem = sorted[i]
context:Add({Name = enumItem.Name, OnClick = onClick})
end
context.Width = valueFrame.AbsoluteSize.X
context:Show(valueFrame.AbsolutePosition.X,
valueFrame.AbsolutePosition.Y + 22)
end
Properties.DisplayBrickColorEditor = function(prop,entryIndex,col)
local editor = Properties.BrickColorEditor
if not editor then
editor = Lib.BrickColorPicker.new()
editor.Gui.DisplayOrder = Main.DisplayOrders.Menu
editor.ReverseYOffset = 22
editor.OnSelect:Connect(function(col)
if not editor.CurrentProp or
editor.CurrentProp.ValueType.Name ~= "BrickColor" then return end
Properties.DisplayColorEditor(colProp,editor.SavedColor.Color)
end)
Properties.BrickColorEditor = editor
end
Properties.DisplayColorEditor = function(prop,col)
local editor = Properties.ColorEditor
if not editor then
editor = Lib.ColorPicker.new()
editor.OnSelect:Connect(function(col)
if not editor.CurrentProp then return end
local typeName = editor.CurrentProp.ValueType.Name
if typeName ~= "Color3" and typeName ~= "BrickColor" then
return end
Properties.ColorEditor = editor
end
editor.CurrentProp = prop
if col then
editor:SetColor(col)
else
local firstVal = Properties.GetFirstPropVal(prop)
if firstVal then editor:SetColor(firstVal) end
end
editor:Show()
end
Properties.DisplayNumberSequenceEditor = function(prop,seq)
local editor = Properties.NumberSequenceEditor
if not editor then
editor = Lib.NumberSequenceEditor.new()
editor.OnSelect:Connect(function(val)
if not editor.CurrentProp or
editor.CurrentProp.ValueType.Name ~= "NumberSequence" then return end
Properties.NumberSequenceEditor = editor
end
editor.CurrentProp = prop
if seq then
editor:SetSequence(seq)
else
local firstVal = Properties.GetFirstPropVal(prop)
if firstVal then editor:SetSequence(firstVal) end
end
editor:Show()
end
Properties.DisplayColorSequenceEditor = function(prop,seq)
local editor = Properties.ColorSequenceEditor
if not editor then
editor = Lib.ColorSequenceEditor.new()
editor.OnSelect:Connect(function(val)
if not editor.CurrentProp or
editor.CurrentProp.ValueType.Name ~= "ColorSequence" then return end
Properties.ColorSequenceEditor = editor
end
editor.CurrentProp = prop
if seq then
editor:SetSequence(seq)
else
local firstVal = Properties.GetFirstPropVal(prop)
if firstVal then editor:SetSequence(firstVal) end
end
editor:Show()
end
Properties.GetFirstPropVal = function(prop)
local first = Properties.FindFirstObjWhichIsA(prop.Class)
if first then
return Properties.GetPropVal(prop,first)
end
end
Properties.GetPropVal = function(prop,obj)
if prop.MultiType then return "<Multiple Types>" end
if not obj then return end
local propVal
if prop.IsAttribute then
propVal = getAttribute(obj,prop.AttributeName)
if propVal == nil then return nil end
return propVal
end
Properties.SelectObject = function(obj)
if inputProp and inputProp.ValueType.Category == "Class" then
local prop = inputProp
inputProp = nil
if isa(obj,prop.ValueType.Name) then
Properties.SetProp(prop,obj)
else
Properties.Refresh()
end
return true
end
return false
end
Properties.DisplayProp = function(prop,entryIndex)
local propName = prop.Name
local typeData = prop.ValueType
local typeName = typeData.Name
local tags = prop.Tags
local gName = prop.Class.."."..prop.Name..(prop.SubName or "")
local propObj = autoUpdateObjs[gName]
local entryData = propEntries[entryIndex]
local UDim2 = UDim2
valueBox.Position = UDim2.new(0,offset,0,0)
valueBox.Size = UDim2.new(1,-endOffset,1,0)
-- Right button
if inputFullName == gName and typeData.Category == "Class" then
Main.MiscIcons:DisplayByKey(guiElems.RightButtonIcon, "Delete")
guiElems.RightButtonIcon.Visible = true
rightButton.Text = ""
rightButton.Visible = true
elseif typeName == "NumberSequence" or typeName == "ColorSequence" then
guiElems.RightButtonIcon.Visible = false
rightButton.Text = "..."
rightButton.Visible = true
else
rightButton.Visible = false
end
-- Displays the correct ValueBox for the ValueType, and sets it to the
prop value
if typeName == "bool" or typeName == "PhysicalProperties" then
valueBox.Visible = false
checkbox.Visible = true
soundPreview.Visible = false
checkboxes[entryIndex].Disabled = tags.ReadOnly
if typeName == "PhysicalProperties" and autoUpdateObjs[gName]
then
checkboxes[entryIndex]:SetState(propVal and true or false)
else
checkboxes[entryIndex]:SetState(propVal)
end
elseif typeName == "SoundPlayer" then
valueBox.Visible = false
checkbox.Visible = false
soundPreview.Visible = true
local playing = Properties.PreviewSound and
Properties.PreviewSound.Playing
Main.MiscIcons:DisplayByKey(soundPreview.ControlButton.Icon,
playing and "Pause" or "Play")
else
valueBox.Visible = true
checkbox.Visible = false
soundPreview.Visible = false
Properties.Refresh = function()
local maxEntries = math.max(math.ceil((propsFrame.AbsoluteSize.Y) /
23),0)
local maxX = propsFrame.AbsoluteSize.X
local valueWidth = math.max(Properties.MinInputWidth,maxX-
Properties.ViewWidth)
local inputPropVisible = false
local isa = game.IsA
local UDim2 = UDim2
local stringSplit = string.split
local scaleType = Settings.Properties.ScaleType
-- Clear connections
for i = 1,#propCons do
propCons[i]:Disconnect()
end
table.clear(propCons)
for i = 1,maxEntries do
local entryData = propEntries[i]
if not propEntries[i] then entryData = Properties.NewPropEntry(i)
propEntries[i] = entryData end
if prop.SpecialRow then
if prop.SpecialRow == "AddAttribute" then
nameFrame.Visible = false
valueFrame.Visible = false
guiElems.RowButton.Visible = true
end
else
-- Revert special row stuff
nameFrame.Visible = true
guiElems.RowButton.Visible = false
if prop.CategoryName then
entry.BackgroundColor3 = Settings.Theme.Main1
valueFrame.Visible = false
propNameBox.Text = prop.CategoryName
propNameBox.Font = Enum.Font.SourceSansBold
expand.Visible = true
propNameBox.TextColor3 = Settings.Theme.Text
nameFrame.BackgroundTransparency = 1
nameFrame.Size = UDim2.new(1,0,1,0)
editAttributeButton.Visible = false
local showingAttrs =
Settings.Properties.ShowAttributes
toggleAttributes.Position = UDim2.new(1,-85-
leftOffset,0,0)
toggleAttributes.Text = (showingAttrs and
"[Setting: ON]" or "[Setting: OFF]")
toggleAttributes.TextColor3 =
Settings.Theme.Text
toggleAttributes.Visible = (prop.CategoryName
== "Attributes")
else
local propName = prop.Name
local typeData = prop.ValueType
local typeName = typeData.Name
local tags = prop.Tags
local propObj = autoUpdateObjs[gName]
expand.Visible = typeData.Category ==
"DataType" and Properties.ExpandableTypes[typeName] or
Properties.ExpandableProps[gName]
propNameBox.TextColor3 = tags.ReadOnly and
Settings.Theme.PlaceholderText or Settings.Theme.Text
-- Display property value
Properties.DisplayProp(prop,i)
if propObj then
if prop.IsAttribute then
propCons[#propCons+1] =
getAttributeChangedSignal(propObj,prop.AttributeName):Connect(function()
Properties.DisplayProp(prop,i)
end)
else
propCons[#propCons+1] =
getPropChangedSignal(propObj,propName):Connect(function()
Properties.DisplayProp(prop,i)
end)
end
end
if typeName == "NumberSequence" or
typeName == "ColorSequence" then
endOffset = 20
end
inputBox.Position =
UDim2.new(scale,offset,0,entry.Position.Y.Offset)
inputBox.Size = UDim2.new(1-scale,-
offset-endOffset-attributeOffset,0,22)
inputBox.Visible = true
valueBox.Visible = false
end
else
nameFrame.BackgroundColor3 =
Settings.Theme.Main1
nameFrame.BackgroundTransparency = 1
valueFrame.BackgroundColor3 =
Settings.Theme.Main1
valueFrame.BackgroundTransparency = 1
valueBox.Visible = beforeVisible
end
end
-- Expand
if prop.CategoryName or
Properties.ExpandableTypes[prop.ValueType and prop.ValueType.Name] or
Properties.ExpandableProps[gName] then
if Lib.CheckMouseInGui(expand) then
Main.MiscIcons:DisplayByKey(expand.Icon,
expanded[gName] and "Collapse_Over" or "Expand_Over")
else
Main.MiscIcons:DisplayByKey(expand.Icon,
expanded[gName] and "Collapse" or "Expand")
end
expand.Visible = true
else
expand.Visible = false
end
end
entry.Visible = true
else
entry.Visible = false
end
end
for i = maxEntries+1,#propEntries do
propEntries[i].Gui:Destroy()
propEntries[i] = nil
checkboxes[i] = nil
end
end
Properties.SetProp = function(prop,val,noupdate,prevAttribute)
local sList = Explorer.Selection.List
local propName = prop.Name
local subName = prop.SubName
local propClass = prop.Class
local typeData = prop.ValueType
local typeName = typeData.Name
local attributeName = prop.AttributeName
local rootTypeData = prop.RootType
local rootTypeName = rootTypeData and rootTypeData.Name
local fullName = prop.Class.."."..prop.Name..(prop.SubName or "")
local Vector3 = Vector3
for i = 1,#sList do
local node = sList[i]
local obj = node.Obj
if isa(obj,propClass) then
pcall(function()
local setVal = val
local root
if prop.IsAttribute then
root = getAttribute(obj,attributeName)
else
root = obj[propName]
end
if prevAttribute then
if prevAttribute.ValueType.Name == typeName
then
setVal =
getAttribute(obj,prevAttribute.AttributeName) or setVal
end
setAttribute(obj,prevAttribute.AttributeName,nil)
end
if rootTypeName then
if rootTypeName == "Vector2" then
setVal = Vector2.new((subName == ".X" and
setVal) or root.X, (subName == ".Y" and setVal) or root.Y)
elseif rootTypeName == "Vector3" then
setVal = Vector3.new((subName == ".X" and
setVal) or root.X, (subName == ".Y" and setVal) or root.Y, (subName == ".Z" and
setVal) or root.Z)
elseif rootTypeName == "UDim" then
setVal = UDim.new((subName == ".Scale"
and setVal) or root.Scale, (subName == ".Offset" and setVal) or root.Offset)
elseif rootTypeName == "UDim2" then
local rootX,rootY = root.X,root.Y
local X_UDim = (subName == ".X" and
setVal) or UDim.new((subName == ".X.Scale" and setVal) or rootX.Scale, (subName ==
".X.Offset" and setVal) or rootX.Offset)
local Y_UDim = (subName == ".Y" and
setVal) or UDim.new((subName == ".Y.Scale" and setVal) or rootY.Scale, (subName ==
".Y.Offset" and setVal) or rootY.Offset)
setVal = UDim2.new(X_UDim,Y_UDim)
elseif rootTypeName == "CFrame" then
local rootPos,rootRight,rootUp,rootLook =
root.Position,root.RightVector,root.UpVector,root.LookVector
local pos = (subName == ".Position" and
setVal) or Vector3.new((subName == ".Position.X" and setVal) or rootPos.X, (subName
== ".Position.Y" and setVal) or rootPos.Y, (subName == ".Position.Z" and setVal) or
rootPos.Z)
local rightV = (subName == ".RightVector"
and setVal) or Vector3.new((subName == ".RightVector.X" and setVal) or rootRight.X,
(subName == ".RightVector.Y" and setVal) or rootRight.Y, (subName ==
".RightVector.Z" and setVal) or rootRight.Z)
local upV = (subName == ".UpVector" and
setVal) or Vector3.new((subName == ".UpVector.X" and setVal) or rootUp.X, (subName
== ".UpVector.Y" and setVal) or rootUp.Y, (subName == ".UpVector.Z" and setVal) or
rootUp.Z)
local lookV = (subName == ".LookVector"
and setVal) or Vector3.new((subName == ".LookVector.X" and setVal) or rootLook.X,
(subName == ".RightVector.Y" and setVal) or rootLook.Y, (subName ==
".RightVector.Z" and setVal) or rootLook.Z)
setVal =
CFrame.fromMatrix(pos,rightV,upV,-lookV)
elseif rootTypeName == "Rect" then
local rootMin,rootMax = root.Min,root.Max
local min = Vector2.new((subName ==
".Min.X" and setVal) or rootMin.X, (subName == ".Min.Y" and setVal) or rootMin.Y)
local max = Vector2.new((subName ==
".Max.X" and setVal) or rootMax.X, (subName == ".Max.Y" and setVal) or rootMax.Y)
setVal = Rect.new(min,max)
elseif rootTypeName == "PhysicalProperties"
then
local rootProps =
PhysicalProperties.new(obj.Material)
local density = (subName == ".Density"
and setVal) or (root and root.Density) or rootProps.Density
local friction = (subName == ".Friction"
and setVal) or (root and root.Friction) or rootProps.Friction
local elasticity = (subName ==
".Elasticity" and setVal) or (root and root.Elasticity) or rootProps.Elasticity
local frictionWeight = (subName ==
".FrictionWeight" and setVal) or (root and root.FrictionWeight) or
rootProps.FrictionWeight
local elasticityWeight = (subName ==
".ElasticityWeight" and setVal) or (root and root.ElasticityWeight) or
rootProps.ElasticityWeight
setVal =
PhysicalProperties.new(density,friction,elasticity,frictionWeight,elasticityWeight)
elseif rootTypeName == "Ray" then
local rootOrigin,rootDirection =
root.Origin,root.Direction
local origin = (subName == ".Origin" and
setVal) or Vector3.new((subName == ".Origin.X" and setVal) or rootOrigin.X,
(subName == ".Origin.Y" and setVal) or rootOrigin.Y, (subName == ".Origin.Z" and
setVal) or rootOrigin.Z)
local direction = (subName ==
".Direction" and setVal) or Vector3.new((subName == ".Direction.X" and setVal) or
rootDirection.X, (subName == ".Direction.Y" and setVal) or rootDirection.Y,
(subName == ".Direction.Z" and setVal) or rootDirection.Z)
setVal = Ray.new(origin,direction)
elseif rootTypeName == "Faces" then
local faces = {}
local faceList =
{"Back","Bottom","Front","Left","Right","Top"}
for _,face in pairs(faceList) do
local val
if subName == "."..face then
val = setVal
else
val = root[face]
end
if val then faces[#faces+1] =
Enum.NormalId[face] end
end
setVal = Faces.new(unpack(faces))
elseif rootTypeName == "Axes" then
local axes = {}
local axesList = {"X","Y","Z"}
for _,axe in pairs(axesList) do
local val
if subName == "."..axe then
val = setVal
else
val = root[axe]
end
if val then axes[#axes+1] =
Enum.Axis[axe] end
end
setVal = Axes.new(unpack(axes))
elseif rootTypeName == "NumberRange" then
setVal = NumberRange.new(subName ==
".Min" and setVal or root.Min, subName == ".Max" and setVal or root.Max)
end
end
if prop.IsAttribute then
setAttribute(obj,attributeName,setVal)
else
obj[propName] = setVal
end
end)
end
end
Properties.InitInputBox = function()
inputBox = create({
{1,"Frame",
{BackgroundColor3=Color3.new(0.14901961386204,0.14901961386204,0.14901961386204),Bo
rderSizePixel=0,Name="InputBox",Size=UDim2.new(0,200,0,22),Visible=false,ZIndex=2,}
},
{2,"TextBox",
{BackgroundColor3=Color3.new(0.17647059261799,0.17647059261799,0.17647059261799),Ba
ckgroundTransparency=1,BorderColor3=Color3.new(0.062745101749897,0.51764708757401,1
),BorderSizePixel=0,ClearTextOnFocus=false,Font=3,Parent={1},PlaceholderColor3=Colo
r3.new(0.69803923368454,0.69803923368454,0.69803923368454),Position=UDim2.new(0,3,0
,0),Size=UDim2.new(1,-
6,1,0),Text="",TextColor3=Color3.new(1,1,1),TextSize=14,TextXAlignment=0,ZIndex=2,}
},
})
inputTextBox = inputBox.TextBox
inputBox.BackgroundColor3 = Settings.Theme.TextBox
inputBox.Parent = Properties.Window.GuiElems.Content.List
inputTextBox.FocusLost:Connect(function()
if not inputProp then return end
inputTextBox.Focused:Connect(function()
inputTextBox.SelectionStart = 1
inputTextBox.CursorPosition = #inputTextBox.Text + 1
end)
Lib.ViewportTextBox.convert(inputTextBox)
end
Properties.SetInputProp = function(prop,entryIndex,special)
local typeData = prop.ValueType
local typeName = typeData.Name
local fullName = prop.Class.."."..prop.Name..(prop.SubName or "")
local propObj = autoUpdateObjs[fullName]
local propVal = Properties.GetPropVal(prop,propObj)
inputProp = prop
if special then
if special == "color" then
if typeName == "Color3" then
inputTextBox.Text = propVal and
Properties.ValueToString(prop,propVal) or ""
Properties.DisplayColorEditor(prop,propVal)
elseif typeName == "BrickColor" then
Properties.DisplayBrickColorEditor(prop,entryIndex,propVal)
elseif typeName == "ColorSequence" then
inputTextBox.Text = propVal and
Properties.ValueToString(prop,propVal) or ""
Properties.DisplayColorSequenceEditor(prop,propVal)
end
elseif special == "right" then
if typeName == "NumberSequence" then
inputTextBox.Text = propVal and
Properties.ValueToString(prop,propVal) or ""
Properties.DisplayNumberSequenceEditor(prop,propVal)
elseif typeName == "ColorSequence" then
inputTextBox.Text = propVal and
Properties.ValueToString(prop,propVal) or ""
Properties.DisplayColorSequenceEditor(prop,propVal)
end
end
else
if Properties.IsTextEditable(prop) then
inputTextBox.Text = propVal and
Properties.ValueToString(prop,propVal) or ""
inputTextBox:CaptureFocus()
elseif typeData.Category == "Enum" then
Properties.DisplayEnumDropdown(entryIndex)
elseif typeName == "BrickColor" then
Properties.DisplayBrickColorEditor(prop,entryIndex,propVal)
end
end
Properties.Refresh()
end
Properties.InitSearch = function()
local searchBox = Properties.GuiElems.ToolBar.SearchFrame.SearchBox
Lib.ViewportTextBox.convert(searchBox)
searchBox:GetPropertyChangedSignal("Text"):Connect(function()
Properties.SearchText = searchBox.Text
Properties.Update()
Properties.Refresh()
end)
end
Properties.InitEntryStuff = function()
Properties.EntryTemplate = create({
{1,"TextButton",
{AutoButtonColor=false,BackgroundColor3=Color3.new(0.17647059261799,0.1764705926179
9,0.17647059261799),BorderColor3=Color3.new(0.1294117718935,0.1294117718935,0.12941
17718935),Font=3,Name="Entry",Position=UDim2.new(0,1,0,1),Size=UDim2.new(0,250,0,22
),Text="",TextSize=14,}},
{2,"Frame",
{BackgroundColor3=Color3.new(0.04313725605607,0.35294118523598,0.68627452850342),Ba
ckgroundTransparency=1,BorderColor3=Color3.new(0.33725491166115,0.49019610881805,0.
73725491762161),BorderSizePixel=0,Name="NameFrame",Parent={1},Position=UDim2.new(0,
20,0,0),Size=UDim2.new(1,-40,1,0),}},
{3,"TextLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Font=3,Name="PropName"
,Parent={2},Position=UDim2.new(0,2,0,0),Size=UDim2.new(1,-
2,1,0),Text="Anchored",TextColor3=Color3.new(1,1,1),TextSize=14,TextTransparency=0.
10000000149012,TextTruncate=1,TextXAlignment=0,}},
{4,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,ClipsDescendants=true,
Font=3,Name="Expand",Parent={2},Position=UDim2.new(0,-
20,0,1),Size=UDim2.new(0,20,0,20),Text="",TextSize=14,Visible=false,}},
{5,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxassetid://
5642383285",ImageRectOffset=Vector2.new(144,16),ImageRectSize=Vector2.new(16,16),Na
me="Icon",Parent={4},Position=UDim2.new(0,2,0,2),ScaleType=4,Size=UDim2.new(0,16,0,
16),}},
{6,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Font
=4,Name="ToggleAttributes",Parent={2},Position=UDim2.new(1,-
85,0,0),Size=UDim2.new(0,85,0,22),Text="[SETTING:
OFF]",TextColor3=Color3.new(1,1,1),TextSize=14,TextTransparency=0.10000000149012,Vi
sible=false,}},
{7,"Frame",
{BackgroundColor3=Color3.new(0.04313725605607,0.35294118523598,0.68627452850342),Ba
ckgroundTransparency=1,BorderColor3=Color3.new(0.33725491166115,0.49019607901573,0.
73725491762161),BorderSizePixel=0,Name="ValueFrame",Parent={1},Position=UDim2.new(1
,-100,0,0),Size=UDim2.new(0,80,1,0),}},
{8,"Frame",
{BackgroundColor3=Color3.new(0.14117647707462,0.14117647707462,0.14117647707462),Bo
rderColor3=Color3.new(0.33725491166115,0.49019610881805,0.73725491762161),BorderSiz
ePixel=0,Name="Line",Parent={7},Position=UDim2.new(0,-
1,0,0),Size=UDim2.new(0,1,1,0),}},
{9,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Font
=3,Name="ColorButton",Parent={7},Size=UDim2.new(0,20,0,22),Text="",TextColor3=Color
3.new(1,1,1),TextSize=14,Visible=false,}},
{10,"Frame",
{BackgroundColor3=Color3.new(1,1,1),BorderColor3=Color3.new(0,0,0),Name="ColorPrevi
ew",Parent={9},Position=UDim2.new(0,5,0,6),Size=UDim2.new(0,10,0,10),}},
{11,"UIGradient",{Parent={10},}},
{12,"Frame",
{BackgroundTransparency=1,Name="EnumArrow",Parent={7},Position=UDim2.new(1,-
16,0,3),Size=UDim2.new(0,16,0,16),Visible=false,}},
{13,"Frame",
{BackgroundColor3=Color3.new(0.86274510622025,0.86274510622025,0.86274510622025),Bo
rderSizePixel=0,Parent={12},Position=UDim2.new(0,8,0,9),Size=UDim2.new(0,1,0,1),}},
{14,"Frame",
{BackgroundColor3=Color3.new(0.86274510622025,0.86274510622025,0.86274510622025),Bo
rderSizePixel=0,Parent={12},Position=UDim2.new(0,7,0,8),Size=UDim2.new(0,3,0,1),}},
{15,"Frame",
{BackgroundColor3=Color3.new(0.86274510622025,0.86274510622025,0.86274510622025),Bo
rderSizePixel=0,Parent={12},Position=UDim2.new(0,6,0,7),Size=UDim2.new(0,5,0,1),}},
{16,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Font=3,Name="ValueBox"
,Parent={7},Position=UDim2.new(0,4,0,0),Size=UDim2.new(1,-
8,1,0),Text="",TextColor3=Color3.new(1,1,1),TextSize=14,TextTransparency=0.10000000
149012,TextTruncate=1,TextXAlignment=0,}},
{17,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Font
=3,Name="RightButton",Parent={7},Position=UDim2.new(1,-
20,0,0),Size=UDim2.new(0,20,0,22),Text="...",TextColor3=Color3.new(1,1,1),TextSize=
14,Visible=false,}},
{18,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Font
=3,Name="SettingsButton",Parent={7},Position=UDim2.new(1,-
20,0,0),Size=UDim2.new(0,20,0,22),Text="",TextColor3=Color3.new(1,1,1),TextSize=14,
Visible=false,}},
{19,"Frame",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Name="SoundPreview",Pa
rent={7},Size=UDim2.new(1,0,1,0),Visible=false,}},
{20,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Font
=3,Name="ControlButton",Parent={19},Size=UDim2.new(0,20,0,22),Text="",TextColor3=Co
lor3.new(1,1,1),TextSize=14,}},
{21,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxassetid://
5642383285",ImageRectOffset=Vector2.new(144,16),ImageRectSize=Vector2.new(16,16),Na
me="Icon",Parent={20},Position=UDim2.new(0,2,0,3),ScaleType=4,Size=UDim2.new(0,16,0
,16),}},
{22,"Frame",
{BackgroundColor3=Color3.new(0.3137255012989,0.3137255012989,0.3137255012989),Borde
rSizePixel=0,Name="TimeLine",Parent={19},Position=UDim2.new(0,26,0.5,-
1),Size=UDim2.new(1,-34,0,2),}},
{23,"Frame",
{BackgroundColor3=Color3.new(0.2352941185236,0.2352941185236,0.2352941185236),Borde
rColor3=Color3.new(0.1294117718935,0.1294117718935,0.1294117718935),Name="Slider",P
arent={22},Position=UDim2.new(0,-4,0,-8),Size=UDim2.new(0,8,0,18),}},
{24,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Font
=3,Name="EditAttributeButton",Parent={1},Position=UDim2.new(1,-
20,0,0),Size=UDim2.new(0,20,0,22),Text="",TextColor3=Color3.new(1,1,1),TextSize=14,
}},
{25,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxassetid://
5034718180",ImageTransparency=0.20000000298023,Name="Icon",Parent={24},Position=UDi
m2.new(0,2,0,3),Size=UDim2.new(0,16,0,16),}},
{26,"TextButton",
{AutoButtonColor=false,BackgroundColor3=Color3.new(0.2352941185236,0.2352941185236,
0.2352941185236),BorderSizePixel=0,Font=3,Name="RowButton",Parent={1},Size=UDim2.ne
w(1,0,1,0),Text="Add
Attribute",TextColor3=Color3.new(1,1,1),TextSize=14,TextTransparency=0.100000001490
12,Visible=false,}},
})
Properties.FullNameFrame = fullNameFrame
Properties.FullNameFrameAttach = Lib.AttachTo(fullNameFrame)
end
-- Vars
categoryOrder = API.CategoryOrder
for category,_ in next,categoryOrder do
if not Properties.CollapsedCategories[category] then
expanded["CAT_"..category] = true
end
end
expanded["Sound.SoundId"] = true
-- Init window
window = Lib.Window.new()
Properties.Window = window
window:SetTitle("Properties")
toolBar = guiItems.ToolBar
propsFrame = guiItems.List
Properties.GuiElems.ToolBar = toolBar
Properties.GuiElems.PropsFrame = propsFrame
Properties.InitEntryStuff()
-- Window events
window.GuiElems.Main:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
if Properties.Window:IsContentVisible() then
Properties.UpdateView()
Properties.Refresh()
end
end)
window.OnActivate:Connect(function()
Properties.UpdateView()
Properties.Update()
Properties.Refresh()
end)
window.OnRestore:Connect(function()
Properties.UpdateView()
Properties.Update()
Properties.Refresh()
end)
-- Init scrollbars
scrollV = Lib.ScrollBar.new()
scrollV.WheelIncrement = 3
scrollV.Gui.Position = UDim2.new(1,-16,0,23)
scrollV:SetScrollFrame(propsFrame)
scrollV.Scrolled:Connect(function()
Properties.Index = scrollV.Index
Properties.Refresh()
end)
scrollH = Lib.ScrollBar.new(true)
scrollH.Increment = 5
scrollH.WheelIncrement = 20
scrollH.Gui.Position = UDim2.new(0,0,1,-16)
scrollH.Scrolled:Connect(function()
Properties.Refresh()
end)
-- Setup Gui
window.GuiElems.Line.Position = UDim2.new(0,0,0,22)
toolBar.Parent = window.GuiElems.Content
propsFrame.Parent = window.GuiElems.Content
guiItems.ScrollCorner.Parent = window.GuiElems.Content
scrollV.Gui.Parent = window.GuiElems.Content
scrollH.Gui.Parent = window.GuiElems.Content
Properties.InitInputBox()
Properties.InitSearch()
end
return Properties
end
-- Common Locals
local Main,Lib,Apps,Settings -- Main Containers
local Explorer, Properties, ScriptViewer, Notebook -- Major Apps
local API,RMD,env,service,plr,create,createSimple -- Main Locals
API = data.API
RMD = data.RMD
env = data.env
service = data.service
plr = data.plr
create = data.create
createSimple = data.createSimple
end
ScriptViewer.ViewScript = function(scr)
local success, source = pcall(env.decompile or function() end, scr)
if not success or not source then source, PreviousScr = "-- DEX -
Source failed to decompile", nil else PreviousScr = scr end
codeFrame:SetText(source)
window:Show()
end
ScriptViewer.Init = function()
window = Lib.Window.new()
window:SetTitle("Script Viewer")
window:Resize(500,400)
ScriptViewer.Window = window
codeFrame = Lib.CodeFrame.new()
codeFrame.Frame.Position = UDim2.new(0,0,0,20)
codeFrame.Frame.Size = UDim2.new(1,0,1,-20)
codeFrame.Frame.Parent = window.GuiElems.Content
copy.MouseButton1Click:Connect(function()
local source = codeFrame:GetText()
setclipboard(source)
end)
save.MouseButton1Click:Connect(function()
local source = codeFrame:GetText()
local filename =
"Place_"..game.PlaceId.."_Script_"..os.time()..".txt"
writefile(filename,source)
if movefileas then -- TODO: USE ENV
movefileas(filename,".txt")
end
end)
dumpbtn.MouseButton1Click:Connect(function()
if PreviousScr ~= nil then
pcall(function()
-- thanks King.Kevin#6025 you'll obviously be credited (no
discord tag since that can easily be impersonated)
local getgc = getgc or get_gc_objects
local getupvalues = (debug and debug.getupvalues) or
getupvalues or getupvals
local getconstants = (debug and debug.getconstants) or
getconstants or getconsts
local getinfo = (debug and (debug.getinfo or debug.info)) or
getinfo
local original = ("\n-- // Function Dumper made by King.Kevin\
n-- // Script Path: %s\n\n--[["):format(PreviousScr:GetFullName())
local dump = original
local functions, function_count, data_base = {}, 0, {}
function functions:add_to_dump(str, indentation, new_line)
local new_line = new_line or true
dump = dump .. ("%s%s%s"):format(string.rep(" ",
indentation), tostring(str), new_line and "\n" or "")
end
function functions:get_function_name(func)
local n = getinfo(func).name
return n ~= "" and n or "Unknown Name"
end
function functions:dump_table(input, indent, index)
local indent = indent < 0 and 0 or indent
functions:add_to_dump(("%s [%s]
%s"):format(tostring(index), tostring(typeof(input)), tostring(input)), indent - 1)
local count = 0
for index, value in pairs(input) do
count = count + 1
if type(value) == "function" then
functions:add_to_dump(("%d [function] =
%s"):format(count, functions:get_function_name(value)), indent)
elseif type(value) == "table" then
if not data_base[value] then
data_base[value] = true
functions:add_to_dump(("%d
[table]:"):format(count), indent)
functions:dump_table(value, indent + 1, index)
else
functions:add_to_dump(("%d [table] (Recursive
table detected)"):format(count), indent)
end
else
functions:add_to_dump(("%d [%s] =
%s"):format(count, tostring(typeof(value)), tostring(value)), indent)
end
end
end
function functions:dump_function(input, indent)
functions:add_to_dump(("\nFunction Dump:
%s"):format(functions:get_function_name(input)), indent)
functions:add_to_dump(("\nFunction Upvalues:
%s"):format(functions:get_function_name(input)), indent)
for index, upvalue in pairs(getupvalues(input)) do
if type(upvalue) == "function" then
functions:add_to_dump(("%d [function] =
%s"):format(index, functions:get_function_name(upvalue)), indent + 1)
elseif type(upvalue) == "table" then
if not data_base[upvalue] then
data_base[upvalue] = true
functions:add_to_dump(("%d
[table]:"):format(index), indent + 1)
functions:dump_table(upvalue, indent + 2,
index)
else
functions:add_to_dump(("%d [table] (Recursive
table detected)"):format(index), indent + 1)
end
else
functions:add_to_dump(("%d [%s] =
%s"):format(index, tostring(typeof(upvalue)), tostring(upvalue)), indent + 1)
end
end
functions:add_to_dump(("\nFunction Constants:
%s"):format(functions:get_function_name(input)), indent)
for index, constant in pairs(getconstants(input)) do
if type(constant) == "function" then
functions:add_to_dump(("%d [function] =
%s"):format(index, functions:get_function_name(constant)), indent + 1)
elseif type(constant) == "table" then
if not data_base[constant] then
data_base[constant] = true
functions:add_to_dump(("%d
[table]:"):format(index), indent + 1)
functions:dump_table(constant, indent + 2,
index)
else
functions:add_to_dump(("%d [table] (Recursive
table detected)"):format(index), indent + 1)
end
else
functions:add_to_dump(("%d [%s] =
%s"):format(index, tostring(typeof(constant)), tostring(constant)), indent + 1)
end
end
end
for _, _function in pairs(getgc()) do
if typeof(_function) == "function" and
getfenv(_function).script and getfenv(_function).script == PreviousScr then
functions:dump_function(_function, 0)
functions:add_to_dump("\n" .. ("="):rep(100), 0, false)
end
end
local source = codeFrame:GetText()
if dump ~= original then source = source .. dump .. "]]" end
codeFrame:SetText(source)
end)
end
end)
end
return ScriptViewer
end
-- Common Locals
local Main,Lib,Apps,Settings -- Main Containers
local Explorer, Properties, ScriptViewer, Notebook -- Major Apps
local API,RMD,env,service,plr,create,createSimple -- Main Locals
API = data.API
RMD = data.RMD
env = data.env
service = data.service
plr = data.plr
create = data.create
createSimple = data.createSimple
end
-- Functions
Lib.FormatLuaString = (function()
local string = string
local gsub = string.gsub
local format = string.format
local char = string.char
local cleanTable = {['"'] = '\\"', ['\\'] = '\\\\'}
for i = 0,31 do
cleanTable[char(i)] = "\\"..format("%03d",i)
end
for i = 127,255 do
cleanTable[char(i)] = "\\"..format("%03d",i)
end
return function(str)
return gsub(str,"[\"\\\0-\31\127-\255]",cleanTable)
end
end)()
Lib.CheckMouseInGui = function(gui)
if gui == nil then return false end
local mouse = Main.Mouse
local guiPosition = gui.AbsolutePosition
local guiSize = gui.AbsoluteSize
Lib.IsShiftDown = function()
return service.UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) or
service.UserInputService:IsKeyDown(Enum.KeyCode.RightShift)
end
Lib.IsCtrlDown = function()
return service.UserInputService:IsKeyDown(Enum.KeyCode.LeftControl) or
service.UserInputService:IsKeyDown(Enum.KeyCode.RightControl)
end
Lib.CreateArrow = function(size,num,dir)
local max = num
local arrowFrame = createSimple("Frame",{
BackgroundTransparency = 1,
Name = "Arrow",
Size = UDim2.new(0,size,0,size)
})
if dir == "up" then
for i = 1,num do
local newLine = createSimple("Frame",{
BackgroundColor3 =
Color3.new(220/255,220/255,220/255),
BorderSizePixel = 0,
Position = UDim2.new(0,math.floor(size/2)-(i-
1),0,math.floor(size/2)+i-math.floor(max/2)-1),
Size = UDim2.new(0,i+(i-1),0,1),
Parent = arrowFrame
})
end
return arrowFrame
elseif dir == "down" then
for i = 1,num do
local newLine = createSimple("Frame",{
BackgroundColor3 =
Color3.new(220/255,220/255,220/255),
BorderSizePixel = 0,
Position = UDim2.new(0,math.floor(size/2)-(i-
1),0,math.floor(size/2)-i+math.floor(max/2)+1),
Size = UDim2.new(0,i+(i-1),0,1),
Parent = arrowFrame
})
end
return arrowFrame
elseif dir == "left" then
for i = 1,num do
local newLine = createSimple("Frame",{
BackgroundColor3 =
Color3.new(220/255,220/255,220/255),
BorderSizePixel = 0,
Position = UDim2.new(0,math.floor(size/2)+i-
math.floor(max/2)-1,0,math.floor(size/2)-(i-1)),
Size = UDim2.new(0,1,0,i+(i-1)),
Parent = arrowFrame
})
end
return arrowFrame
elseif dir == "right" then
for i = 1,num do
local newLine = createSimple("Frame",{
BackgroundColor3 =
Color3.new(220/255,220/255,220/255),
BorderSizePixel = 0,
Position = UDim2.new(0,math.floor(size/2)-
i+math.floor(max/2)+1,0,math.floor(size/2)-(i-1)),
Size = UDim2.new(0,1,0,i+(i-1)),
Parent = arrowFrame
})
end
return arrowFrame
end
error("r u ok")
end
Lib.ParseXML = (function()
local func = function()
-- Only exists to parse RMD
-- from https://github.com/jonathanpoelen/xmlparser
-- http://lua-users.org/wiki/StringTrim
local trim = function(s)
local from = s:match"^%s*()"
return from > #s and "" or s:match(".*%S", from)
end
if evalEntities then
local pos = s:find('<[_%w]')
if pos then
s:sub(1, pos):gsub('<!ENTITY%s+([_%w]+)%s+(.)
(.-)%2', function(name, q, entity)
entities[#entities+1] = {name=name,
value=entity}
end)
tentities = createEntityTable(entities)
s = replaceEntities(s:sub(pos), tentities)
end
end
local t, l = {}, {}
s:gsub('<([?!/]?)([-:_%w]+)%s*(/?>?)([^<]*)',
function(type, name, closed, txt)
-- open
if #type == 0 then
local a = {}
if #closed == 0 then
local len = 0
for all,aname,_,value,starttxt in
string.gmatch(txt, "(.-([-_%w]+)%s*=%s*(.)(.-)%3%s*(/?>?))") do
len = len + #all
a[aname] = value
if #starttxt ~= 0 then
txt = txt:sub(len+1)
closed = starttxt
break
end
end
end
t[#t+1] = {tag=name, attrs=a, children={}}
addtext(txt)
-- close
elseif '/' == type then
t = l[#l]
l[#l] = nil
addtext(txt)
-- ENTITY
elseif '!' == type then
if E == name:byte(1) then
txt:gsub('([_%w]+)%s+(.)(.-)%2',
function(name, q, entity)
entities[#entities+1] = {name=name,
value=entity}
end, 1)
end
-- elseif '?' == type then
-- print('? ' .. name .. ' // ' .. attrs ..
'$$')
-- elseif '-' == type then
-- print('comment ' .. name .. ' // ' ..
attrs .. '$$')
-- else
-- print('o ' .. #p .. ' // ' .. name ..
' // ' .. attrs .. '$$')
end
end)
function parseText(txt)
return parse(txt)
end
function defaultEntityTable()
return { quot='"', apos='\'', lt='<', gt='>', amp='&',
tab='\t', nbsp=' ', }
end
return parseText
end
local newEnv = setmetatable({},{__index = getfenv()})
setfenv(func,newEnv)
return func()
end)()
Lib.FastWait = function(s)
if not s then return signalWait(renderStepped) end
local start = tick()
while tick() - start < s do signalWait(renderStepped) end
end
Lib.ButtonAnim = function(button,data)
local holding = false
local disabled = false
local mode = data and data.Mode or 1
local control = {}
if mode == 2 then
local lerpTo = data.LerpTo or Color3.new(0,0,0)
local delta = data.LerpDelta or 0.2
control.StartColor = data.StartColor or button.BackgroundColor3
control.PressColor = data.PressColor or
control.StartColor:lerp(lerpTo,delta)
control.HoverColor = data.HoverColor or
control.StartColor:lerp(control.PressColor,0.6)
control.OutlineColor = data.OutlineColor
end
button.InputBegan:Connect(function(input)
if disabled then return end
if input.UserInputType == Enum.UserInputType.MouseMovement and
not holding then
if mode == 1 then
button.BackgroundTransparency = 0.4
elseif mode == 2 then
button.BackgroundColor3 = control.HoverColor
end
elseif input.UserInputType == Enum.UserInputType.MouseButton1
then
holding = true
if mode == 1 then
button.BackgroundTransparency = 0
elseif mode == 2 then
button.BackgroundColor3 = control.PressColor
if control.OutlineColor then button.BorderColor3 =
control.PressColor end
end
end
end)
button.InputEnded:Connect(function(input)
if disabled then return end
if input.UserInputType == Enum.UserInputType.MouseMovement and
not holding then
if mode == 1 then
button.BackgroundTransparency = 1
elseif mode == 2 then
button.BackgroundColor3 = control.StartColor
end
elseif input.UserInputType == Enum.UserInputType.MouseButton1
then
holding = false
if mode == 1 then
button.BackgroundTransparency =
Lib.CheckMouseInGui(button) and 0.4 or 1
elseif mode == 2 then
button.BackgroundColor3 = Lib.CheckMouseInGui(button)
and control.HoverColor or control.StartColor
if control.OutlineColor then button.BorderColor3 =
control.OutlineColor end
end
end
end)
control.Disable = function()
disabled = true
holding = false
if mode == 1 then
button.BackgroundTransparency = 1
elseif mode == 2 then
button.BackgroundColor3 = control.StartColor
end
end
control.Enable = function()
disabled = false
end
return control
end
Lib.FindAndRemove = function(t,item)
local pos = table.find(t,item)
if pos then table.remove(t,pos) end
end
Lib.AttachTo = function(obj,data)
local target,posOffX,posOffY,sizeOffX,sizeOffY,resize,con
local disabled = false
update()
end
setup(obj,data)
return {
SetData = function(obj,data)
setup(obj,data)
end,
Enable = function()
disabled = false
update()
end,
Disable = function()
disabled = true
end,
Destroy = function()
con:Disconnect()
con = nil
end,
}
end
Lib.ProtectedGuis = {}
Lib.ShowGui = function(gui)
if env.protectgui then
env.protectgui(gui)
end
gui.Parent = Main.GuiHolder
end
Lib.ColorToBytes = function(col)
local round = math.round
return string.format("%d, %d,
%d",round(col.r*255),round(col.g*255),round(col.b*255))
end
Lib.ReadFile = function(filename)
if not env.readfile then return end
Lib.DeferFunc = function(f,...)
signalWait(renderStepped)
return f(...)
end
Lib.LoadCustomAsset = function(filepath)
if not env.getcustomasset or not env.isfile or not env.isfile(filepath)
then return end
return env.getcustomasset(filepath)
end
Lib.FetchCustomAsset = function(url,filepath)
if not env.writefile then return end
env.writefile(filepath,data)
return Lib.LoadCustomAsset(filepath)
end
-- Classes
Lib.Signal = (function()
local funcs = {}
funcs.Connect = function(self,func)
if type(func) ~= "function" then error("Attempt to connect a non-
function") end
local con = {
Signal = self,
Func = func,
Disconnect = disconnect
}
self.Connections[#self.Connections+1] = con
return con
end
funcs.Fire = function(self,...)
for i,v in next,self.Connections do
xpcall(coroutine.wrap(v.Func),function(e) warn(e.."\
n"..debug.traceback()) end,...)
end
end
local mt = {
__index = funcs,
__tostring = function(self)
return "Signal: " .. tostring(#self.Connections) .. "
Connections"
end
}
return setmetatable(obj,mt)
end
Lib.Set = (function()
local funcs = {}
funcs.Add = function(self,obj)
if self.Map[obj] then return end
funcs.AddTable = function(self,t)
local changed
local list,map = self.List,self.Map
for i = 1,#t do
local elem = t[i]
if not map[elem] then
list[#list+1] = elem
map[elem] = true
changed = true
end
end
if changed then self.Changed:Fire() end
end
funcs.Remove = function(self,obj)
if not self.Map[obj] then return end
funcs.RemoveTable = function(self,t)
local changed
local list,map = self.List,self.Map
local removeSet = {}
for i = 1,#t do
local elem = t[i]
map[elem] = nil
removeSet[elem] = true
end
for i = #list,1,-1 do
local elem = list[i]
if removeSet[elem] then
table.remove(list,i)
changed = true
end
end
if changed then self.Changed:Fire() end
end
funcs.Set = function(self,obj)
if #self.List == 1 and self.List[1] == obj then return end
self.List = {obj}
self.Map = {[obj] = true}
self.Changed:Fire()
end
funcs.SetTable = function(self,t)
local newList,newMap = {},{}
self.List,self.Map = newList,newMap
table.move(t,1,#t,1,newList)
for i = 1,#t do
newMap[t[i]] = true
end
self.Changed:Fire()
end
funcs.Clear = function(self)
if #self.List == 0 then return end
self.List = {}
self.Map = {}
self.Changed:Fire()
end
return obj
end
Lib.IconMap = (function()
local funcs = {}
funcs.GetLabel = function(self)
local label = Instance.new("ImageLabel")
self:SetupLabel(label)
return label
end
funcs.SetupLabel = function(self,obj)
obj.BackgroundTransparency = 1
obj.ImageRectOffset = Vector2.new(0,0)
obj.ImageRectSize = Vector2.new(self.IconSizeX,self.IconSizeY)
obj.ScaleType = Enum.ScaleType.Crop
obj.Size = UDim2.new(0,self.IconSizeX,0,self.IconSizeY)
end
funcs.Display = function(self,obj,index)
obj.Image = self.MapId
if not self.NumX then
obj.ImageRectOffset = Vector2.new(self.IconSizeX*index, 0)
else
obj.ImageRectOffset = Vector2.new(self.IconSizeX*(index %
self.NumX), self.IconSizeY*math.floor(index / self.NumX))
end
end
funcs.DisplayByKey = function(self,obj,key)
if self.IndexDict[key] then
self:Display(obj,self.IndexDict[key])
end
end
funcs.SetDict = function(self,dict)
self.IndexDict = dict
end
local mt = {}
mt.__index = funcs
Lib.ScrollBar = (function()
local funcs = {}
local user = service.UserInputService
local mouse = plr:GetMouse()
local checkMouseInGui = Lib.CheckMouseInGui
local createArrow = Lib.CreateArrow
if self.Horizontal then
scrollThumb.Size = UDim2.new(visible/total,0,1,0)
if scrollThumb.AbsoluteSize.X < 16 then
scrollThumb.Size = UDim2.new(0,16,1,0)
end
local fs = scrollThumbFrame.AbsoluteSize.X
local bs = scrollThumb.AbsoluteSize.X
scrollThumb.Position =
UDim2.new(self:GetScrollPercent()*(fs-bs)/fs,0,0,0)
else
scrollThumb.Size = UDim2.new(1,0,visible/total,0)
if scrollThumb.AbsoluteSize.Y < 16 then
scrollThumb.Size = UDim2.new(1,0,0,16)
end
local fs = scrollThumbFrame.AbsoluteSize.Y
local bs = scrollThumb.AbsoluteSize.Y
scrollThumb.Position =
UDim2.new(0,0,self:GetScrollPercent()*(fs-bs)/fs,0)
end
end
if self.Horizontal then
newFrame.Size = UDim2.new(1,0,0,16)
button1 = createSimple("ImageButton",{
Parent = newFrame,
Name = "Left",
Size = UDim2.new(0,16,0,16),
BackgroundTransparency = 1,
BorderSizePixel = 0,
AutoButtonColor = false
})
createArrow(16,4,"left").Parent = button1
button2 = createSimple("ImageButton",{
Parent = newFrame,
Name = "Right",
Position = UDim2.new(1,-16,0,0),
Size = UDim2.new(0,16,0,16),
BackgroundTransparency = 1,
BorderSizePixel = 0,
AutoButtonColor = false
})
createArrow(16,4,"right").Parent = button2
else
newFrame.Size = UDim2.new(0,16,1,0)
button1 = createSimple("ImageButton",{
Parent = newFrame,
Name = "Up",
Size = UDim2.new(0,16,0,16),
BackgroundTransparency = 1,
BorderSizePixel = 0,
AutoButtonColor = false
})
createArrow(16,4,"up").Parent = button1
button2 = createSimple("ImageButton",{
Parent = newFrame,
Name = "Down",
Position = UDim2.new(0,0,1,-16),
Size = UDim2.new(0,16,0,16),
BackgroundTransparency = 1,
BorderSizePixel = 0,
AutoButtonColor = false
})
createArrow(16,4,"down").Parent = button2
end
scrollThumb.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
and not thumbPress then scrollThumb.BackgroundTransparency = 0.2
scrollThumb.BackgroundColor3 = self.ThumbSelectColor end
if input.UserInputType ~= Enum.UserInputType.MouseButton1
then return end
buttonPress = false
thumbFramePress = false
thumbPress = true
scrollThumb.BackgroundTransparency = 0
local mouseOffset = mouse[dir] -
scrollThumb.AbsolutePosition[dir]
local mouseStart = mouse[dir]
local releaseEvent
local mouseEvent
releaseEvent = user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
releaseEvent:Disconnect()
if mouseEvent then mouseEvent:Disconnect() end
if checkMouseInGui(scrollThumb) then
scrollThumb.BackgroundTransparency = 0.2 else scrollThumb.BackgroundTransparency =
0 scrollThumb.BackgroundColor3 = self.ThumbColor end
thumbPress = false
end)
self:Update()
mouseEvent = user.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement and thumbPress and releaseEvent.Connected then
local thumbFrameSize =
scrollThumbFrame.AbsoluteSize[dir]-scrollThumb.AbsoluteSize[dir]
local pos = mouse[dir] -
scrollThumbFrame.AbsolutePosition[dir] - mouseOffset
if pos > thumbFrameSize then
pos = thumbFrameSize
elseif pos < 0 then
pos = 0
end
if lastThumbPos ~= pos then
lastThumbPos = pos
self:ScrollTo(math.floor(0.5+pos/thumbFrameSize*(self.TotalSpace-
self.VisibleSpace)))
end
wait()
end
end)
end)
scrollThumb.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
and not thumbPress then scrollThumb.BackgroundTransparency = 0
scrollThumb.BackgroundColor3 = self.ThumbColor end
end)
scrollThumbFrame.InputBegan:Connect(function(input)
if input.UserInputType ~= Enum.UserInputType.MouseButton1
or checkMouseInGui(scrollThumb) then return end
thumbPress = false
thumbFramePress = true
doTick()
local thumbFrameTick = tick()
local releaseEvent
releaseEvent = user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
releaseEvent:Disconnect()
thumbFramePress = false
end)
while thumbFramePress do
if tick() - thumbFrameTick >= 0.3 and
checkMouseInGui(scrollThumbFrame) then
doTick()
end
wait()
end
end)
newFrame.MouseWheelForward:Connect(function()
self:ScrollTo(self.Index - self.WheelIncrement)
end)
newFrame.MouseWheelBackward:Connect(function()
self:ScrollTo(self.Index + self.WheelIncrement)
end)
self.GuiElems.ScrollThumb = scrollThumb
self.GuiElems.ScrollThumbFrame = scrollThumbFrame
self.GuiElems.Button1 = button1
self.GuiElems.Button2 = button2
self.GuiElems.MarkerFrame = markerFrame
return newFrame
end
funcs.Update = function(self,nocallback)
local total = self.TotalSpace
local visible = self.VisibleSpace
local index = self.Index
local button1 = self.GuiElems.Button1
local button2 = self.GuiElems.Button2
self.Index = math.clamp(self.Index,0,math.max(0,total-visible))
if self:CanScrollUp() then
for i,v in pairs(button1.Arrow:GetChildren()) do
v.BackgroundTransparency = 0
end
else
button1.BackgroundTransparency = 1
for i,v in pairs(button1.Arrow:GetChildren()) do
v.BackgroundTransparency = 0.5
end
end
if self:CanScrollDown() then
for i,v in pairs(button2.Arrow:GetChildren()) do
v.BackgroundTransparency = 0
end
else
button2.BackgroundTransparency = 1
for i,v in pairs(button2.Arrow:GetChildren()) do
v.BackgroundTransparency = 0.5
end
end
drawThumb(self)
end
funcs.UpdateMarkers = function(self)
local markerFrame = self.GuiElems.MarkerFrame
markerFrame:ClearAllChildren()
funcs.AddMarker = function(self,ind,color)
self.Markers[ind] = color or Color3.new(0,0,0)
end
funcs.ScrollTo = function(self,ind,nocallback)
self.Index = ind
self:Update()
if not nocallback then
self.Scrolled:Fire()
end
end
funcs.ScrollUp = function(self)
self.Index = self.Index - self.Increment
self:Update()
end
funcs.ScrollDown = function(self)
self.Index = self.Index + self.Increment
self:Update()
end
funcs.CanScrollUp = function(self)
return self.Index > 0
end
funcs.CanScrollDown = function(self)
return self.Index + self.VisibleSpace < self.TotalSpace
end
funcs.GetScrollPercent = function(self)
return self.Index/(self.TotalSpace-self.VisibleSpace)
end
funcs.SetScrollPercent = function(self,perc)
self.Index = math.floor(perc*(self.TotalSpace-self.VisibleSpace))
self:Update()
end
funcs.Texture = function(self,data)
self.ThumbColor = data.ThumbColor or Color3.new(0,0,0)
self.ThumbSelectColor = data.ThumbSelectColor or
Color3.new(0,0,0)
self.GuiElems.ScrollThumb.BackgroundColor3 = data.ThumbColor or
Color3.new(0,0,0)
self.Gui.BackgroundColor3 = data.FrameColor or Color3.new(0,0,0)
self.GuiElems.Button1.BackgroundColor3 = data.ButtonColor or
Color3.new(0,0,0)
self.GuiElems.Button2.BackgroundColor3 = data.ButtonColor or
Color3.new(0,0,0)
for i,v in pairs(self.GuiElems.Button1.Arrow:GetChildren()) do
v.BackgroundColor3 = data.ArrowColor or Color3.new(0,0,0)
end
for i,v in pairs(self.GuiElems.Button2.Arrow:GetChildren()) do
v.BackgroundColor3 = data.ArrowColor or Color3.new(0,0,0)
end
end
funcs.SetScrollFrame = function(self,frame)
if self.ScrollUpEvent then self.ScrollUpEvent:Disconnect()
self.ScrollUpEvent = nil end
if self.ScrollDownEvent then self.ScrollDownEvent:Disconnect()
self.ScrollDownEvent = nil end
self.ScrollUpEvent = frame.MouseWheelForward:Connect(function()
self:ScrollTo(self.Index - self.WheelIncrement) end)
self.ScrollDownEvent =
frame.MouseWheelBackward:Connect(function() self:ScrollTo(self.Index +
self.WheelIncrement) end)
end
local mt = {}
mt.__index = funcs
Lib.Window = (function()
local funcs = {}
local static = {MinWidth = 200, FreeWidth = 200}
local mouse = plr:GetMouse()
local sidesGui,alignIndicator
local visibleWindows = {}
local leftSide = {Width = 300, Windows = {}, ResizeCons = {}, Hidden =
true}
local rightSide = {Width = 300, Windows = {}, ResizeCons = {}, Hidden =
true}
local displayOrderStart
local sideDisplayOrder
local sideTweenInfo =
TweenInfo.new(0.3,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
local tweens = {}
local isA = game.IsA
local theme = {
MainColor1 = Color3.fromRGB(52,52,52),
MainColor2 = Color3.fromRGB(45,45,45),
Button = Color3.fromRGB(60,60,60)
}
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
resizer.BackgroundTransparency = 0.5
elseif input.UserInputType ==
Enum.UserInputType.MouseButton1 then
local releaseEvent,mouseEvent
self.Resizing = resizer
resizer.BackgroundTransparency = 1
releaseEvent =
service.UserInputService.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
self.Resizing = false
resizer.BackgroundTransparency = 1
end
end)
mouseEvent =
service.UserInputService.InputChanged:Connect(function(input)
if self.Resizable and
self.ResizableInternal and input.UserInputType == Enum.UserInputType.MouseMovement
then
self:StopTweens()
local deltaX = input.Position.X -
resizer.AbsolutePosition.X - offX
local deltaY = input.Position.Y -
resizer.AbsolutePosition.Y - offY
if guiMain.AbsoluteSize.X +
deltaX*signX < self.MinX then deltaX = signX*(self.MinX - guiMain.AbsoluteSize.X)
end
if guiMain.AbsoluteSize.Y +
deltaY*signY < self.MinY then deltaY = signY*(self.MinY - guiMain.AbsoluteSize.Y)
end
if signY < 0 and
guiMain.AbsolutePosition.Y + deltaY < 0 then deltaY = -guiMain.AbsolutePosition.Y
end
guiMain.Position = guiMain.Position
+ UDim2.new(0,(signX < 0 and deltaX or 0),0,(signY < 0 and deltaY or 0))
self.SizeX = self.SizeX + (isH and
deltaX*signX or 0)
self.SizeY = self.SizeY + (isV and
deltaY*signY or 0)
guiMain.Size =
UDim2.new(0,self.SizeX,0,self.Minimized and 20 or self.SizeY)
resizer.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
and self.Resizing ~= resizer then
resizer.BackgroundTransparency = 1
end
end)
end
local updateWindows
return true
end
return pos,range
end
self.GuiElems.Main = guiMain
self.GuiElems.TopBar = guiMain.TopBar
self.GuiElems.Content = guiMain.Content
self.GuiElems.Line = guiMain.Content.Line
self.GuiElems.Outlines = guiMain.Outlines
self.GuiElems.Title = guiTopBar.Title
self.GuiElems.Close = guiTopBar.Close
self.GuiElems.Minimize = guiTopBar.Minimize
self.GuiElems.ResizeControls = guiResizeControls
self.ContentPane = guiMain.Content
guiTopBar.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
and self.Draggable then
local releaseEvent,mouseEvent
local alignInsertPos,alignInsertSide
guiDragging = true
releaseEvent =
clonerefs(game:GetService("UserInputService")).InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
guiDragging = false
alignIndicator.Parent = nil
if alignInsertSide then
local targetSide = (alignInsertSide
== "left" and leftSide) or (alignInsertSide == "right" and rightSide)
self:AlignTo(targetSide,alignInsertPos)
end
end
end)
mouseEvent =
clonerefs(game:GetService("UserInputService")).InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement and self.Draggable and not self.Closed then
if self.Aligned then
if leftSide.Resizing or
rightSide.Resizing then return end
local posX,posY = input.Position.X-
offX,input.Position.Y-offY
local delta = math.sqrt((posX-
initX)^2 + (posY-initY)^2)
if delta >= 5 then
self:SetAligned(false)
end
else
local inputX,inputY =
input.Position.X,input.Position.Y
local posX,posY = inputX-
offX,inputY-offY
if posY < 0 then posY = 0 end
guiMain.Position =
UDim2.new(0,posX,0,posY)
if self.Resizable and
self.Alignable then
if inputX < 25 then
if
sideHasRoom(leftSide,self.MinY or 100) then
local
insertPos,range = getSideInsertPos(leftSide,inputY)
alignIndicator.Indicator.Position = UDim2.new(0,-15,0,range[1])
alignIndicator.Indicator.Size = UDim2.new(0,40,0,range[2]-range[1])
Lib.ShowGui(alignIndicator)
alignInsertPos =
insertPos
alignInsertSide =
"left"
return
end
elseif inputX >= maxX - 25
then
if
sideHasRoom(rightSide,self.MinY or 100) then
local
insertPos,range = getSideInsertPos(rightSide,inputY)
alignIndicator.Indicator.Position = UDim2.new(0,maxX-25,0,range[1])
alignIndicator.Indicator.Size = UDim2.new(0,40,0,range[2]-range[1])
Lib.ShowGui(alignIndicator)
alignInsertPos =
insertPos
alignInsertSide =
"right"
return
end
end
end
alignIndicator.Parent = nil
alignInsertPos = nil
alignInsertSide = nil
end
end
end)
end
end)
guiTopBar.Close.MouseButton1Click:Connect(function()
if self.Closed then return end
self:Close()
end)
guiTopBar.Minimize.MouseButton1Click:Connect(function()
if self.Closed then return end
if self.Aligned then
self:SetAligned(false)
else
self:SetMinimized()
end
end)
guiTopBar.Minimize.MouseButton2Click:Connect(function()
if self.Closed then return end
if not self.Aligned then
self:SetMinimized(nil,2)
guiTopBar.Minimize.BackgroundTransparency = 1
end
end)
guiMain.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
and not self.Aligned and not self.Closed then
moveToTop(self)
end
end)
guiMain:GetPropertyChangedSignal("AbsolutePosition"):Connect(function()
local absPos = guiMain.AbsolutePosition
self.PosX = absPos.X
self.PosY = absPos.Y
end)
resizeHook(self,guiResizeControls.North,"N")
resizeHook(self,guiResizeControls.NorthEast,"NE")
resizeHook(self,guiResizeControls.East,"E")
resizeHook(self,guiResizeControls.SouthEast,"SE")
resizeHook(self,guiResizeControls.South,"S")
resizeHook(self,guiResizeControls.SouthWest,"SW")
resizeHook(self,guiResizeControls.West,"W")
resizeHook(self,guiResizeControls.NorthWest,"NW")
guiMain.Size = UDim2.new(0,self.SizeX,0,self.SizeY)
gui.DescendantAdded:Connect(function(obj) focusInput(self,obj)
end)
local descs = gui:GetDescendants()
for i = 1,#descs do
focusInput(self,descs[i])
end
self.MinimizeAnim = Lib.ButtonAnim(guiTopBar.Minimize)
self.CloseAnim = Lib.ButtonAnim(guiTopBar.Close)
return gui
end
leftSide.Frame:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.Out,Enum.Easin
gStyle.Quad,0.3,true)
elseif #leftSide.Windows == 0 and leftSide.Frame.Position ==
UDim2.new(0,0,0,0) then
leftSide.Frame:TweenPosition(UDim2.new(0,-leftSide.Width-
5,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quad,0.3,true)
end
local rightTweenPos = (#rightSide.Windows == 0 and
UDim2.new(1,5,0,0) or UDim2.new(1,-rightSide.Width,0,0))
rightSide.Frame:TweenPosition(rightTweenPos,Enum.EasingDirection.Out,Enum.EasingSty
le.Quad,0.3,true)]]
local leftHidden = #leftSide.Windows == 0 or leftSide.Hidden
local rightHidden = #rightSide.Windows == 0 or rightSide.Hidden
local leftPos = (leftHidden and UDim2.new(0,-leftSide.Width-
10,0,0) or UDim2.new(0,0,0,0))
local rightPos = (rightHidden and UDim2.new(1,10,0,0) or
UDim2.new(1,-rightSide.Width,0,0))
resizer.InputBegan:Connect(function(input)
if not side.Resizing then
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
resizer.BackgroundColor3 = theme.MainColor2
elseif input.UserInputType ==
Enum.UserInputType.MouseButton1 then
local releaseEvent,mouseEvent
side.Resizing = resizer
resizer.BackgroundColor3 = theme.MainColor2
releaseEvent =
service.UserInputService.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
side.Resizing = false
resizer.BackgroundColor3 =
theme.Button
end
end)
mouseEvent =
service.UserInputService.InputChanged:Connect(function(input)
if not resizer.Parent then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
side.Resizing = false
return
end
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
if dir == "V" then
local delta =
input.Position.Y - resizer.AbsolutePosition.Y - offY
updateSideFrames()
sideResized(side)
elseif dir == "H" then
local maxWidth =
math.max(300,sidesGui.AbsoluteSize.X-static.FreeWidth)
local otherSide = (side ==
leftSide and rightSide or leftSide)
local delta =
input.Position.X - resizer.AbsolutePosition.X - offX
delta = (side == leftSide and
delta or -delta)
local proposedSize =
math.max(static.MinWidth,side.Width + delta)
if proposedSize +
otherSide.Width <= maxWidth then
side.Width =
proposedSize
else
local newOtherSize =
maxWidth - proposedSize
if newOtherSize >=
static.MinWidth then
side.Width =
proposedSize
otherSide.Width =
newOtherSize
else
side.Width =
maxWidth - static.MinWidth
otherSide.Width =
static.MinWidth
end
end
updateSideFrames(true)
sideResized(side)
sideResized(otherSide)
end
end
end)
end
end
end)
resizer.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
and side.Resizing ~= resizer then
resizer.BackgroundColor3 = theme.Button
end
end)
end
--side.Frame.Back.Position = UDim2.new(0,0,0,0)
--side.Frame.Back.Size = UDim2.new(0,side.Width,1,0)
end
local function updateSide(side,noTween)
local oldHeight = 0
local currentPos = 0
local neededSize = 0
local windows = side.Windows
local height = sidesGui.AbsoluteSize.Y - (math.max(0,#windows -
1) * 4)
updateWindows = function(noTween)
updateSideFrames(noTween)
updateSide(leftSide,noTween)
updateSide(rightSide,noTween)
local count = 0
for i = #visibleWindows,1,-1 do
visibleWindows[i].Gui.DisplayOrder = displayOrderStart +
count
Lib.ShowGui(visibleWindows[i].Gui)
count = count + 1
end
leftSide.Frame:TweenPosition(leftTweenPos,Enum.EasingDirection.Out,Enum.EasingStyle
.Quad,0.3,true)
local rightTweenPos = (#rightSide.Windows == 0 and
UDim2.new(1,5,0,0) or UDim2.new(1,-rightSide.Width,0,0))
rightSide.Frame:TweenPosition(rightTweenPos,Enum.EasingDirection.Out,Enum.EasingSty
le.Quad,0.3,true)]]
end
funcs.SetMinimized = function(self,set,mode)
local oldVal = self.Minimized
local newVal
if set == nil then newVal = not self.Minimized else newVal = set
end
self.Minimized = newVal
if not mode then mode = 1 end
self.GuiElems.Main:TweenSize(UDim2.new(0,self.SizeX,0,newVal and 20 or
self.SizeY),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,0.25,true)
else
local maxY = sidesGui.AbsoluteSize.Y
local newPos = UDim2.new(0,self.PosX,0,newVal and
math.min(maxY-20,self.PosY + self.SizeY - 20) or math.max(0,self.PosY - self.SizeY
+ 20))
self.GuiElems.Main:TweenPosition(newPos,Enum.EasingDirection.Out,Enum.EasingStyle.Q
uart,0.25,true)
self.GuiElems.Main:TweenSize(UDim2.new(0,self.SizeX,0,newVal and 20 or
self.SizeY),Enum.EasingDirection.Out,Enum.EasingStyle.Quart,0.25,true)
end
self.GuiElems.Minimize.ImageLabel.Image = newVal and
"rbxassetid://5060023708" or "rbxassetid://5034768003"
end
funcs.Resize = function(self,sizeX,sizeY)
self.SizeX = sizeX or self.SizeX
self.SizeY = sizeY or self.SizeY
self.GuiElems.Main.Size = UDim2.new(0,self.SizeX,0,self.SizeY)
end
funcs.SetSize = funcs.Resize
funcs.SetTitle = function(self,title)
self.GuiElems.Title.Text = title
end
funcs.SetResizable = function(self,val)
self.Resizable = val
self.GuiElems.ResizeControls.Visible = self.Resizable and
self.ResizableInternal
end
funcs.SetResizableInternal = function(self,val)
self.ResizableInternal = val
self.GuiElems.ResizeControls.Visible = self.Resizable and
self.ResizableInternal
end
funcs.SetAligned = function(self,val)
self.Aligned = val
self:SetResizableInternal(not val)
self.GuiElems.Main.Active = not val
self.GuiElems.Main.Outlines.Visible = not val
if not val then
for i,v in pairs(leftSide.Windows) do if v == self then
table.remove(leftSide.Windows,i) break end end
for i,v in pairs(rightSide.Windows) do if v == self then
table.remove(rightSide.Windows,i) break end end
if not table.find(visibleWindows,self) then
table.insert(visibleWindows,1,self) end
self.GuiElems.Minimize.ImageLabel.Image =
"rbxassetid://5034768003"
self.Side = nil
updateWindows()
else
self:SetMinimized(false,3)
for i,v in pairs(visibleWindows) do if v == self then
table.remove(visibleWindows,i) break end end
self.GuiElems.Minimize.ImageLabel.Image =
"rbxassetid://5448127505"
end
end
funcs.Add = function(self,obj,name)
if type(obj) == "table" and obj.Gui and obj.Gui:IsA("GuiObject")
then
obj.Gui.Parent = self.ContentPane
else
obj.Parent = self.ContentPane
end
if name then self.Elements[name] = obj end
end
funcs.GetElement = function(self,obj,name)
return self.Elements[name]
end
funcs.AlignTo = function(self,side,pos,size,silent)
if table.find(side.Windows,self) or self.Closed then return end
size = size or self.SizeY
if size > 0 and size <= 1 then
local totalSideHeight = 0
for i,v in pairs(side.Windows) do totalSideHeight =
totalSideHeight + v.SizeY end
self.SizeY = (totalSideHeight > 0 and totalSideHeight *
size * 2) or size
else
self.SizeY = (size > 0 and size or 100)
end
self:SetAligned(true)
self.Side = side
self.SizeX = side.Width
self.Gui.DisplayOrder = sideDisplayOrder + 1
for i,v in pairs(side.Windows) do v.Gui.DisplayOrder =
sideDisplayOrder end
pos = math.min(#side.Windows+1, pos or 1)
self.SidePos = pos
table.insert(side.Windows, pos, self)
funcs.Close = function(self)
self.Closed = true
self:SetResizableInternal(false)
Lib.FindAndRemove(leftSide.Windows,self)
Lib.FindAndRemove(rightSide.Windows,self)
Lib.FindAndRemove(visibleWindows,self)
self.MinimizeAnim.Disable()
self.CloseAnim.Disable()
self.ClosedSide = self.Side
self.Side = nil
self.OnDeactivate:Fire()
self:DoTween(self.GuiElems.Main,ti,{Size =
UDim2.new(0,self.SizeX,0,20)})
self:DoTween(self.GuiElems.Title,ti,{TextTransparency = 1})
self:DoTween(self.GuiElems.Minimize.ImageLabel,ti,
{ImageTransparency = 1})
self:DoTween(self.GuiElems.Close.ImageLabel,ti,
{ImageTransparency = 1})
Lib.FastWait(0.2)
if closeTime ~= self.LastClose then return end
self:DoTween(self.GuiElems.TopBar,ti,
{BackgroundTransparency = 1})
self:DoTween(self.GuiElems.Outlines,ti,{ImageTransparency =
1})
Lib.FastWait(0.2)
if closeTime ~= self.LastClose then return end
end
self.Aligned = false
self.Gui.Parent = nil
updateWindows(true)
end
funcs.Hide = funcs.Close
funcs.IsVisible = function(self)
return not self.Closed and ((self.Side and not self.Side.Hidden)
or not self.Side)
end
funcs.IsContentVisible = function(self)
return self:IsVisible() and not self.Minimized
end
funcs.Focus = function(self)
moveToTop(self)
end
funcs.MoveInBoundary = function(self)
local posX,posY = self.PosX,self.PosY
local maxX,maxY = sidesGui.AbsoluteSize.X,sidesGui.AbsoluteSize.Y
posX = math.min(posX,maxX-self.SizeX)
posY = math.min(posY,maxY-20)
self.GuiElems.Main.Position = UDim2.new(0,posX,0,posY)
end
funcs.DoTween = function(self,...)
local tween = service.TweenService:Create(...)
self.Tweens[#self.Tweens+1] = tween
tween:Play()
end
funcs.StopTweens = function(self)
for i,v in pairs(self.Tweens) do
v:Cancel()
end
self.Tweens = {}
end
funcs.Show = function(self,data)
return static.ShowWindow(self,data)
end
funcs.ShowAndFocus = function(self,data)
static.ShowWindow(self,data)
service.RunService.RenderStepped:wait()
self:Focus()
end
static.ShowWindow = function(window,data)
data = data or {}
local align = data.Align
local pos = data.Pos
local size = data.Size
local targetSide = (align == "left" and leftSide) or (align ==
"right" and rightSide)
window.Closed = false
window.LastClose = tick()
window.GuiElems.Title.TextTransparency = 0
window.GuiElems.Minimize.ImageLabel.ImageTransparency = 0
window.GuiElems.Close.ImageLabel.ImageTransparency = 0
window.GuiElems.TopBar.BackgroundTransparency = 0
window.GuiElems.Outlines.ImageTransparency = 0
window.GuiElems.Minimize.ImageLabel.Image =
"rbxassetid://5034768003"
window.GuiElems.Main.Active = true
window.GuiElems.Main.Outlines.Visible = true
window:SetMinimized(false,3)
window:SetResizableInternal(true)
window.MinimizeAnim.Enable()
window.CloseAnim.Enable()
if align then
window:AlignTo(targetSide,pos,size,data.Silent)
else
if align == nil and window.ClosedSide then -- Regular open
window:AlignTo(window.ClosedSide,window.SidePos,size,true)
static.SetSideVisible(window.ClosedSide,true)
else
if table.find(visibleWindows,window) then return end
window.ClosedSide = nil
window.OnActivate:Fire()
end
static.ToggleSide = function(name)
local side = (name == "left" and leftSide or rightSide)
side.Hidden = not side.Hidden
for i,v in pairs(side.Windows) do
if side.Hidden then
v.OnDeactivate:Fire()
else
v.OnActivate:Fire()
end
end
updateWindows()
end
static.SetSideVisible = function(s,vis)
local side = (type(s) == "table" and s) or (s == "left" and
leftSide or rightSide)
side.Hidden = not vis
for i,v in pairs(side.Windows) do
if side.Hidden then
v.OnDeactivate:Fire()
else
v.OnActivate:Fire()
end
end
updateWindows()
end
static.Init = function()
displayOrderStart = Main.DisplayOrders.Window
sideDisplayOrder = Main.DisplayOrders.SideWindow
sidesGui = Instance.new("ScreenGui")
local leftFrame = create({
{1,"Frame",
{Active=true,Name="LeftSide",BackgroundColor3=Color3.new(0.17647059261799,0.1764705
9261799,0.17647059261799),BorderSizePixel=0,}},
{2,"TextButton",
{AutoButtonColor=false,BackgroundColor3=Color3.new(0.2549019753933,0.2549019753933,
0.2549019753933),BorderSizePixel=0,Font=3,Name="Resizer",Parent={1},Size=UDim2.new(
0,5,1,0),Text="",TextColor3=Color3.new(0,0,0),TextSize=14,}},
{3,"Frame",
{BackgroundColor3=Color3.new(0.14117647707462,0.14117647707462,0.14117647707462),Bo
rderSizePixel=0,Name="Line",Parent={2},Position=UDim2.new(0,0,0,0),Size=UDim2.new(0
,1,1,0),}},
{4,"TextButton",
{AutoButtonColor=false,BackgroundColor3=Color3.new(0.2549019753933,0.2549019753933,
0.2549019753933),BorderSizePixel=0,Font=3,Name="WindowResizer",Parent={1},Position=
UDim2.new(1,-
300,0,0),Size=UDim2.new(1,0,0,4),Text="",TextColor3=Color3.new(0,0,0),TextSize=14,}
},
{5,"Frame",
{BackgroundColor3=Color3.new(0.14117647707462,0.14117647707462,0.14117647707462),Bo
rderSizePixel=0,Name="Line",Parent={4},Size=UDim2.new(1,0,0,1),}},
})
leftSide.Frame = leftFrame
leftFrame.Position = UDim2.new(0,-leftSide.Width-10,0,0)
leftSide.WindowResizer = leftFrame.WindowResizer
leftFrame.WindowResizer.Parent = nil
leftFrame.Parent = sidesGui
sideResizerHook(leftFrame.Resizer,"H",leftSide)
sideResizerHook(rightFrame.Resizer,"H",rightSide)
alignIndicator = Instance.new("ScreenGui")
alignIndicator.DisplayOrder = Main.DisplayOrders.Core
local indicator = Instance.new("Frame",alignIndicator)
indicator.BackgroundColor3 = Color3.fromRGB(0, 170, 255)
indicator.BorderSizePixel = 0
indicator.BackgroundTransparency = 0.8
indicator.Name = "Indicator"
local corner = Instance.new("UICorner",indicator)
corner.CornerRadius = UDim.new(0,10)
rightToggle.MouseButton1Click:Connect(function()
static.ToggleSide("right")
end)
leftToggle.Parent = sidesGui
rightToggle.Parent = sidesGui
sidesGui:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
local maxWidth = math.max(300,sidesGui.AbsoluteSize.X-
static.FreeWidth)
leftSide.Width =
math.max(static.MinWidth,math.min(leftSide.Width,maxWidth-rightSide.Width))
rightSide.Width =
math.max(static.MinWidth,math.min(rightSide.Width,maxWidth-leftSide.Width))
for i = 1,#visibleWindows do
visibleWindows[i]:MoveInBoundary()
end
updateWindows(true)
end)
sidesGui.DisplayOrder = sideDisplayOrder - 1
Lib.ShowGui(sidesGui)
updateSideFrames()
end
Lib.ContextMenu = (function()
local funcs = {}
local mouse
self.GuiElems.SearchBar:GetPropertyChangedSignal("Text"):Connect(function()
local lower,find = string.lower,string.find
local searchText = lower(self.GuiElems.SearchBar.Text)
local items = self.Items
local map = self.ItemToEntryMap
local toSize =
self.GuiElems.List.UIListLayout.AbsoluteContentSize.Y + 6
self.GuiElems.List.CanvasSize = UDim2.new(0,0,0,toSize-6)
end)
return contextGui
end
funcs.Add = function(self,item)
local newItem = {
Name = item.Name or "Item",
Icon = item.Icon or "",
Shortcut = item.Shortcut or "",
OnClick = item.OnClick,
OnHover = item.OnHover,
Disabled = item.Disabled or false,
DisabledIcon = item.DisabledIcon or "",
IconMap = item.IconMap,
OnRightClick = item.OnRightClick
}
if self.QueuedDivider then
local text = self.QueuedDividerText and
#self.QueuedDividerText > 0 and self.QueuedDividerText
self:AddDivider(text)
end
self.Items[#self.Items+1] = newItem
self.Updated = nil
end
funcs.AddRegistered = function(self,name,disabled)
if not self.Registered[name] then error(name.." is not
registered") end
if self.QueuedDivider then
local text = self.QueuedDividerText and
#self.QueuedDividerText > 0 and self.QueuedDividerText
self:AddDivider(text)
end
self.Registered[name].Disabled = disabled
self.Items[#self.Items+1] = self.Registered[name]
self.Updated = nil
end
funcs.Register = function(self,name,item)
self.Registered[name] = {
Name = item.Name or "Item",
Icon = item.Icon or "",
Shortcut = item.Shortcut or "",
OnClick = item.OnClick,
OnHover = item.OnHover,
DisabledIcon = item.DisabledIcon or "",
IconMap = item.IconMap,
OnRightClick = item.OnRightClick
}
end
funcs.UnRegister = function(self,name)
self.Registered[name] = nil
end
funcs.AddDivider = function(self,text)
self.QueuedDivider = false
local textWidth = text and
service.TextService:GetTextSize(text,14,Enum.Font.SourceSans,Vector2.new(999999999,
20)).X or nil
table.insert(self.Items,{Divider = true, Text = text, TextSize =
textWidth and textWidth+4})
self.Updated = nil
end
funcs.QueueDivider = function(self,text)
self.QueuedDivider = true
self.QueuedDividerText = text or ""
end
funcs.Clear = function(self)
self.Items = {}
self.Updated = nil
end
funcs.Refresh = function(self)
for i,v in pairs(self.GuiElems.List:GetChildren()) do
if not v:IsA("UIListLayout") then
v:Destroy()
end
end
local map = {}
self.ItemToEntryMap = map
for i = 1,#items do
local item = items[i]
if item.Divider then
local newDivider = dividerFrame:Clone()
newDivider.Line.BackgroundColor3 =
self.Theme.DividerColor
if item.Text then
newDivider.Size = UDim2.new(1,0,0,20)
newDivider.Line.Position =
UDim2.new(0,item.TextSize,0.5,0)
newDivider.Line.Size = UDim2.new(1,-
item.TextSize,0,1)
newDivider.DividerName.TextColor3 =
self.Theme.TextColor
newDivider.DividerName.Text = item.Text
newDivider.DividerName.Visible = true
end
newDivider.Visible = true
map[item] = newDivider
newDivider.Parent = contextList
else
local newEntry = entryFrame:Clone()
newEntry.BackgroundColor3 = self.Theme.HighlightColor
newEntry.EntryName.TextColor3 = self.Theme.TextColor
newEntry.EntryName.Text = item.Name
newEntry.Shortcut.Text = item.Shortcut
if item.Disabled then
newEntry.EntryName.TextColor3 =
Color3.new(150/255,150/255,150/255)
newEntry.Shortcut.TextColor3 =
Color3.new(150/255,150/255,150/255)
end
if self.Iconless then
newEntry.EntryName.Position =
UDim2.new(0,2,0,0)
newEntry.EntryName.Size = UDim2.new(1,-4,0,20)
newEntry.Icon.Visible = false
else
local iconIndex = item.Disabled and
item.DisabledIcon or item.Icon
if item.IconMap then
if type(iconIndex) == "number" then
item.IconMap:Display(newEntry.Icon,iconIndex)
elseif type(iconIndex) == "string" then
item.IconMap:DisplayByKey(newEntry.Icon,iconIndex)
end
elseif type(iconIndex) == "string" then
newEntry.Icon.Image = iconIndex
end
end
newEntry.MouseButton1Click:Connect(function()
item.OnClick(item.Name)
if not item.NoHide then
self:Hide()
end
end)
end
if item.OnRightClick then
newEntry.MouseButton2Click:Connect(function()
item.OnRightClick(item.Name)
if not item.NoHide then
self:Hide()
end
end)
end
end
newEntry.InputBegan:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
newEntry.BackgroundTransparency = 0
end
end)
newEntry.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
newEntry.BackgroundTransparency = 1
end
end)
newEntry.Visible = true
map[item] = newEntry
newEntry.Parent = contextList
end
end
self.Updated = true
end
funcs.Show = function(self,x,y)
-- Initialize Gui
local elems = self.GuiElems
elems.SearchFrame.Visible = self.SearchEnabled
elems.List.Position = UDim2.new(0,2,0,2 + (self.SearchEnabled and
24 or 0))
elems.List.Size = UDim2.new(1,-4,1,-4 - (self.SearchEnabled and
24 or 0))
if self.SearchEnabled and self.ClearSearchOnShow then
elems.SearchBar.Text = "" end
self.GuiElems.List.CanvasPosition = Vector2.new(0,0)
-- Vars
local reverseY = false
local x,y = x or mouse.X, y or mouse.Y
local maxX,maxY = mouse.ViewSizeX,mouse.ViewSizeY
-- Size adjustment
local toSize = elems.List.UIListLayout.AbsoluteContentSize.Y + 6
-- Padding
if self.MaxHeight and toSize > self.MaxHeight then
elems.List.CanvasSize = UDim2.new(0,0,0,toSize-6)
toSize = self.MaxHeight
else
elems.List.CanvasSize = UDim2.new(0,0,0,0)
end
if y + toSize > maxY then reverseY = true end
-- Close event
local closable
if self.CloseEvent then self.CloseEvent:Disconnect() end
self.CloseEvent =
service.UserInputService.InputBegan:Connect(function(input)
if not closable or input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
-- Resize
if reverseY then
elems.Main.Position = UDim2.new(0,x,0,y-
(self.ReverseYOffset or 0))
local newY = y - toSize - (self.ReverseYOffset or 0)
y = newY >= 0 and newY or 0
elems.Main:TweenSizeAndPosition(UDim2.new(0,self.Width,0,toSize),UDim2.new(0,x,0,y)
,Enum.EasingDirection.Out,Enum.EasingStyle.Quart,0.2,true)
else
elems.Main:TweenSize(UDim2.new(0,self.Width,0,toSize),Enum.EasingDirection.Out,Enum
.EasingStyle.Quart,0.2,true)
end
-- Close debounce
Lib.FastWait()
if self.SearchEnabled and self.FocusSearchOnShow then
elems.SearchBar:CaptureFocus() end
closable = true
end
funcs.Hide = function(self)
self.Gui.Parent = nil
end
funcs.ApplyTheme = function(self,data)
local theme = self.Theme
theme.ContentColor = data.ContentColor or Settings.Theme.Menu
theme.OutlineColor = data.OutlineColor or Settings.Theme.Menu
theme.DividerColor = data.DividerColor or Settings.Theme.Outline2
theme.TextColor = data.TextColor or Settings.Theme.Text
theme.HighlightColor = data.HighlightColor or
Settings.Theme.Main1
self.GuiElems.Main.BackgroundColor3 = theme.OutlineColor
self.GuiElems.Main.Container.BackgroundColor3 =
theme.ContentColor
end
Lib.CodeFrame = (function()
local funcs = {}
local typeMap = {
[1] = "String",
[2] = "String",
[3] = "String",
[4] = "Comment",
[5] = "Operator",
[6] = "Number",
[7] = "Keyword",
[8] = "BuiltIn",
[9] = "LocalMethod",
[10] = "LocalProperty",
[11] = "Nil",
[12] = "Bool",
[13] = "Function",
[14] = "Local",
[15] = "Self",
[16] = "FunctionName",
[17] = "Bracket"
}
local specialKeywordsTypes = {
["nil"] = 11,
["true"] = 12,
["false"] = 12,
["function"] = 13,
["local"] = 14,
["self"] = 15
}
local keywords = {
["and"] = true,
["break"] = true,
["do"] = true,
["else"] = true,
["elseif"] = true,
["end"] = true,
["false"] = true,
["for"] = true,
["function"] = true,
["if"] = true,
["in"] = true,
["local"] = true,
["nil"] = true,
["not"] = true,
["or"] = true,
["repeat"] = true,
["return"] = true,
["then"] = true,
["true"] = true,
["until"] = true,
["while"] = true,
["plugin"] = true
}
local builtIns = {
["delay"] = true,
["elapsedTime"] = true,
["require"] = true,
["spawn"] = true,
["tick"] = true,
["time"] = true,
["typeof"] = true,
["UserSettings"] = true,
["wait"] = true,
["warn"] = true,
["game"] = true,
["shared"] = true,
["script"] = true,
["workspace"] = true,
["assert"] = true,
["collectgarbage"] = true,
["error"] = true,
["getfenv"] = true,
["getmetatable"] = true,
["ipairs"] = true,
["loadstring"] = true,
["newproxy"] = true,
["next"] = true,
["pairs"] = true,
["pcall"] = true,
["print"] = true,
["rawequal"] = true,
["rawget"] = true,
["rawset"] = true,
["select"] = true,
["setfenv"] = true,
["setmetatable"] = true,
["tonumber"] = true,
["tostring"] = true,
["type"] = true,
["unpack"] = true,
["xpcall"] = true,
["_G"] = true,
["_VERSION"] = true,
["coroutine"] = true,
["debug"] = true,
["math"] = true,
["os"] = true,
["string"] = true,
["table"] = true,
["bit32"] = true,
["utf8"] = true,
["Axes"] = true,
["BrickColor"] = true,
["CFrame"] = true,
["Color3"] = true,
["ColorSequence"] = true,
["ColorSequenceKeypoint"] = true,
["DockWidgetPluginGuiInfo"] = true,
["Enum"] = true,
["Faces"] = true,
["Instance"] = true,
["NumberRange"] = true,
["NumberSequence"] = true,
["NumberSequenceKeypoint"] = true,
["PathWaypoint"] = true,
["PhysicalProperties"] = true,
["Random"] = true,
["Ray"] = true,
["Rect"] = true,
["Region3"] = true,
["Region3int16"] = true,
["TweenInfo"] = true,
["UDim"] = true,
["UDim2"] = true,
["Vector2"] = true,
["Vector2int16"] = true,
["Vector3"] = true,
["Vector3int16"] = true
}
local richReplace = {
["'"] = "'",
["\""] = """,
["<"] = "<",
[">"] = ">",
["&"] = "&"
}
local tabSub = "\205"
local tabReplacement = (" %s%s "):format(tabSub,tabSub)
local tabJumps = {
[("[^%s] %s"):format(tabSub,tabSub)] = 0,
[(" %s%s"):format(tabSub,tabSub)] = -1,
[("%s%s "):format(tabSub,tabSub)] = 2,
[("%s [^%s]"):format(tabSub,tabSub)] = 1,
}
local enumEntries = {}
local enums = Enum:GetEnums()
for i = 1,#enums do
enumEntries[tostring(enums[i])] = true
end
builtIns["Enum"] = enumEntries
builtInInited = true
end
editBox.Focused:Connect(function()
obj:ConnectEditBoxEvent()
obj.Editing = true
end)
editBox.FocusLost:Connect(function()
obj:DisconnectEditBoxEvent()
obj.Editing = false
end)
editBox:GetPropertyChangedSignal("Text"):Connect(function()
local text = editBox.Text
if #text == 0 or obj.EditBoxCopying then return end
editBox.Text = ""
obj:AppendText(text)
end)
end
local function setupMouseSelection(obj)
local mouse = plr:GetMouse()
local codeFrame = obj.GuiElems.LinesFrame
local lines = obj.Lines
codeFrame.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
then
local fontSizeX,fontSizeY =
math.ceil(obj.FontSize/2),obj.FontSize
obj.SelectionRange = {{-1,-1},{-1,-1}}
obj:MoveCursor(selX,selY)
obj.FloatCursorX = selX
sel2Y = math.min(#lines-1,sel2Y)
local relativeLine = lines[sel2Y+1] or ""
sel2X = math.min(#relativeLine, sel2X +
obj:TabAdjust(sel2X,sel2Y))
obj:MoveCursor(sel2X,sel2Y)
obj.FloatCursorX = sel2X
obj:Refresh()
end
releaseEvent =
service.UserInputService.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
releaseEvent:Disconnect()
mouseEvent:Disconnect()
scrollEvent:Disconnect()
obj:SetCopyableSelection()
--updateSelection()
end
end)
mouseEvent =
service.UserInputService.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
local upDelta = mouse.Y -
codeFrame.AbsolutePosition.Y
local downDelta = mouse.Y -
codeFrame.AbsolutePosition.Y - codeFrame.AbsoluteSize.Y
local leftDelta = mouse.X -
codeFrame.AbsolutePosition.X
local rightDelta = mouse.X -
codeFrame.AbsolutePosition.X - codeFrame.AbsoluteSize.X
scrollPowerV = 0
scrollPowerH = 0
if downDelta > 0 then
scrollPowerV =
math.floor(downDelta*0.05) + 1
elseif upDelta < 0 then
scrollPowerV =
math.ceil(upDelta*0.05) - 1
end
if rightDelta > 0 then
scrollPowerH =
math.floor(rightDelta*0.05) + 1
elseif leftDelta < 0 then
scrollPowerH =
math.ceil(leftDelta*0.05) - 1
end
updateSelection()
end
end)
scrollEvent =
clonerefs(game:GetService("RunService")).RenderStepped:Connect(function()
if scrollPowerV ~= 0 or scrollPowerH ~= 0 then
obj:ScrollDelta(scrollPowerH,scrollPowerV)
updateSelection()
end
end)
obj:Refresh()
end
end)
end
lineTweens.Invis =
tweenService:Create(cursor,TweenInfo.new(0.4,Enum.EasingStyle.Quart,Enum.EasingDire
ction.Out),{BackgroundTransparency = 1})
lineTweens.Vis =
tweenService:Create(cursor,TweenInfo.new(0.2,Enum.EasingStyle.Quart,Enum.EasingDire
ction.Out),{BackgroundTransparency = 0})
elems.LinesFrame = linesFrame
elems.LineNumbersLabel = lineNumbersLabel
elems.Cursor = cursor
elems.EditBox = editBox
elems.ScrollCorner = create({{1,"Frame",
{BackgroundColor3=Color3.new(0.15686275064945,0.15686275064945,0.15686275064945),Bo
rderSizePixel=0,Name="ScrollCorner",Position=UDim2.new(1,-16,1,-
16),Size=UDim2.new(0,16,0,16),Visible=false,}}})
elems.ScrollCorner.Parent = frame
linesFrame.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
then
obj:SetEditing(true,input)
end
end)
obj.Frame = frame
obj.Gui = frame
obj.GuiElems = elems
setupEditBox(obj)
setupMouseSelection(obj)
return frame
end
funcs.GetSelectionText = function(self)
if not self:IsValidRange() then return "" end
if deltaLines == 0 then
return self:ConvertText(lines[selY+1]:sub(selX+1,sel2X),
false)
end
return self:ConvertText(result,false)
end
funcs.SetCopyableSelection = function(self)
local text = self:GetSelectionText()
local editBox = self.GuiElems.EditBox
self.EditBoxCopying = true
editBox.Text = text
editBox.SelectionStart = 1
editBox.CursorPosition = #editBox.Text + 1
self.EditBoxCopying = false
end
funcs.ConnectEditBoxEvent = function(self)
if self.EditBoxEvent then
self.EditBoxEvent:Disconnect()
end
self.EditBoxEvent =
service.UserInputService.InputBegan:Connect(function(input)
if input.UserInputType ~= Enum.UserInputType.Keyboard then
return end
startRange = startRange or
{self.CursorX,self.CursorY}
end
self:DeleteRange({startRange,endRange},false,true)
self:ResetSelection(true)
self:JumpToCursor()
end)
elseif keycode == keycodes.Delete then
setupMove(keycodes.Delete,function()
local startRange,endRange
if self:IsValidRange() then
startRange = self.SelectionRange[1]
endRange = self.SelectionRange[2]
else
startRange = {self.CursorX,self.CursorY}
end
endRange = endRange or
{endCursorX,endCursorY}
end
self:DeleteRange({startRange,endRange},false,true)
self:ResetSelection(true)
self:JumpToCursor()
end)
elseif
service.UserInputService:IsKeyDown(Enum.KeyCode.LeftControl) then
if keycode == keycodes.A then
self.SelectionRange = {{0,0},
{#self.Lines[#self.Lines],#self.Lines-1}}
self:SetCopyableSelection()
self:Refresh()
end
end
end)
end
funcs.DisconnectEditBoxEvent = function(self)
if self.EditBoxEvent then
self.EditBoxEvent:Disconnect()
end
end
funcs.ResetSelection = function(self,norefresh)
self.SelectionRange = {{-1,-1},{-1,-1}}
if not norefresh then self:Refresh() end
end
funcs.IsValidRange = function(self,range)
local selectionRange = range or self.SelectionRange
local selX,selY = selectionRange[1][1], selectionRange[1][2]
local sel2X,sel2Y = selectionRange[2][1], selectionRange[2][2]
return true
end
funcs.DeleteRange = function(self,range,noprocess,updatemouse)
range = range or self.SelectionRange
if not self:IsValidRange(range) then return end
funcs.AppendText = function(self,text)
self:DeleteRange(nil,true,true)
local lines,cursorX,cursorY =
self.Lines,self.CursorX,self.CursorY
local line = lines[cursorY+1]
local before = line:sub(1,cursorX)
local after = line:sub(cursorX+1)
text = text:gsub("\r\n","\n")
text = self:ConvertText(text,true) -- Tab Convert
for i = 1,#textLines do
local linePos = cursorY+i
if i > 1 then insert(lines,linePos,"") end
lines[linePos] = newBefore..textLine..newAfter
end
self:ProcessTextChange()
self.CursorX = cursorX + #textLines[#textLines]
self.CursorY = cursorY + #textLines-1
self:UpdateCursor()
end
funcs.ScrollDelta = function(self,x,y)
self.ScrollV:ScrollTo(self.ScrollV.Index + y)
self.ScrollH:ScrollTo(self.ScrollH.Index + x)
end
-- x and y starts at 0
funcs.TabAdjust = function(self,x,y)
local lines = self.Lines
local line = lines[y+1]
x=x+1
if line then
local left = line:sub(x-1,x-1)
local middle = line:sub(x,x)
local right = line:sub(x+1,x+1)
local selRange = (#left > 0 and left or " ") .. (#middle >
0 and middle or " ") .. (#right > 0 and right or " ")
for i,v in pairs(tabJumps) do
if selRange:find(i) then
return v
end
end
end
return 0
end
funcs.SetEditing = function(self,on,input)
self:UpdateCursor(input)
if on then
if self.Editable then
self.GuiElems.EditBox.Text = ""
self.GuiElems.EditBox:CaptureFocus()
end
else
self.GuiElems.EditBox:ReleaseFocus()
end
end
funcs.CursorAnim = function(self,on)
local cursor = self.GuiElems.Cursor
local animTime = tick()
self.LastAnimTime = animTime
lineTweens.Invis:Cancel()
lineTweens.Vis:Cancel()
cursor.BackgroundTransparency = 0
coroutine.wrap(function()
while self.Editable do
Lib.FastWait(0.5)
if self.LastAnimTime ~= animTime then return end
lineTweens.Invis:Play()
Lib.FastWait(0.4)
if self.LastAnimTime ~= animTime then return end
lineTweens.Vis:Play()
Lib.FastWait(0.2)
end
end)()
end
funcs.MoveCursor = function(self,x,y)
self.CursorX = x
self.CursorY = y
self:UpdateCursor()
self:JumpToCursor()
end
funcs.JumpToCursor = function(self)
self:Refresh()
end
funcs.UpdateCursor = function(self,input)
local linesFrame = self.GuiElems.LinesFrame
local cursor = self.GuiElems.Cursor
local hSize = math.max(0,linesFrame.AbsoluteSize.X)
local vSize = math.max(0,linesFrame.AbsoluteSize.Y)
local maxLines = math.ceil(vSize / self.FontSize)
local maxCols = math.ceil(hSize / math.ceil(self.FontSize/2))
local viewX,viewY = self.ViewX,self.ViewY
local totalLinesStr = tostring(#self.Lines)
local fontWidth = math.ceil(self.FontSize / 2)
local linesOffset = #totalLinesStr*fontWidth + 4*fontWidth
if input then
local linesFrame = self.GuiElems.LinesFrame
local frameX,frameY =
linesFrame.AbsolutePosition.X,linesFrame.AbsolutePosition.Y
local mouseX,mouseY = input.Position.X,input.Position.Y
local fontSizeX,fontSizeY =
math.ceil(self.FontSize/2),self.FontSize
-- Update modified
self.CursorX = cursorX
self.CursorY = cursorY
funcs.MapNewLines = function(self)
local newLines = {}
local count = 1
local text = self.Text
local find = string.find
local init = 1
self.NewLines = newLines
end
funcs.PreHighlight = function(self)
local start = tick()
local text = self.Text:gsub("\\\\"," ")
--print("BACKSLASH SUB",tick()-start)
local textLen = #text
local found = {}
local foundMap = {}
local extras = {}
local find = string.find
local sub = string.sub
self.ColoredLines = {}
count = count+1
init = y+1
x,y,extra = find(str,pattern,init,raw)
end
end
local start = tick()
findAll(text,'"',1,true)
findAll(text,"'",2,true)
findAll(text,"%[(=*)%[",3)
findAll(text,"--",4,true)
table.sort(found)
if ahead == 3 then
_,ending =
find(text,"]"..extras[pos+2].."]",pos+1,true)
if not ending then ending = textLen end
else
ending = find(text,"\n",pos+1,true) or textLen
end
end
lastEnding = ending
--if i < 200 then print(curLine) end
end
self.PreHighlights = foundHighlights
--print(tick()-start)
--print(#found,curLine)
end
funcs.HighlightLine = function(self,line)
local cached = self.ColoredLines[line]
if cached then return cached end
local preHighlightMap = {}
for pos,data in next,preHighlights do
local relativePos = pos-lineStart
if relativePos < 1 then
currentType = data[1]
lastEnding = data[2] - lineStart
--warn(pos,data[2])
else
preHighlightMap[relativePos] = {data[1],data[2]-
lineStart}
end
end
lastEnding = col+#word-1
if wordType ~= 7 then
if wordBeginsDotted then
local prevBuiltIn = lastWord and
builtIns[lastWord]
wordType = (prevBuiltIn and
type(prevBuiltIn) == "table" and prevBuiltIn[word] and 8) or 10
end
if wordType ~= 8 then
local x,y,br = find(lineText,"^
%s*([%({\"'])",lastEnding+1)
if x then
wordType = (funcStatus > 0
and br == "(" and 16) or 9
funcStatus = 0
end
end
else
wordType = specialKeywordsTypes[word] or
wordType
funcStatus = (word == "function" and 1 or
0)
end
lastWord = word
wordBeginsDotted = false
if funcStatus > 0 then funcStatus = 1 end
if wordType then
currentType = wordType
highlights[col] = currentType
else
currentType = nil
end
elseif find(char,"%p") then
local isDot = (char == ".")
local isNum = isDot and
find(sub(lineText,col+1,col+1),"%d")
highlights[col] = (isNum and 6 or 5)
self.ColoredLines[line] = highlights
return highlights
end
funcs.Refresh = function(self)
local start = tick()
lineFrame.Parent = linesFrame
self.LineFrames[row] = lineFrame
end
-- Selection Highlight
local selectionRange = self.SelectionRange
local selPos1 = selectionRange[1]
local selPos2 = selectionRange[2]
local selRow,selColumn = selPos1[2],selPos1[1]
local sel2Row,sel2Column = selPos2[2],selPos2[1]
local selRelaX,selRelaY = viewX,relaY-1
lineFrame.SelectionHighlight.Position =
UDim2.new(0,posX*fontSizeX,0,0)
lineFrame.SelectionHighlight.Size =
UDim2.new(0,sizeX*fontSizeX,1,0)
lineFrame.SelectionHighlight.Visible = true
else
lineFrame.SelectionHighlight.Visible = false
end
-- Selection Text Color for first char
local inSelection = selRelaY >= selRow and selRelaY <=
sel2Row and (selRelaY == selRow and viewX >= selColumn or selRelaY ~= selRow) and
(selRelaY == sel2Row and viewX < sel2Column or selRelaY ~= sel2Row)
if inSelection then
curType = -999
curTemplate = selectionTemplate
end
local lastText =
gsub(sub(lineText,colStart,viewX+maxCols),"['\"<>&]",richReplace)
--warn("SUB",colStart,viewX+maxCols-1)
if #lastText > 0 then
resText = resText .. (curTemplate ~= textTemplate and
(curTemplate .. lastText .. "</font>") or lastText)
end
if self.Lines[relaY] then
lineNumberStr = lineNumberStr .. (relaY ==
self.CursorY and ("<b>"..relaY.."</b>\n") or relaY .. "\n")
end
lineFrame.Label.Text = resText
end
for i = maxLines+1,#self.LineFrames do
self.LineFrames[i]:Destroy()
self.LineFrames[i] = nil
end
self.Frame.LineNumbers.Text = lineNumberStr
self:UpdateCursor()
--print("REFRESH TIME",tick()-start)
end
funcs.UpdateView = function(self)
local totalLinesStr = tostring(#self.Lines)
local fontWidth = math.ceil(self.FontSize / 2)
local linesOffset = #totalLinesStr*fontWidth + 4*fontWidth
scrollV.VisibleSpace = maxLines
scrollV.TotalSpace = #self.Lines + 1
scrollH.VisibleSpace = math.ceil(hSize/fontWidth)
scrollH.TotalSpace = self.MaxTextCols + 1
self.ViewY = scrollV.Index
self.ViewX = scrollH.Index
self.Frame.Lines.Position = UDim2.new(0,linesOffset,0,0)
self.Frame.Lines.Size = UDim2.new(1,-
linesOffset+oldOffsets.X,1,oldOffsets.Y)
self.Frame.LineNumbers.Position =
UDim2.new(0,fontWidth,0,0)
self.Frame.LineNumbers.Size =
UDim2.new(0,#totalLinesStr*fontWidth,1,oldOffsets.Y)
self.Frame.LineNumbers.TextSize = self.FontSize
end
end
funcs.ProcessTextChange = function(self)
local maxCols = 0
local lines = self.Lines
for i = 1,#lines do
local lineLen = #lines[i]
if lineLen > maxCols then
maxCols = lineLen
end
end
self.MaxTextCols = maxCols
self:UpdateView()
self.Text = table.concat(self.Lines,"\n")
self:MapNewLines()
self:PreHighlight()
self:Refresh()
--self.TextChanged:Fire()
end
funcs.ConvertText = function(self,text,toEditor)
if toEditor then
return text:gsub("\t",(" %s%s "):format(tabSub,tabSub))
else
return text:gsub((" %s%s "):format(tabSub,tabSub),"\t")
end
end
funcs.SetText = function(self,txt)
txt = self:ConvertText(txt,true) -- Tab Convert
local lines = self.Lines
table.clear(lines)
local count = 1
self:ProcessTextChange()
end
funcs.MakeRichTemplates = function(self)
local floor = math.floor
local templates = {}
self.RichTemplates = templates
end
funcs.ApplyTheme = function(self)
local colors = Settings.Theme.Syntax
self.Colors = colors
self.Frame.LineNumbers.TextColor3 = colors.Text
self.Frame.BackgroundColor3 = colors.Background
end
scrollV.WheelIncrement = 3
scrollH.Increment = 2
scrollH.WheelIncrement = 7
scrollV.Scrolled:Connect(function()
obj.ViewY = scrollV.Index
obj:Refresh()
end)
scrollH.Scrolled:Connect(function()
obj.ViewX = scrollH.Index
obj:Refresh()
end)
makeFrame(obj)
obj:MakeRichTemplates()
obj:ApplyTheme()
scrollV:SetScrollFrame(obj.Frame.Lines)
scrollV.Gui.Parent = obj.Frame
scrollH.Gui.Parent = obj.Frame
obj:UpdateView()
obj.Frame:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
obj:UpdateView()
obj:Refresh()
end)
return obj
end
Lib.Checkbox = (function()
local funcs = {}
local c3 = Color3.fromRGB
local v2 = Vector2.new
local ud2s = UDim2.fromScale
local ud2o = UDim2.fromOffset
local ud = UDim.new
local max = math.max
local new = Instance.new
local TweenSize = new("Frame").TweenSize
local ti = TweenInfo.new
local delay = delay
service.Debris:AddItem(circle, 0.4)
end
-- walls
local top, bottom, left, right = filler.top, filler.bottom,
filler.left, filler.right
self.Gui = checkbox
self.GuiElems = {
Top = top,
Bottom = bottom,
Left = left,
Right = right,
Outline = outline,
Filler = filler,
Checkmark = checkmark,
Checkmark2 = filler.checkmark2,
Middle = filler.middle
}
checkbox.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then
local release
release =
service.UserInputService.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
release:Disconnect()
if Lib.CheckMouseInGui(checkbox) then
if self.Style == 0 then
ripple(ripples_container,
self.Disabled and self.Colors.Disabled or self.Colors.Primary)
end
self.OnInput:Fire()
end
end
end)
end
end)
self:Paint()
end
funcs.Collapse = function(self,anim)
local guiElems = self.GuiElems
if anim then
TweenSize(guiElems.Top, ud2o(14, 14), "In", "Quart", 4/15,
true)
TweenSize(guiElems.Bottom, ud2o(14, 14), "In", "Quart",
4/15, true)
TweenSize(guiElems.Left, ud2o(14, 14), "In", "Quart", 4/15,
true)
TweenSize(guiElems.Right, ud2o(14, 14), "In", "Quart",
4/15, true)
else
guiElems.Top.Size = ud2o(14, 14)
guiElems.Bottom.Size = ud2o(14, 14)
guiElems.Left.Size = ud2o(14, 14)
guiElems.Right.Size = ud2o(14, 14)
end
end
funcs.Expand = function(self,anim)
local guiElems = self.GuiElems
if anim then
TweenSize(guiElems.Top, ud2o(14, 0), "InOut", "Quart",
4/15, true)
TweenSize(guiElems.Bottom, ud2o(14, 0), "InOut", "Quart",
4/15, true)
TweenSize(guiElems.Left, ud2o(0, 14), "InOut", "Quart",
4/15, true)
TweenSize(guiElems.Right, ud2o(0, 14), "InOut", "Quart",
4/15, true)
else
guiElems.Top.Size = ud2o(14, 0)
guiElems.Bottom.Size = ud2o(14, 0)
guiElems.Left.Size = ud2o(0, 14)
guiElems.Right.Size = ud2o(0, 14)
end
end
funcs.Paint = function(self)
local guiElems = self.GuiElems
if self.Style == 0 then
local color_base = self.Disabled and self.Colors.Disabled
guiElems.Outline.BackgroundColor3 = color_base or
(self.Toggled and self.Colors.Primary) or self.Colors.Secondary
local walls_color = color_base or self.Colors.Primary
guiElems.Top.BackgroundColor3 = walls_color
guiElems.Bottom.BackgroundColor3 = walls_color
guiElems.Left.BackgroundColor3 = walls_color
guiElems.Right.BackgroundColor3 = walls_color
else
guiElems.Outline.BackgroundColor3 = self.Disabled and
self.Colors.Disabled or self.Colors.Secondary
guiElems.Filler.BackgroundColor3 = self.Disabled and
self.Colors.DisabledBackground or self.Colors.Background
guiElems.Checkmark2.ImageColor3 = self.Disabled and
self.Colors.DisabledCheck or self.Colors.Primary
end
end
funcs.SetState = function(self,val,anim)
self.Toggled = val
if self.Toggled then
if self.Style == 0 then
if anim then
self.OutlineColorTween =
service.TweenService:Create(self.GuiElems.Outline, ti(4/15,
Enum.EasingStyle.Circular, Enum.EasingDirection.Out), {BackgroundColor3 =
self.Colors.Primary})
self.OutlineColorTween:Play()
delay(0.15, function()
if setStateTime ~= self.LastSetStateTime
then return end
self:Paint()
TweenSize(self.GuiElems.Checkmark,
ud2o(14, 20), "Out", "Bounce", 2/15, true)
end)
else
self.GuiElems.Outline.BackgroundColor3 =
self.Colors.Primary
self:Paint()
self.GuiElems.Checkmark.Size = ud2o(14, 20)
end
self:Collapse(anim)
else
self:Paint()
self.GuiElems.Checkmark2.Visible = true
self.GuiElems.Middle.Visible = false
end
else
if self.Style == 0 then
if anim then
self.OutlineColorTween =
service.TweenService:Create(self.GuiElems.Outline, ti(4/15,
Enum.EasingStyle.Circular, Enum.EasingDirection.In), {BackgroundColor3 =
self.Colors.Secondary})
self.OutlineColorTween:Play()
delay(0.15, function()
if setStateTime ~= self.LastSetStateTime
then return end
self:Paint()
TweenSize(self.GuiElems.Checkmark,
ud2o(0, 20), "Out", "Quad", 1/15, true)
end)
else
self.GuiElems.Outline.BackgroundColor3 =
self.Colors.Secondary
self:Paint()
self.GuiElems.Checkmark.Size = ud2o(0, 20)
end
self:Expand(anim)
else
self:Paint()
self.GuiElems.Checkmark2.Visible = false
self.GuiElems.Middle.Visible = self.Toggled == nil
end
end
end
Lib.BrickColorPicker = (function()
local funcs = {}
local paletteCount = 0
local mouse = service.Players.LocalPlayer:GetMouse()
local hexStartX = 4
local hexSizeX = 27
local hexTriangleStart = 1
local hexTriangleSize = 8
local bottomColors = {
Color3.fromRGB(17,17,17),
Color3.fromRGB(99,95,98),
Color3.fromRGB(163,162,165),
Color3.fromRGB(205,205,205),
Color3.fromRGB(223,223,222),
Color3.fromRGB(237,234,234),
Color3.fromRGB(27,42,53),
Color3.fromRGB(91,93,105),
Color3.fromRGB(159,161,172),
Color3.fromRGB(202,203,209),
Color3.fromRGB(231,231,236),
Color3.fromRGB(248,248,248)
}
return false
end
hex.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
and isMouseInHexagon(hex) then
self.OnPreview:Fire(color)
end
end)
end
colorFrame.MoreColors.MouseButton1Click:Connect(function()
self.OnMoreColors:Fire()
self:Close()
end)
self.Gui = gui
end
funcs.SetMoreColorsVisible = function(self,vis)
local colorFrame = self.Gui.Frame
colorFrame.Size = UDim2.new(0,337,0,380 - (not vis and 33 or 0))
colorFrame.MoreColors.Visible = vis
end
funcs.Show = function(self,x,y,prevColor)
self.PrevColor = prevColor or self.PrevColor
self.Gui.Frame.Position = UDim2.new(0,x,0,y)
Lib.FastWait()
closable = true
end
funcs.Close = function(self)
self.Gui.Parent = nil
self.OnCancel:Fire()
end
newMt.OnSelect = Lib.Signal.new()
newMt.OnCancel = Lib.Signal.new()
newMt.OnPreview = Lib.Signal.new()
local basicColors =
{Color3.new(0,0,0),Color3.new(0.66666668653488,0,0),Color3.new(0,0.33333334326744,0
),Color3.new(0.66666668653488,0.33333334326744,0),Color3.new(0,0.66666668653488,0),
Color3.new(0.66666668653488,0.66666668653488,0),Color3.new(0,1,0),Color3.new(0.6666
6668653488,1,0),Color3.new(0,0,0.49803924560547),Color3.new(0.66666668653488,0,0.49
803924560547),Color3.new(0,0.33333334326744,0.49803924560547),Color3.new(0.66666668
653488,0.33333334326744,0.49803924560547),Color3.new(0,0.66666668653488,0.498039245
60547),Color3.new(0.66666668653488,0.66666668653488,0.49803924560547),Color3.new(0,
1,0.49803924560547),Color3.new(0.66666668653488,1,0.49803924560547),Color3.new(0,0,
1),Color3.new(0.66666668653488,0,1),Color3.new(0,0.33333334326744,1),Color3.new(0.6
6666668653488,0.33333334326744,1),Color3.new(0,0.66666668653488,1),Color3.new(0.666
66668653488,0.66666668653488,1),Color3.new(0,1,1),Color3.new(0.66666668653488,1,1),
Color3.new(0.33333334326744,0,0),Color3.new(1,0,0),Color3.new(0.33333334326744,0.33
333334326744,0),Color3.new(1,0.33333334326744,0),Color3.new(0.33333334326744,0.6666
6668653488,0),Color3.new(1,0.66666668653488,0),Color3.new(0.33333334326744,1,0),Col
or3.new(1,1,0),Color3.new(0.33333334326744,0,0.49803924560547),Color3.new(1,0,0.498
03924560547),Color3.new(0.33333334326744,0.33333334326744,0.49803924560547),Color3.
new(1,0.33333334326744,0.49803924560547),Color3.new(0.33333334326744,0.666666686534
88,0.49803924560547),Color3.new(1,0.66666668653488,0.49803924560547),Color3.new(0.3
3333334326744,1,0.49803924560547),Color3.new(1,1,0.49803924560547),Color3.new(0.333
33334326744,0,1),Color3.new(1,0,1),Color3.new(0.33333334326744,0.33333334326744,1),
Color3.new(1,0.33333334326744,1),Color3.new(0.33333334326744,0.66666668653488,1),Co
lor3.new(1,0.66666668653488,1),Color3.new(0.33333334326744,1,1),Color3.new(1,1,1)}
local customColors = {}
chosenColor = Color3.new(red,green,blue)
colorScope.Position = UDim2.new(0,relativeX-9,0,relativeY-
9)
colorStrip.ImageColor3 = Color3.fromHSV(hue,sat,1)
colorArrow.Position = UDim2.new(0,-2,0,relativeStripY-4)
previewFrame.BackgroundColor3 = chosenColor
newMt.Color = chosenColor
newMt.OnPreview:Fire(chosenColor)
end
updateColor()
end
local function colorStripInput()
local relativeY = mouse.Y - colorStrip.AbsolutePosition.Y
updateColor()
end
releaseEvent =
user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
releaseEvent:Disconnect()
pressing = false
end)
startNum = startNum + 1
func(startNum)
while pressing do
if tick()-startTime > 0.3 then
startNum = startNum + 1
func(startNum)
end
wait(0.1)
end
end
end)
frame.ArrowFrame.Up.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
frame.ArrowFrame.Up.BackgroundTransparency = 1
end
end)
frame.ArrowFrame.Down.InputBegan:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
frame.ArrowFrame.Down.BackgroundTransparency =
0.5
elseif input.UserInputType ==
Enum.UserInputType.MouseButton1 then
local releaseEvent,runEvent
releaseEvent =
user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
releaseEvent:Disconnect()
pressing = false
end)
startNum = startNum - 1
func(startNum)
while pressing do
if tick()-startTime > 0.3 then
startNum = startNum - 1
func(startNum)
end
wait(0.1)
end
end
end)
frame.ArrowFrame.Down.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
frame.ArrowFrame.Down.BackgroundTransparency =
1
end
end)
end
colorSpace.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
then
local releaseEvent,mouseEvent
releaseEvent =
user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
releaseEvent:Disconnect()
mouseEvent:Disconnect()
end)
mouseEvent =
user.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
colorSpaceInput()
end
end)
colorSpaceInput()
end
end)
colorStrip.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
then
local releaseEvent,mouseEvent
releaseEvent =
user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
releaseEvent:Disconnect()
mouseEvent:Disconnect()
end)
mouseEvent =
user.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
colorStripInput()
end
end)
colorStripInput()
end
end)
newColor.MouseButton1Click:Connect(function()
red,green,blue = v.r,v.g,v.b
local newColor = Color3.new(red,green,blue)
hue,sat,val = Color3.toHSV(newColor)
updateColor()
end)
newColor.Parent = basicColorsFrame
column = column + 1
if column == 6 then row = row + 1 column = 0 end
end
row = 0
column = 0
for i = 1,12 do
local color = customColors[i] or Color3.new(0,0,0)
local newColor = colorChoice:Clone()
newColor.BackgroundColor3 = color
newColor.Position = UDim2.new(0,1 + 30*column,0,20 +
23*row)
newColor.MouseButton1Click:Connect(function()
local curColor = customColors[i] or Color3.new(0,0,0)
red,green,blue = curColor.r,curColor.g,curColor.b
hue,sat,val = Color3.toHSV(curColor)
updateColor()
end)
newColor.MouseButton2Click:Connect(function()
customColors[i] = chosenColor
newColor.BackgroundColor3 = chosenColor
end)
newColor.Parent = customColorsFrame
column = column + 1
if column == 6 then row = row + 1 column = 0 end
end
okButton.MouseButton1Click:Connect(function()
newMt.OnSelect:Fire(chosenColor) window:Close() end)
okButton.InputBegan:Connect(function(input) if
input.UserInputType == Enum.UserInputType.MouseMovement then
okButton.BackgroundTransparency = 0.4 end end)
okButton.InputEnded:Connect(function(input) if
input.UserInputType == Enum.UserInputType.MouseMovement then
okButton.BackgroundTransparency = 0 end end)
cancelButton.MouseButton1Click:Connect(function()
newMt.OnCancel:Fire() window:Close() end)
cancelButton.InputBegan:Connect(function(input) if
input.UserInputType == Enum.UserInputType.MouseMovement then
cancelButton.BackgroundTransparency = 0.4 end end)
cancelButton.InputEnded:Connect(function(input) if
input.UserInputType == Enum.UserInputType.MouseMovement then
cancelButton.BackgroundTransparency = 0 end end)
updateColor()
newMt.SetColor = function(self,color)
red,green,blue = color.r,color.g,color.b
hue,sat,val = Color3.toHSV(color)
updateColor()
end
newMt.Show = function(self)
self.Window:Show()
end
return newMt
end
Lib.NumberSequenceEditor = (function()
local function new() -- TODO: Convert to newer class model
local newMt = setmetatable({},{})
newMt.OnSelect = Lib.Signal.new()
newMt.OnCancel = Lib.Signal.new()
newMt.OnPreview = Lib.Signal.new()
for i = 2,10 do
local newLine = Instance.new("Frame")
newLine.BackgroundTransparency = 0.5
newLine.BackgroundColor3 = Color3.new(96/255,96/255,96/255)
newLine.BorderSizePixel = 0
newLine.Size = UDim2.new(0,1,1,0)
newLine.Position = UDim2.new((i-1)/(11-1),0,0,0)
newLine.Parent = numberLineOutlines
end
for i = 2,4 do
local newLine = Instance.new("Frame")
newLine.BackgroundTransparency = 0.5
newLine.BackgroundColor3 = Color3.new(96/255,96/255,96/255)
newLine.BorderSizePixel = 0
newLine.Size = UDim2.new(1,0,0,1)
newLine.Position = UDim2.new(0,0,(i-1)/(5-1),0)
newLine.Parent = numberLineOutlines
end
for i = 1,numberLine.AbsoluteSize.X do
local line = sequenceLine:Clone()
eLines[i] = line
line.Name = "E"..tostring(i)
line.BackgroundTransparency = 0.5
line.BackgroundColor3 = Color3.new(199/255,44/255,28/255)
line.Position = UDim2.new(0,i-1,0,0)
line.Parent = numberLine
end
for i = 1,numberLine.AbsoluteSize.X do
local line = sequenceLine:Clone()
lines[i] = line
line.Name = tostring(i)
line.Position = UDim2.new(0,i-1,0,0)
line.Parent = numberLine
end
local envelopeDragTop,envelopeDragBottom =
envelopeDrag:Clone(),envelopeDrag:Clone()
envelopeDragTop.Parent = numberLine
envelopeDragBottom.Parent = numberLine
table.insert(newPoints,NumberSequenceKeypoint.new(v[2],v[1],v[3]))
end
newMt.Sequence = NumberSequence.new(newPoints)
newMt.OnSelect:Fire(newMt.Sequence)
end
local envelopeDistance =
numberLine.AbsoluteSize.Y*(point[3]/10)
envelopeDragTop.Position =
UDim2.new(0,point[4].Position.X.Offset-1,0,point[4].Position.Y.Offset-
envelopeDistance-17)
envelopeDragTop.Visible = true
envelopeDragBottom.Position =
UDim2.new(0,point[4].Position.X.Offset-
1,0,point[4].Position.Y.Offset+envelopeDistance+2)
envelopeDragBottom.Visible = true
end
end
envelopeDragTop.InputBegan:Connect(function(input)
if input.UserInputType ~= Enum.UserInputType.MouseButton1
or not currentPoint or Lib.CheckMouseInGui(currentPoint[4].Select) then return end
local mouseEvent,releaseEvent
local maxSize = numberLine.AbsoluteSize.Y
local mouseDelta =
math.abs(envelopeDragTop.AbsolutePosition.Y - mouse.Y)
envelopeDragTop.Line.Position = UDim2.new(0,2,0,0)
envelopeDragTop.Line.Size = UDim2.new(0,3,0,20)
releaseEvent = user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
mouseEvent:Disconnect()
releaseEvent:Disconnect()
envelopeDragTop.Line.Position = UDim2.new(0,3,0,0)
envelopeDragTop.Line.Size = UDim2.new(0,1,0,20)
end)
mouseEvent = user.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
local topDiff =
(currentPoint[4].AbsolutePosition.Y+2)-(mouse.Y-mouseDelta)-19
local newEnvelope =
10*(math.max(topDiff,0)/maxSize)
local maxEnvelope =
math.min(currentPoint[1],10-currentPoint[1])
currentPoint[3] =
math.min(newEnvelope,maxEnvelope)
newMt:Redraw()
buildSequence()
updateInputs(currentPoint)
end
end)
end)
envelopeDragBottom.InputBegan:Connect(function(input)
if input.UserInputType ~= Enum.UserInputType.MouseButton1
or not currentPoint or Lib.CheckMouseInGui(currentPoint[4].Select) then return end
local mouseEvent,releaseEvent
local maxSize = numberLine.AbsoluteSize.Y
local mouseDelta =
math.abs(envelopeDragBottom.AbsolutePosition.Y - mouse.Y)
envelopeDragBottom.Line.Position = UDim2.new(0,2,0,0)
envelopeDragBottom.Line.Size = UDim2.new(0,3,0,20)
releaseEvent = user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
mouseEvent:Disconnect()
releaseEvent:Disconnect()
envelopeDragBottom.Line.Position = UDim2.new(0,3,0,0)
envelopeDragBottom.Line.Size = UDim2.new(0,1,0,20)
end)
mouseEvent = user.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
local bottomDiff = (mouse.Y+(20-mouseDelta))-
(currentPoint[4].AbsolutePosition.Y+2)-19
local newEnvelope =
10*(math.max(bottomDiff,0)/maxSize)
local maxEnvelope =
math.min(currentPoint[1],10-currentPoint[1])
currentPoint[3] =
math.min(newEnvelope,maxEnvelope)
newMt:Redraw()
buildSequence()
updateInputs(currentPoint)
end
end)
end)
newPoint.Parent = numberLine
newSelect.InputBegan:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
for i,v in pairs(points) do
v[4].Select.BackgroundTransparency = 1 end
newSelect.BackgroundTransparency = 0
updateInputs(point)
end
if input.UserInputType ==
Enum.UserInputType.MouseButton1 and not currentlySelected then
currentPoint = point
local mouseEvent,releaseEvent
currentlySelected = true
newSelect.BackgroundColor3 =
Color3.new(249/255,191/255,59/255)
releaseEvent =
user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
mouseEvent:Disconnect()
releaseEvent:Disconnect()
currentlySelected = nil
newSelect.BackgroundColor3 =
Color3.new(199/255,44/255,28/255)
end)
mouseEvent =
user.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
local maxX =
numberLine.AbsoluteSize.X-1
local relativeX = mouse.X -
numberLine.AbsolutePosition.X
if relativeX < 0 then relativeX = 0
end
if relativeX > maxX then relativeX
= maxX end
local maxY =
numberLine.AbsoluteSize.Y-1
local relativeY = mouse.Y -
numberLine.AbsolutePosition.Y
if relativeY < 0 then relativeY = 0
end
if relativeY > maxY then relativeY
= maxY end
if point ~= beginPoint and point ~=
endPoint then
point[2] = relativeX/maxX
end
point[1] = 10-(relativeY/maxY)*10
local maxEnvelope =
math.min(point[1],10-point[1])
point[3] =
math.min(oldEnvelope,maxEnvelope)
newMt:Redraw()
updateInputs(point)
for i,v in pairs(points) do
v[4].Select.BackgroundTransparency = 1 end
newSelect.BackgroundTransparency =
0
buildSequence()
end
end)
end
end)
return newPoint
end
for lineCount =
math.min(fromPoint[4].Position.X.Offset+1,toPoint[4].Position.X.Offset),toPoint[4].
Position.X.Offset do
if deltaX == 0 and deltaY == 0 then return end
local riseNow = math.floor(currentRise)
local line = lines[lineCount+3]
if line then
if totalRise+riseNow > maxRise then
riseNow = maxRise-totalRise end
if math.sign(slope) == -1 then
line.Position =
UDim2.new(0,lineCount+2,0,fromPoint[4].Position.Y.Offset + -(totalRise+riseNow)+2)
else
line.Position =
UDim2.new(0,lineCount+2,0,fromPoint[4].Position.Y.Offset + totalRise+2)
end
line.Size =
UDim2.new(0,1,0,math.max(riseNow,1))
end
totalRise = totalRise + riseNow
currentRise = currentRise - riseNow +
math.abs(slope)
timeBox.FocusLost:Connect(function()
local point = currentPoint
local num = tonumber(timeBox.Text)
if point and num and point ~= beginPoint and point ~=
endPoint then
num = math.clamp(num,0,1)
point[2] = num
redraw()
buildSequence()
updateInputs(point)
end
end)
valueBox.FocusLost:Connect(function()
local point = currentPoint
local num = tonumber(valueBox.Text)
if point and num then
local oldEnvelope = point[3]
num = math.clamp(num,0,10)
point[1] = num
local maxEnvelope = math.min(point[1],10-point[1])
point[3] = math.min(oldEnvelope,maxEnvelope)
redraw()
buildSequence()
updateInputs(point)
end
end)
envelopeBox.FocusLost:Connect(function()
local point = currentPoint
local num = tonumber(envelopeBox.Text)
if point and num then
num = math.clamp(num,0,5)
local maxEnvelope = math.min(point[1],10-point[1])
point[3] = math.min(num,maxEnvelope)
redraw()
buildSequence()
updateInputs(point)
end
end)
numberLine.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
and #points < 20 then
if Lib.CheckMouseInGui(envelopeDragTop) or
Lib.CheckMouseInGui(envelopeDragBottom) then return end
for i,v in pairs(points) do
if Lib.CheckMouseInGui(v[4].Select) then return
end
end
local maxX = numberLine.AbsoluteSize.X-1
local relativeX = mouse.X -
numberLine.AbsolutePosition.X
if relativeX < 0 then relativeX = 0 end
if relativeX > maxX then relativeX = maxX end
local maxY = numberLine.AbsoluteSize.Y-1
local relativeY = mouse.Y -
numberLine.AbsolutePosition.Y
if relativeY < 0 then relativeY = 0 end
if relativeY > maxY then relativeY = maxY end
local raw = relativeX/maxX
local newPoint = {10-(relativeY/maxY)*10,raw,0}
newPoint[4] = placePoint(newPoint)
table.insert(points,newPoint)
redraw()
buildSequence()
end
end)
deleteButton.MouseButton1Click:Connect(function()
if currentPoint and currentPoint ~= beginPoint and
currentPoint ~= endPoint then
for i,v in pairs(points) do
if v == currentPoint then
v[4]:Destroy()
table.remove(points,i)
break
end
end
currentlySelected = nil
redraw()
buildSequence()
updateInputs(points[1])
end
end)
resetButton.MouseButton1Click:Connect(function()
if resetSequence then
newMt:SetSequence(resetSequence)
buildSequence()
end
end)
closeButton.MouseButton1Click:Connect(function()
window:Close()
end)
buttonAnimations(deleteButton)
buttonAnimations(resetButton)
buttonAnimations(closeButton)
placePoints()
redraw()
newMt.Show = function(self)
window:Show()
end
return newMt
end
newMt.Sequence = ColorSequence.new(Color3.new(1,1,1))
local function buildSequence(noupdate)
local newPoints = {}
table.sort(colors,function(a,b) return a[2] < b[2] end)
for i,v in pairs(colors) do
table.insert(newPoints,ColorSequenceKeypoint.new(v[2],v[1]))
end
newMt.Sequence = ColorSequence.new(newPoints)
if not noupdate then newMt.OnSelect:Fire(newMt.Sequence)
end
end
newArrow.InputBegan:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
cursor.Visible = true
cursor.Position = UDim2.new(0,9 +
newArrow.Position.X.Offset,0,0)
end
if input.UserInputType ==
Enum.UserInputType.MouseButton1 then
updateInputs(point)
if point == beginPoint or point == endPoint or
currentlySelected then return end
local mouseEvent,releaseEvent
currentlySelected = true
releaseEvent =
user.InputEnded:Connect(function(input)
if input.UserInputType ~=
Enum.UserInputType.MouseButton1 then return end
mouseEvent:Disconnect()
releaseEvent:Disconnect()
currentlySelected = nil
cursor.Visible = false
end)
mouseEvent =
user.InputChanged:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
local maxSize =
colorLine.AbsoluteSize.X-1
local relativeX = mouse.X -
colorLine.AbsolutePosition.X
if relativeX < 0 then relativeX = 0
end
if relativeX > maxSize then
relativeX = maxSize end
local raw = relativeX/maxSize
point[2] = relativeX/maxSize
updateInputs(point)
cursor.Visible = true
cursor.Position = UDim2.new(0,9 +
newArrow.Position.X.Offset,0,0)
buildSequence()
newMt:Redraw()
end
end)
end
end)
newArrow.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType.MouseMovement then
cursor.Visible = false
end
end)
return newArrow
end
for i = 2,#colors do
local nextColor = colors[i]
local endPos = math.floor((colorLine.AbsoluteSize.X-
1) * nextColor[2]) + 1
nextColor[3].Position = UDim2.new(0,endPos,0,0)
end
end
newMt.Redraw = redraw
colorLine.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
and #colors < 20 then
local maxSize = colorLine.AbsoluteSize.X-1
local relativeX = mouse.X -
colorLine.AbsolutePosition.X
if relativeX < 0 then relativeX = 0 end
if relativeX > maxSize then relativeX = maxSize end
colorLine.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
then
local maxSize = colorLine.AbsoluteSize.X-1
local relativeX = mouse.X -
colorLine.AbsolutePosition.X
if relativeX < 0 then relativeX = 0 end
if relativeX > maxSize then relativeX = maxSize end
cursor.Visible = true
cursor.Position = UDim2.new(0,10 + relativeX,0,0)
end
end)
colorLine.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement
then
local inArrow = false
for i,v in pairs(colors) do
if Lib.CheckMouseInGui(v[3]) then
inArrow = v[3]
end
end
cursor.Visible = inArrow and true or false
if inArrow then cursor.Position = UDim2.new(0,9 +
inArrow.Position.X.Offset,0,0) end
end
end)
timeBox:GetPropertyChangedSignal("Text"):Connect(function()
local point = currentPoint
local num = tonumber(timeBox.Text)
if point and num and point ~= beginPoint and point ~=
endPoint then
num = math.clamp(num,0,1)
point[2] = num
buildSequence()
redraw()
end
end)
colorBox.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
then
local editor = newMt.ColorPicker
if not editor then
editor = Lib.ColorPicker.new()
editor.Window:SetTitle("ColorSequence Color
Picker")
editor.OnSelect:Connect(function(col)
if currentPoint then
currentPoint[1] = col
end
buildSequence()
redraw()
end)
newMt.ColorPicker = editor
end
editor.Window:ShowAndFocus()
end
end)
deleteButton.MouseButton1Click:Connect(function()
if currentPoint and currentPoint ~= beginPoint and
currentPoint ~= endPoint then
for i,v in pairs(colors) do
if v == currentPoint then
v[3]:Destroy()
table.remove(colors,i)
break
end
end
currentlySelected = nil
updateInputs(colors[1])
buildSequence()
redraw()
end
end)
resetButton.MouseButton1Click:Connect(function()
if resetSequence then
newMt:SetSequence(resetSequence)
end
end)
closeButton.MouseButton1Click:Connect(function()
window:Close()
end)
topClose.MouseButton1Click:Connect(function()
window:Close()
end)
buttonAnimations(deleteButton)
buttonAnimations(resetButton)
buttonAnimations(closeButton)
placeArrows()
redraw()
newMt.Show = function(self)
window:Show()
end
return newMt
end
Lib.ViewportTextBox = (function()
local textService = clonerefs(game:GetService("TextService"))
local props = {
OffsetX = 0,
TextBox = PH,
CursorPos = -1,
Gui = PH,
View = PH
}
local funcs = {}
funcs.Update = function(self)
local cursorPos = self.CursorPos or -1
local text = self.TextBox.Text
if text == "" then self.TextBox.Position = UDim2.new(0,0,0,0)
return end
if cursorPos == -1 then return end
local totalTextSize =
textService:GetTextSize(text,self.TextBox.TextSize,self.TextBox.Font,Vector2.new(99
9999999,100)).X
local cursorTextSize =
textService:GetTextSize(cursorText,self.TextBox.TextSize,self.TextBox.Font,Vector2.
new(999999999,100)).X
if pos then
self.TextBox.Position = UDim2.new(0,-pos,0,0)
self.TextBox.Size = UDim2.new(1,pos,1,0)
end
end
funcs.GetText = function(self)
return self.TextBox.Text
end
funcs.SetText = function(self,text)
self.TextBox.Text = text
end
local mt = getGuiMT(props,funcs)
obj.TextBox = textbox
obj.View = view
obj.Gui = view
textbox.Changed:Connect(function(prop)
if prop == "Text" or prop == "CursorPosition" or prop ==
"AbsoluteSize" then
local cursorPos = obj.TextBox.CursorPosition
if cursorPos ~= -1 then obj.CursorPos = cursorPos end
obj:Update()
end
end)
obj:Update()
view.Parent = textbox.Parent
textbox.Parent = view
return obj
end
Lib.Label = (function()
local props,funcs = {},{}
local mt = getGuiMT(props,funcs)
local function new()
local label = Instance.new("TextLabel")
label.BackgroundTransparency = 1
label.TextXAlignment = Enum.TextXAlignment.Left
label.TextColor3 = Settings.Theme.Text
label.TextTransparency = 0.1
label.Size = UDim2.new(0,100,0,20)
label.Font = Enum.Font.SourceSans
label.TextSize = 14
Lib.Frame = (function()
local props,funcs = {},{}
local mt = getGuiMT(props,funcs)
Lib.Button = (function()
local props = {
Gui = PH,
Anim = PH,
Disabled = false,
OnClick = SIGNAL,
OnDown = SIGNAL,
OnUp = SIGNAL,
AllowedButtons = {1}
}
local funcs = {}
local tableFind = table.find
funcs.Trigger = function(self,event,button)
if not self.Disabled and tableFind(self.AllowedButtons,button)
then
self["On"..event]:Fire(button)
end
end
funcs.SetDisabled = function(self,dis)
self.Disabled = dis
if dis then
self.Anim:Disable()
self.Gui.TextTransparency = 0.5
else
self.Anim.Enable()
self.Gui.TextTransparency = 0
end
end
local mt = getGuiMT(props,funcs)
b.MouseButton1Click:Connect(function() obj:Trigger("Click",1)
end)
b.MouseButton1Down:Connect(function() obj:Trigger("Down",1) end)
b.MouseButton1Up:Connect(function() obj:Trigger("Up",1) end)
b.MouseButton2Click:Connect(function() obj:Trigger("Click",2)
end)
b.MouseButton2Down:Connect(function() obj:Trigger("Down",2) end)
b.MouseButton2Up:Connect(function() obj:Trigger("Up",2) end)
return obj
end
Lib.DropDown = (function()
local props = {
Gui = PH,
Anim = PH,
Context = PH,
Selected = PH,
Disabled = false,
CanBeEmpty = true,
Options = {},
GuiElems = {},
OnSelect = SIGNAL
}
local funcs = {}
funcs.Update = function(self)
local options = self.Options
funcs.ShowOptions = function(self)
local context = self.Context
context.Width = self.Gui.AbsoluteSize.X
context.ReverseYOffset = self.Gui.AbsoluteSize.Y
context:Show(self.Gui.AbsolutePosition.X,
self.Gui.AbsolutePosition.Y + context.ReverseYOffset)
end
funcs.SetOptions = function(self,opts)
self.Options = opts
if self.CanBeEmpty then
context:Add({Name = "- Select -", OnClick = function()
self.Selected = nil self.OnSelect:Fire(nil) self:Update() end})
end
for i = 1,#options do
context:Add({Name = options[i], OnClick = onClick})
end
self:Update()
end
funcs.SetSelected = function(self,opt)
self.Selected = type(opt) == "number" and self.Options[opt] or
opt
self:Update()
end
local mt = getGuiMT(props,funcs)
local function new()
local f = Instance.new("TextButton")
f.AutoButtonColor = false
f.Text = ""
f.Size = UDim2.new(0,100,0,20)
f.BackgroundColor3 = Settings.Theme.TextBox
f.BorderColor3 = Settings.Theme.Outline3
Lib.ClickSystem = (function()
local props = {
LastItem = PH,
OnDown = SIGNAL,
OnRelease = SIGNAL,
AllowedButtons = {1},
Combo = 0,
MaxCombo = 2,
ComboTime = 0.5,
Items = {},
ItemCons = {},
ClickId = -1,
LastButton = ""
}
local funcs = {}
local tostring = tostring
funcs.Trigger = function(self,item,button)
if table.find(self.AllowedButtons,button) then
if self.LastButton ~= button or self.LastItem ~= item or
self.Combo == self.MaxCombo or tick() - self.ClickId > self.ComboTime then
self.Combo = 0
self.LastButton = button
self.LastItem = item
end
self.Combo = self.Combo + 1
self.ClickId = tick()
local release
release =
service.UserInputService.InputEnded:Connect(function(input)
if input.UserInputType ==
Enum.UserInputType["MouseButton"..button] then
release:Disconnect()
if Lib.CheckMouseInGui(item) and
self.LastButton == button and self.LastItem == item then
self["OnRelease"]:Fire(item,self.Combo,button)
end
end
end)
self["OnDown"]:Fire(item,self.Combo,button)
end
end
funcs.Add = function(self,item)
if table.find(self.Items,item) then return end
local cons = {}
cons[1] = item.MouseButton1Down:Connect(function()
self:Trigger(item,1) end)
cons[2] = item.MouseButton2Down:Connect(function()
self:Trigger(item,2) end)
self.ItemCons[item] = cons
self.Items[#self.Items+1] = item
end
funcs.Remove = function(self,item)
local ind = table.find(self.Items,item)
if not ind then return end
return obj
end
return Lib
end
-- Main vars
local Main, Explorer, Properties, ScriptViewer, DefaultSettings, Notebook,
Serializer, Lib
local API, RMD
-- Default Settings
DefaultSettings = (function()
local rgb = Color3.fromRGB
return {
Explorer = {
_Recurse = true,
Sorting = true,
TeleportToOffset = Vector3.new(0,0,0),
ClickToRename = true,
AutoUpdateSearch = true,
AutoUpdateMode = 0, -- 0 Default, 1 no tree update, 2 no
descendant events, 3 frozen
PartSelectionBox = true,
GuiSelectionBox = true,
CopyPathUseGetChildren = true
},
Properties = {
_Recurse = true,
MaxConflictCheck = 50,
ShowDeprecated = false,
ShowHidden = false,
ClearOnFocus = false,
LoadstringInput = true,
NumberRounding = 3,
ShowAttributes = false,
MaxAttributes = 50,
ScaleType = 1 -- 0 Full Name Shown, 1 Equal Halves
},
Theme = {
_Recurse = true,
Main1 = rgb(52,52,52),
Main2 = rgb(45,45,45),
Outline1 = rgb(33,33,33), -- Mainly frames
Outline2 = rgb(55,55,55), -- Mainly button
Outline3 = rgb(30,30,30), -- Mainly textbox
TextBox = rgb(38,38,38),
Menu = rgb(32,32,32),
ListSelection = rgb(11,90,175),
Button = rgb(60,60,60),
ButtonHover = rgb(68,68,68),
ButtonPress = rgb(40,40,40),
Highlight = rgb(75,75,75),
Text = rgb(255,255,255),
PlaceholderText = rgb(100,100,100),
Important = rgb(255,0,0),
ExplorerIconMap = "",
MiscIconMap = "",
Syntax = {
Text = rgb(204,204,204),
Background = rgb(36,36,36),
Selection = rgb(255,255,255),
SelectionBack = rgb(11,90,175),
Operator = rgb(204,204,204),
Number = rgb(255,198,0),
String = rgb(173,241,149),
Comment = rgb(102,102,102),
Keyword = rgb(248,109,124),
Error = rgb(255,0,0),
FindBackground = rgb(141,118,0),
MatchingWord = rgb(85,85,85),
BuiltIn = rgb(132,214,247),
CurrentLine = rgb(45,50,65),
LocalMethod = rgb(253,251,172),
LocalProperty = rgb(97,161,241),
Nil = rgb(255,198,0),
Bool = rgb(255,198,0),
Function = rgb(248,109,124),
Local = rgb(248,109,124),
Self = rgb(248,109,124),
FunctionName = rgb(253,251,172),
Bracket = rgb(204,204,204)
},
}
}
end)()
-- Vars
local Settings = {}
local Apps = {}
local env = {}
local service = setmetatable({},{__index = function(self,name)
local serv = clonerefs(game:GetService(name))
self[name] = serv
return serv
end})
local plr = service.Players.LocalPlayer or service.Players.PlayerAdded:wait()
return insts[1]
end
Main = (function()
local Main = {}
Main.ModuleList = {"Explorer","Properties","ScriptViewer"}
Main.Elevated = false
Main.MissingEnv = {}
Main.Version = "" -- Beta 1.0.0
Main.Mouse = plr:GetMouse()
Main.AppControls = {}
Main.Apps = Apps
Main.MenuApps = {}
Main.DisplayOrders = {
SideWindow = 8,
Window = 10,
Menu = 100000,
Core = 101000
}
Main.GetInitDeps = function()
return {
Main = Main,
Lib = Lib,
Apps = Apps,
Settings = Settings,
API = API,
RMD = RMD,
env = env,
service = service,
plr = plr,
create = create,
createSimple = createSimple
}
end
Main.Error = function(str)
if rconsoleprint then
rconsoleprint("DEX ERROR: "..tostring(str).."\n")
wait(9e9)
else
error(str)
end
end
Main.LoadModule = function(name)
if Main.Elevated then -- If you don't have filesystem api then ur outta
luck tbh
local control
Main.AppControls[name] = control
control.InitDeps(Main.GetInitDeps())
Main.LoadModules = function()
for i,v in pairs(Main.ModuleList) do
local s,e = pcall(Main.LoadModule,v)
if not s then
Main.Error("FAILED LOADING " + v + " CAUSE " + e)
end
end
Main.InitEnv = function()
setmetatable(env, {__newindex = function(self, name, func)
if not func then Main.MissingEnv[#Main.MissingEnv + 1] = name
return end
rawset(self, name, func)
end})
-- file
env.readfile = readfile
env.writefile = writefile
env.appendfile = appendfile
env.makefolder = makefolder
env.listfiles = listfiles
env.loadfile = loadfile
env.saveinstance = saveinstance
-- debug
env.getupvalues = debug.getupvalues or getupvals
env.getconstants = debug.getconstants or getconsts
env.islclosure = islclosure or is_l_closure
env.checkcaller = checkcaller
env.getreg = getreg
env.getgc = getgc
-- other
env.setfflag = setfflag
env.decompile = decompile
env.protectgui = protect_gui or (syn and syn.protect_gui)
env.gethui = gethui
env.setclipboard = setclipboard
env.getnilinstances = getnilinstances or get_nil_instances
env.getloadedmodules = getloadedmodules
setmetatable(env, nil)
end
Main.LoadSettings = function()
local s,data = pcall(env.readfile or error,"DexSettings.json")
if s and data and data ~= "" then
local s,decoded = service.HttpService:JSONDecode(data)
if s and decoded then
for i,v in next,decoded do
end
else
-- TODO: Notification
end
else
Main.ResetSettings()
end
end
Main.ResetSettings = function()
local function recur(t,res)
for set,val in pairs(t) do
if type(val) == "table" and val._Recurse then
if type(res[set]) ~= "table" then
res[set] = {}
end
recur(val,res[set])
else
res[set] = val
end
end
return res
end
recur(DefaultSettings,Settings)
end
Main.FetchAPI = function()
local api,rawAPI
if Main.Elevated then
if Main.LocalDepsUpToDate() then
local localAPI = Lib.ReadFile("dex/rbx_api.dat")
if localAPI then
rawAPI = localAPI
else
Main.DepsVersionData[1] = ""
end
end
rawAPI = rawAPI or
game:HttpGet("http://setup.roblox.com/"..Main.RobloxVersion.."-API-Dump.json")
else
if script:FindFirstChild("API") then
rawAPI = require(script.API)
else
error("NO API EXISTS")
end
end
Main.RawAPI = rawAPI
api = service.HttpService:JSONDecode(rawAPI)
classes[class.Name] = newClass
end
enums[enum.Name] = newEnum
end
insertAbove(categoryOrder,"Behavior","Tuning")
insertAbove(categoryOrder,"Appearance","Data")
insertAbove(categoryOrder,"Attachments","Axes")
insertAbove(categoryOrder,"Cylinder","Slider")
insertAbove(categoryOrder,"Localization","Jump Settings")
insertAbove(categoryOrder,"Surface","Motion")
insertAbove(categoryOrder,"Surface Inputs","Surface")
insertAbove(categoryOrder,"Part","Surface Inputs")
insertAbove(categoryOrder,"Assembly","Surface Inputs")
insertAbove(categoryOrder,"Character","Controls")
categoryOrder[#categoryOrder+1] = "Unscriptable"
categoryOrder[#categoryOrder+1] = "Attributes"
local categoryOrderMap = {}
for i = 1,#categoryOrder do
categoryOrderMap[categoryOrder[i]] = i
end
return {
Classes = classes,
Enums = enums,
CategoryOrder = categoryOrderMap,
GetMember = getMember
}
end
Main.FetchRMD = function()
local rawXML
if Main.Elevated then
if Main.LocalDepsUpToDate() then
local localRMD = Lib.ReadFile("dex/rbx_rmd.dat")
if localRMD then
rawXML = localRMD
else
Main.DepsVersionData[1] = ""
end
end
rawXML = rawXML or
game:HttpGet("https://raw.githubusercontent.com/CloneTrooper1019/Roblox-Client-
Tracker/roblox/ReflectionMetadata.xml")
else
if script:FindFirstChild("RMD") then
rawXML = require(script.RMD)
else
error("NO RMD EXISTS")
end
end
Main.RawRMD = rawXML
local parsed = Lib.ParseXML(rawXML)
local classList = parsed.children[1].children[1].children
local enumList = parsed.children[1].children[2].children
local propertyOrders = {}
classes[className].Properties[data.Name] = data
end
end
end
elseif child.attrs.class == "ReflectionMetadataFunctions"
then
local members = child.children
for _,member in pairs(members) do
if member.attrs.class ==
"ReflectionMetadataMember" then
local data = {}
if member.children[1].tag == "Properties"
then
local props =
member.children[1].children
for _,prop in pairs(props) do
if prop.attrs then
local name =
prop.attrs.name
name =
name:sub(1,1):upper()..name:sub(2)
data[name] =
prop.children[1].text
end
end
classes[className].Functions[data.Name] = data
end
end
end
end
end
end
Main.ShowGui = function(gui)
if env.protectgui then
env.protectgui(gui)
end
gui.Parent = Main.GuiHolder
end
local ti =
TweenInfo.new(0.4,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
tweenNumber(100,ti,function(val)
val = val/200
local start = NumberSequenceKeypoint.new(0,0)
local a1 = NumberSequenceKeypoint.new(val,0)
local a2 =
NumberSequenceKeypoint.new(math.min(0.5,val+math.min(0.05,val)),1)
if a1.Time == a2.Time then a2 = a1 end
local b1 = NumberSequenceKeypoint.new(1-val,0)
local b2 = NumberSequenceKeypoint.new(math.max(0.5,1-val-
math.min(0.05,val)),1)
if b1.Time == b2.Time then b2 = b1 end
local goal = NumberSequenceKeypoint.new(1,0)
backGradient.Transparency =
NumberSequence.new({start,a1,a2,b2,b1,goal})
outlinesGradient.Transparency =
NumberSequence.new({start,a1,a2,b2,b1,goal})
end)
fastwait(0.4)
tweenNumber(100,ti,function(val)
val = val/166.66
local start = NumberSequenceKeypoint.new(0,0)
local a1 = NumberSequenceKeypoint.new(val,0)
local a2 = NumberSequenceKeypoint.new(val+0.01,1)
local goal = NumberSequenceKeypoint.new(1,1)
holderGradient.Transparency =
NumberSequence.new({start,a1,a2,goal})
end)
tweenS:Create(titleText,ti,{Position = UDim2.new(0,60,0,15),
TextTransparency = 0}):Play()
tweenS:Create(descText,ti,{Position = UDim2.new(0,20,0,60),
TextTransparency = 0}):Play()
fastwait(0.9)
local progressTI =
TweenInfo.new(0.25,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
tweenS:Create(statusText,progressTI,{Position = UDim2.new(0,20,0,120),
TextTransparency = 0}):Play()
tweenS:Create(progressBar,progressTI,{Position = UDim2.new(0,60,0,145),
Size = UDim2.new(0,100,0,4)}):Play()
fastwait(0.25)
tweenNumber(100,TweenInfo.new(0.4,Enum.EasingStyle.Back,Enum.EasingDirection.In),fu
nction(val)
val = val/250
local start = NumberSequenceKeypoint.new(0,0)
local a1 = NumberSequenceKeypoint.new(0.6+val,0)
local a2 =
NumberSequenceKeypoint.new(math.min(1,0.601+val),1)
if a1.Time == a2.Time then a2 = a1 end
local goal = NumberSequenceKeypoint.new(1,a1 == a2 and 0 or
1)
holderGradient.Transparency =
NumberSequence.new({start,a1,a2,goal})
end)
fastwait(0.5)
gui.Main.BackgroundTransparency = 1
outlinesGradient.Rotation = 30
tweenNumber(100,ti,function(val)
val = val/100
local start = NumberSequenceKeypoint.new(0,1)
local a1 = NumberSequenceKeypoint.new(val,1)
local a2 =
NumberSequenceKeypoint.new(math.min(1,val+math.min(0.05,val)),0)
if a1.Time == a2.Time then a2 = a1 end
local goal = NumberSequenceKeypoint.new(1,a1 == a2 and 1 or
0)
outlinesGradient.Transparency =
NumberSequence.new({start,a1,a2,goal})
holderGradient.Transparency =
NumberSequence.new({start,a1,a2,goal})
end)
fastwait(0.45)
gui:Destroy()
end
Main.CreateApp = function(data)
if Main.MenuApps[data.Name] then return end -- TODO: Handle conflict
local control = {}
updateState()
local ySize =
service.TextService:GetTextSize(data.Name,14,Enum.Font.SourceSans,Vector2.new(62,99
9999)).Y
app.Main.Size = UDim2.new(1,0,0,math.clamp(46+ySize,60,74))
app.Main.AppName.Text = data.Name
app.Main.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
app.Main.BackgroundTransparency = 0
app.Main.BackgroundColor3 = Settings.Theme.ButtonHover
end
end)
app.Main.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
app.Main.BackgroundTransparency = data.Open and 0 or 1
app.Main.BackgroundColor3 = Settings.Theme.Button
end
end)
app.Main.MouseButton1Click:Connect(function()
if data.Open then disable() else enable() end
end)
app.Visible = true
app.Parent = Main.AppsContainer
Main.AppsFrame.CanvasSize =
UDim2.new(0,0,0,Main.AppsContainerGrid.AbsoluteCellCount.Y*82 + 8)
control.Enable = enable
control.Disable = disable
Main.MenuApps[data.Name] = control
return control
end
Main.SetMainGuiOpen = function(val)
Main.MainGuiOpen = val
service.TweenService:Create(Main.MainGui.OpenButton,TweenInfo.new(0.2,Enum.EasingSt
yle.Quad,Enum.EasingDirection.Out),{BackgroundTransparency = val and 0 or
(Lib.CheckMouseInGui(Main.MainGui.OpenButton) and 0 or 0.2)}):Play()
Main.CreateMainGui = function()
local gui = create({
{1,"ScreenGui",{IgnoreGuiInset=true,Name="MainMenu",}},
{2,"TextButton",
{AnchorPoint=Vector2.new(0.5,0),AutoButtonColor=false,BackgroundColor3=Color3.new(0
.17647059261799,0.17647059261799,0.17647059261799),BorderSizePixel=0,Font=4,Name="O
penButton",Parent={1},Position=UDim2.new(0.5,0,0,2),Size=UDim2.new(0,32,0,32),Text=
"Dex",TextColor3=Color3.new(1,1,1),TextSize=16,TextTransparency=0.20000000298023,}}
,
{3,"UICorner",{CornerRadius=UDim.new(0,4),Parent={2},}},
{4,"Frame",
{AnchorPoint=Vector2.new(0.5,0),BackgroundColor3=Color3.new(0.17647059261799,0.1764
7059261799,0.17647059261799),ClipsDescendants=true,Name="MainFrame",Parent={2},Posi
tion=UDim2.new(0.5,0,1,-4),Size=UDim2.new(0,224,0,200),}},
{5,"UICorner",{CornerRadius=UDim.new(0,4),Parent={4},}},
{6,"Frame",
{BackgroundColor3=Color3.new(0.20392157137394,0.20392157137394,0.20392157137394),Na
me="BottomFrame",Parent={4},Position=UDim2.new(0,0,1,-
24),Size=UDim2.new(1,0,0,24),}},
{7,"UICorner",{CornerRadius=UDim.new(0,4),Parent={6},}},
{8,"Frame",
{BackgroundColor3=Color3.new(0.20392157137394,0.20392157137394,0.20392157137394),Bo
rderSizePixel=0,Name="CoverFrame",Parent={6},Size=UDim2.new(1,0,0,4),}},
{9,"Frame",
{BackgroundColor3=Color3.new(0.1294117718935,0.1294117718935,0.1294117718935),Borde
rSizePixel=0,Name="Line",Parent={8},Position=UDim2.new(0,0,0,-
1),Size=UDim2.new(1,0,0,1),}},
{10,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Font=3,Name="Settings"
,Parent={6},Position=UDim2.new(1,-
48,0,0),Size=UDim2.new(0,24,1,0),Text="",TextColor3=Color3.new(1,1,1),TextSize=14,}
},
{11,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxassetid://
6578871732",ImageTransparency=0.20000000298023,Name="Icon",Parent={10},Position=UDi
m2.new(0,4,0,4),Size=UDim2.new(0,16,0,16),}},
{12,"TextButton",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Font=3,Name="Informati
on",Parent={6},Position=UDim2.new(1,-
24,0,0),Size=UDim2.new(0,24,1,0),Text="",TextColor3=Color3.new(1,1,1),TextSize=14,}
},
{13,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxassetid://
6578933307",ImageTransparency=0.20000000298023,Name="Icon",Parent={12},Position=UDi
m2.new(0,4,0,4),Size=UDim2.new(0,16,0,16),}},
{14,"ScrollingFrame",
{Active=true,AnchorPoint=Vector2.new(0.5,0),BackgroundColor3=Color3.new(1,1,1),Back
groundTransparency=1,BorderColor3=Color3.new(0.1294117718935,0.1294117718935,0.1294
117718935),BorderSizePixel=0,Name="AppsFrame",Parent={4},Position=UDim2.new(0.5,0,0
,0),ScrollBarImageColor3=Color3.new(0,0,0),ScrollBarThickness=4,Size=UDim2.new(0,22
2,1,-25),}},
{15,"Frame",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Name="Container",Paren
t={14},Position=UDim2.new(0,7,0,8),Size=UDim2.new(1,-14,0,2),}},
{16,"UIGridLayout",
{CellSize=UDim2.new(0,66,0,74),Parent={15},SortOrder=2,}},
{17,"Frame",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Name="App",Parent={1},
Size=UDim2.new(0,100,0,100),Visible=false,}},
{18,"TextButton",
{AutoButtonColor=false,BackgroundColor3=Color3.new(0.2352941185236,0.2352941185236,
0.2352941185236),BorderSizePixel=0,Font=3,Name="Main",Parent={17},Size=UDim2.new(1,
0,0,60),Text="",TextColor3=Color3.new(0,0,0),TextSize=14,}},
{19,"ImageLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,Image="rbxassetid://
6579106223",ImageRectSize=Vector2.new(32,32),Name="Icon",Parent={18},Position=UDim2
.new(0.5,-16,0,4),ScaleType=4,Size=UDim2.new(0,32,0,32),}},
{20,"TextLabel",
{BackgroundColor3=Color3.new(1,1,1),BackgroundTransparency=1,BorderSizePixel=0,Font
=3,Name="AppName",Parent={18},Position=UDim2.new(0,2,0,38),Size=UDim2.new(1,-4,1,-
40),Text="Explorer",TextColor3=Color3.new(1,1,1),TextSize=14,TextTransparency=0.100
00000149012,TextTruncate=1,TextWrapped=true,TextYAlignment=0,}},
{21,"Frame",
{BackgroundColor3=Color3.new(0,0.66666668653488,1),BorderSizePixel=0,Name="Highligh
t",Parent={18},Position=UDim2.new(0,0,1,-2),Size=UDim2.new(1,0,0,2),}},
})
Main.MainGui = gui
Main.AppsFrame = gui.OpenButton.MainFrame.AppsFrame
Main.AppsContainer = Main.AppsFrame.Container
Main.AppsContainerGrid = Main.AppsContainer.UIGridLayout
Main.AppTemplate = gui.App
Main.MainGuiOpen = false
openButton.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
service.TweenService:Create(Main.MainGui.OpenButton,TweenInfo.new(0,Enum.EasingStyl
e.Quad,Enum.EasingDirection.Out),{BackgroundTransparency = 0}):Play()
end
end)
openButton.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
service.TweenService:Create(Main.MainGui.OpenButton,TweenInfo.new(0,Enum.EasingStyl
e.Quad,Enum.EasingDirection.Out),{BackgroundTransparency = Main.MainGuiOpen and 0
or 0.2}):Play()
end
end)
Lib.ShowGui(gui)
end
Main.SetupFilesystem = function()
if not env.writefile or not env.makefolder then return end
local writefile, makefolder = env.writefile, env.makefolder
makefolder("dex")
makefolder("dex/assets")
makefolder("dex/saved")
makefolder("dex/plugins")
makefolder("dex/ModuleCache")
end
Main.LocalDepsUpToDate = function()
return Main.DepsVersionData and Main.ClientVersion ==
Main.DepsVersionData[1]
end
Main.Init = function()
Main.Elevated = pcall(function() local a =
clonerefs(game:GetService("CoreGui")):GetFullName() end)
Main.InitEnv()
Main.LoadSettings()
Main.SetupFilesystem()
-- Load Lib
local intro = Main.CreateIntro("Initializing Library")
Lib = Main.LoadModule("Lib")
Lib.FastWait()
-- Init icons
Main.MiscIcons =
Lib.IconMap.new("rbxassetid://6511490623",256,256,16,16)
Main.MiscIcons:SetDict({
Reference = 0, Cut = 1,
Cut_Disabled = 2, Copy = 3, Copy_Disabled = 4, Paste = 5,
Paste_Disabled = 6,
Delete = 7, Delete_Disabled = 8, Group
= 9, Group_Disabled = 10, Ungroup = 11, Ungroup_Disabled =
12, TeleportTo = 13,
Rename = 14, JumpToParent = 15,
ExploreData = 16, Save = 17, CallFunction = 18, CallRemote =
19, Undo = 20,
Undo_Disabled = 21, Redo = 22,
Redo_Disabled = 23, Expand_Over = 24, Expand = 25, Collapse_Over
= 26, Collapse = 27,
SelectChildren = 28, SelectChildren_Disabled = 29,
InsertObject = 30, ViewScript = 31, AddStar = 32, RemoveStar =
33, Script_Disabled = 34,
LocalScript_Disabled = 35, Play = 36, Pause
= 37, Rename_Disabled = 38
})
Main.LargeIcons =
Lib.IconMap.new("rbxassetid://6579106223",256,256,32,32)
Main.LargeIcons:SetDict({
Explorer = 0, Properties = 1, Script_Viewer = 2,
})
-- Done
intro.SetProgress("Complete",1)
coroutine.wrap(function()
Lib.FastWait(1.25)
intro.Close()
end)()
-- Init window system, create main menu, show explorer and properties
Lib.Window.Init()
Main.CreateMainGui()
Explorer.Window:Show({Align = "right", Pos = 1, Size = 0.5, Silent =
true})
Properties.Window:Show({Align = "right", Pos = 2, Size = 0.5, Silent =
true})
Lib.DeferFunc(function() Lib.Window.ToggleSide("right") end)
end
return Main
end)()
-- Start
Main.Init()