diff --git a/Novetus/Novetus.Bootstrapper/LocalFuncs.cs b/Novetus/Novetus.Bootstrapper/LocalFuncs.cs
index 5f9ad1f..7ee7973 100644
--- a/Novetus/Novetus.Bootstrapper/LocalFuncs.cs
+++ b/Novetus/Novetus.Bootstrapper/LocalFuncs.cs
@@ -15,6 +15,7 @@ namespace Novetus.Bootstrapper
{
public static void LaunchApplicationExt(string filePath, string appName, string args = "")
{
+ GlobalFuncs.Config(LocalPaths.ConfigPath, true);
GlobalFuncs.LogPrint("Starting " + appName);
try
{
diff --git a/Novetus/Novetus.Bootstrapper/LocalPaths.cs b/Novetus/Novetus.Bootstrapper/LocalPaths.cs
index c9e4945..d8c9a2a 100644
--- a/Novetus/Novetus.Bootstrapper/LocalPaths.cs
+++ b/Novetus/Novetus.Bootstrapper/LocalPaths.cs
@@ -24,6 +24,7 @@ namespace Novetus.Bootstrapper
#region File Paths
public static readonly string LauncherPath = FixedBinDir + "\\" + LauncherName;
public static readonly string InfoPath = FixedConfigDir + "\\" + GlobalPaths.InfoName;
+ public static readonly string ConfigPath = FixedConfigDir + "\\" + GlobalPaths.ConfigName;
#endregion
}
#endregion
diff --git a/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.Designer.cs b/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.Designer.cs
index a211bb7..d44256d 100644
--- a/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.Designer.cs
+++ b/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.Designer.cs
@@ -42,6 +42,7 @@ namespace Novetus.Bootstrapper
this.URIButton = new System.Windows.Forms.Button();
this.VersionLabel = new System.Windows.Forms.Label();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ this.LauncherBox = new System.Windows.Forms.CheckBox();
this.CMDGroup.SuspendLayout();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
@@ -90,7 +91,7 @@ namespace Novetus.Bootstrapper
//
// DependencyInstallerButton
//
- this.DependencyInstallerButton.Location = new System.Drawing.Point(30, 46);
+ this.DependencyInstallerButton.Location = new System.Drawing.Point(32, 42);
this.DependencyInstallerButton.Name = "DependencyInstallerButton";
this.DependencyInstallerButton.Size = new System.Drawing.Size(155, 23);
this.DependencyInstallerButton.TabIndex = 5;
@@ -129,12 +130,13 @@ namespace Novetus.Bootstrapper
//
// groupBox1
//
+ this.groupBox1.Controls.Add(this.LauncherBox);
this.groupBox1.Controls.Add(this.URIButton);
this.groupBox1.Controls.Add(this.LaunchSDKButton);
this.groupBox1.Controls.Add(this.DependencyInstallerButton);
- this.groupBox1.Location = new System.Drawing.Point(281, 195);
+ this.groupBox1.Location = new System.Drawing.Point(281, 191);
this.groupBox1.Name = "groupBox1";
- this.groupBox1.Size = new System.Drawing.Size(216, 80);
+ this.groupBox1.Size = new System.Drawing.Size(216, 91);
this.groupBox1.TabIndex = 7;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Other Options";
@@ -172,6 +174,17 @@ namespace Novetus.Bootstrapper
this.pictureBox1.TabIndex = 1;
this.pictureBox1.TabStop = false;
//
+ // LauncherBox
+ //
+ this.LauncherBox.AutoSize = true;
+ this.LauncherBox.Location = new System.Drawing.Point(51, 68);
+ this.LauncherBox.Name = "LauncherBox";
+ this.LauncherBox.Size = new System.Drawing.Size(120, 17);
+ this.LauncherBox.TabIndex = 7;
+ this.LauncherBox.Text = "Skip on next launch";
+ this.LauncherBox.UseVisualStyleBackColor = true;
+ this.LauncherBox.CheckedChanged += new System.EventHandler(this.LauncherBox_CheckedChanged);
+ //
// NovetusLaunchForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -192,6 +205,7 @@ namespace Novetus.Bootstrapper
this.CMDGroup.ResumeLayout(false);
this.CMDGroup.PerformLayout();
this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
@@ -211,6 +225,7 @@ namespace Novetus.Bootstrapper
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button URIButton;
private System.Windows.Forms.Label VersionLabel;
+ private System.Windows.Forms.CheckBox LauncherBox;
}
}
diff --git a/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs b/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs
index c8b97e5..c3e8be0 100644
--- a/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs
+++ b/Novetus/Novetus.Bootstrapper/NovetusLaunchForm.cs
@@ -15,35 +15,54 @@ namespace Novetus.Bootstrapper
private void NovetusLaunchForm_Load(object sender, EventArgs e)
{
- //use novetus font for label!!
-
GlobalFuncs.ReadInfoFile(LocalPaths.InfoPath, true, LocalPaths.LauncherPath);
+ ReadConfigValues(LocalPaths.ConfigPath);
- //dammit windows 11...
- /*GlobalFuncs.LogPrint("Loading Font...");
- try
+ if (GlobalVars.UserConfiguration.BootstrapperShowUI)
{
- PrivateFontCollection pfc = new PrivateFontCollection();
- string fontPath = LocalPaths.FixedDataDir + "\\BootstrapperFont.ttf";
- pfc.AddFontFile(fontPath);
+ //use novetus font for label!!
- foreach (var fam in pfc.Families)
+ //dammit windows 11...
+ /*GlobalFuncs.LogPrint("Loading Font...");
+ try
{
- VersionLabel.Font = new Font(fam, VersionLabel.Font.Size);
- LaunchNovetusButton.Font = new Font(fam, VersionLabel.Font.Size);
- }
- GlobalFuncs.LogPrint("Font Loaded");
- }
- catch (Exception ex)
- {
- GlobalFuncs.LogExceptions(ex);
- }*/
+ PrivateFontCollection pfc = new PrivateFontCollection();
+ string fontPath = LocalPaths.FixedDataDir + "\\BootstrapperFont.ttf";
+ pfc.AddFontFile(fontPath);
- VersionLabel.Text = GlobalVars.ProgramInformation.Version.ToUpper();
- CenterToScreen();
+ foreach (var fam in pfc.Families)
+ {
+ VersionLabel.Font = new Font(fam, VersionLabel.Font.Size);
+ LaunchNovetusButton.Font = new Font(fam, VersionLabel.Font.Size);
+ }
+ GlobalFuncs.LogPrint("Font Loaded");
+ }
+ catch (Exception ex)
+ {
+ GlobalFuncs.LogExceptions(ex);
+ }*/
+
+ VersionLabel.Text = GlobalVars.ProgramInformation.Version.ToUpper();
+ CenterToScreen();
+ }
+ else
+ {
+ LaunchNovetus();
+ }
+ }
+
+ void ReadConfigValues(string cfgpath)
+ {
+ GlobalFuncs.Config(cfgpath, false);
+ LauncherBox.Checked = !GlobalVars.UserConfiguration.BootstrapperShowUI;
}
private void LaunchNovetusButton_Click(object sender, EventArgs e)
+ {
+ LaunchNovetus();
+ }
+
+ private void LaunchNovetus()
{
LocalFuncs.LaunchApplication(LocalPaths.LauncherName);
Close();
@@ -77,5 +96,10 @@ namespace Novetus.Bootstrapper
LocalFuncs.LaunchApplication(LocalPaths.URIName);
Close();
}
+
+ private void LauncherBox_CheckedChanged(object sender, EventArgs e)
+ {
+ GlobalVars.UserConfiguration.BootstrapperShowUI = !LauncherBox.Checked;
+ }
}
}
diff --git a/Novetus/NovetusCore/Classes/FileFormat.cs b/Novetus/NovetusCore/Classes/FileFormat.cs
index 7acb5ed..afaf589 100644
--- a/Novetus/NovetusCore/Classes/FileFormat.cs
+++ b/Novetus/NovetusCore/Classes/FileFormat.cs
@@ -75,6 +75,7 @@ public class FileFormat
FirstServerLaunch = true;
NewGUI = false;
URIQuickConfigure = true;
+ BootstrapperShowUI = true;
}
public string SelectedClient { get; set; }
@@ -105,6 +106,7 @@ public class FileFormat
public bool FirstServerLaunch { get; set; }
public bool NewGUI { get; set; }
public bool URIQuickConfigure { get; set; }
+ public bool BootstrapperShowUI { get; set; }
}
#endregion
diff --git a/Novetus/NovetusCore/StorageAndFunctions/GlobalFuncs.cs b/Novetus/NovetusCore/StorageAndFunctions/GlobalFuncs.cs
index d8317ed..2e21176 100644
--- a/Novetus/NovetusCore/StorageAndFunctions/GlobalFuncs.cs
+++ b/Novetus/NovetusCore/StorageAndFunctions/GlobalFuncs.cs
@@ -254,6 +254,7 @@ public class GlobalFuncs
ini.IniWriteValue(section, "FirstServerLaunch", GlobalVars.UserConfiguration.FirstServerLaunch.ToString());
ini.IniWriteValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString());
ini.IniWriteValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString());
+ ini.IniWriteValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString());
ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write);
ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write);
@@ -273,7 +274,7 @@ public class GlobalFuncs
disablehelpmessage, discord, mappath, mapsnip,
graphics, reshade, qualitylevel, style, savebackups, altIP,
disReshadeDel, showNotifs, SB_Name, SB_Address, priority,
- firstServerLaunch, newgui, quickconfigure;
+ firstServerLaunch, newgui, quickconfigure, bootstrapper;
INIFile ini = new INIFile(cfgpath);
@@ -303,6 +304,7 @@ public class GlobalFuncs
firstServerLaunch = ini.IniReadValue(section, "FirstServerLaunch", GlobalVars.UserConfiguration.FirstServerLaunch.ToString());
newgui = ini.IniReadValue(section, "NewGUI", GlobalVars.UserConfiguration.NewGUI.ToString());
quickconfigure = ini.IniReadValue(section, "URIQuickConfigure", GlobalVars.UserConfiguration.URIQuickConfigure.ToString());
+ bootstrapper = ini.IniReadValue(section, "BootstrapperShowUI", GlobalVars.UserConfiguration.BootstrapperShowUI.ToString());
disablehelpmessage = ConfigUseOldValIfExists(ini, section, "ItemMakerDisableHelpMessage", "AssetSDKDisableHelpMessage", GlobalVars.UserConfiguration.DisabledAssetSDKHelp.ToString(), write);
savebackups = ConfigUseOldValIfExists(ini, section, "AssetLocalizerSaveBackups", "AssetSDKFixerSaveBackups", GlobalVars.UserConfiguration.AssetSDKFixerSaveBackups.ToString(), write);
@@ -347,6 +349,7 @@ public class GlobalFuncs
GlobalVars.UserConfiguration.FirstServerLaunch = ValueBool(firstServerLaunch, DefaultConfiguration.FirstServerLaunch);
GlobalVars.UserConfiguration.NewGUI = ValueBool(newgui, DefaultConfiguration.NewGUI);
GlobalVars.UserConfiguration.URIQuickConfigure = ValueBool(quickconfigure, DefaultConfiguration.URIQuickConfigure);
+ GlobalVars.UserConfiguration.BootstrapperShowUI = ValueBool(bootstrapper, DefaultConfiguration.BootstrapperShowUI);
string oldMapath = Path.GetDirectoryName(GlobalVars.UserConfiguration.MapPath);
//update the map path if the file doesn't exist and write to config.
@@ -385,6 +388,7 @@ public class GlobalFuncs
GlobalVars.PlayerTripcode = curval;
}
+#if !BASICLAUNCHER
if (!File.Exists(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization))
{
Customization(GlobalPaths.ConfigDir + "\\" + GlobalPaths.ConfigNameCustomization, true);
@@ -395,6 +399,7 @@ public class GlobalFuncs
}
ReShade(GlobalPaths.ConfigDir, "ReShade.ini", write);
+#endif
}
}
diff --git a/changelog.txt b/changelog.txt
index 57bd48d..1108520 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,6 +1,19 @@
-1.3 Snapshot v22.8272.20133.2
+1.3 Snapshot v22.8282.21847.1
+Enhancements:
+- Added the following Place Contest (August 2022) entries:
+ Ironman_45 - MW2
+- Added the ability to skip the Bootstrapper on the next Novetus launch.
+
+Fixes:
+- Fixed issues with regenerating structures in Universal - Crossroads.
+----------------------------------------------------------------------------
+1.3 Snapshot v22.8272.20133.3
Enhancements:
- Improved the Media Feature Pack/Windows Media Player installation instructions in the Dependency Installer.
+- Added the Flood Fill plugin from later versions of 2012 to 2012M.
+
+Fixes:
+- Fixed 2012M zooming out the camera upon the first player respawn.
----------------------------------------------------------------------------
1.3 Snapshot v22.8272.20133.2
Fixes:
diff --git a/scripts/batch/Novetus_dependency_installer_lite.bat b/scripts/batch/Novetus_dependency_installer_lite.bat
index a6a4598..7e448b2 100644
--- a/scripts/batch/Novetus_dependency_installer_lite.bat
+++ b/scripts/batch/Novetus_dependency_installer_lite.bat
@@ -85,11 +85,8 @@ goto REDISTINSTALLER
:mfp
CLS
-echo Please install the Media Feature Pack from Microsoft's website for your respective version of Windows.
-echo https://support.microsoft.com/en-us/topic/media-feature-pack-list-for-windows-n-editions-c1c6fffa-d052-8338-7a79-a4bb980a700a
-echo A web browser window to the site will pop up after you press a key.
-echo Note: you can check what version you are on by goting to Settings, then System, then go down to About.
-pause
-start "" https://support.microsoft.com/en-us/topic/media-feature-pack-list-for-windows-n-editions-c1c6fffa-d052-8338-7a79-a4bb980a700a
+echo Please install the Windows Media Player through Windows' "Add a feature" utility.
+echo Windows 7+: Go to the Control Panel, Programs and Features, go to "Turn Windows features on and off", and enable Windows Media Player in Media Features.
+echo Windows 10+: Go to the Settings app, Apps, Optional Features, then search "Windows Media Player", then select it and press Install.
pause
goto REDISTINSTALLER
\ No newline at end of file
diff --git a/scripts/game/2012M/CSMPFunctions.lua b/scripts/game/2012M/CSMPFunctions.lua
index da903a8..afc8178 100644
--- a/scripts/game/2012M/CSMPFunctions.lua
+++ b/scripts/game/2012M/CSMPFunctions.lua
@@ -1,4 +1,5 @@
showServerNotifications = true
+RequestingMarker=true
pcall(function() settings().Diagnostics:LegacyScriptMode() end)
pcall(function() game:GetService("ScriptContext").ScriptsDisabled = false end)
@@ -587,6 +588,7 @@ function CSServer(Port,PlayerLimit,ClientEXEMD5,LauncherMD5,ClientScriptMD5,Noti
pcall(function() dofile("rbxasset://..//..//..//addons//core//AddonLoader.lua") end)
pcall(function() _G.CSScript_PreInit("Server", "2012M") end)
pcall(function() game:SetPlaceID(-1, false) end)
+ game:GetService("ChangeHistoryService"):SetEnabled(false)
dofile("rbxasset://scripts\\cores\\StarterScriptServer.lua")
assert((type(Port)~="number" or tonumber(Port)~=nil or Port==nil),"CSRun Error: Port must be nil or a number.")
local NetworkServer=game:GetService("NetworkServer")
@@ -634,15 +636,14 @@ function CSServer(Port,PlayerLimit,ClientEXEMD5,LauncherMD5,ClientScriptMD5,Noti
game.Players:Chat("Player '" .. Player.Name .. "' joined")
end
Player:LoadCharacter()
- end
-
- Player.CharacterAdded:connect(function(pchar)
LoadSecurity(newWaitForChildSecurity(Player,"Security"),Player,game.Lighting)
newWaitForChildSecurity(Player,"Tripcode")
LoadTripcode(Player)
pcall(function() print("Player '" .. Player.Name .. "-" .. Player.userId .. "' security check success. Tripcode: '" .. Player.Tripcode.Value .. "'") end)
- LoadCharacterNew(newWaitForChildSecurity(Player,"Appearance"), pchar)
- end)
+ if (Player.Character ~= nil) then
+ LoadCharacterNew(newWaitForChildSecurity(Player,"Appearance"), Player.Character)
+ end
+ end
Player.Changed:connect(function(Property)
if (game.Lighting:findFirstChild("DisableRespawns") == nil) then
@@ -723,7 +724,6 @@ function CSConnect(UserID,ServerIP,ServerPort,PlayerName,Hat1ID,Hat2ID,Hat3ID,He
local function ConnectionAccepted(Peer,Replicator)
Replicator.Disconnection:connect(Disconnection)
- local RequestingMarker=true
game:SetMessageBrickCount()
local Marker=Replicator:SendMarker()
Marker.Received:connect(function()
diff --git a/scripts/game/2012M/cores/StarterScript.lua b/scripts/game/2012M/cores/StarterScript.lua
index 00fb3f2..91d0109 100644
--- a/scripts/game/2012M/cores/StarterScript.lua
+++ b/scripts/game/2012M/cores/StarterScript.lua
@@ -74,7 +74,7 @@ if game.CoreGui.Version >= 3 then
if game.Players.LocalPlayer.userId == 7210880 or game.Players.LocalPlayer.userId == 0 then inRightPlace = true end
--if not inRightPlace then return end -- restricting availability of backpack
-
+
-- Backpack Builder
dofile("rbxasset://scripts\\cores\\BackpackBuilder.lua")
waitForChild(screenGui,"CurrentLoadout")
diff --git a/scripts/game/2012M/libraries.rbxm b/scripts/game/2012M/libraries.rbxm
index d60a41e..c8d6dcf 100644
--- a/scripts/game/2012M/libraries.rbxm
+++ b/scripts/game/2012M/libraries.rbxm
@@ -6,11 +6,10 @@
false
Sorter
- print("Special thanks to Bitl, Carrot, iago, winsupermario1234, Khangaroo, drslicendice, coke, TheLivingBee, Raymonf, and a bunch of play - testers for help making 2011 fully stable and work. 8)")
-script.CoreDialogScripts:clone().Parent = game.Lighting
+ print("Special thanks to Bitl, Carrot, iago, winsupermario1234, Khangaroo, drslicendice, coke, TheLivingBee, Raymonf, and a bunch of play - testers for help making 2012 fully stable and work. 8)")
+script.Backpack:clone().Parent = game.StarterGui
script.ResetCommand:clone().Parent = game.Workspace
script:remove()
- true
-
@@ -33,57 +32,20180 @@ function onPlayerEntered(newPlayer)
end
game.Players.ChildAdded:connect(onPlayerEntered)
- true
- -
+
-
-
- 0
- 0
- 0
- 1
- 0
- 0
- 0
- 1
- 0
- 0
- 0
- 1
-
- CoreDialogScripts
-
[null]
- true
+ Backpack
- -
+
-
- true
+ false
- ReenableDialogScript
- wait(5)
-local dialog = script.Parent
-if dialog:IsA("Dialog") then
- dialog.InUse = false
-end
-script:Remove()
-
- true
+ BackpackBuilder
+ --rbxsig%IEUAo3Q1k4Rwb3ZcqPBum//j3+Jm/9Nv0JyCeCRWUrggWps7aG81/aPzlH9pPlMkkdsZwLsCRu6eTTrqzXn2DAJNPRs7y8akc3z91r1DP3jwomfpdT+2DBAmPk3Cdj8NXQzP6T+uEYm2kk2TW9pXonKvCgRVqXFx8J7mTr+aM1M=%
+--rbxassetid%45284430%
+local t = {}
+
+local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
+ local eventConnection = nil
+
+ --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
+ local tryConnect = function()
+ if game:IsAncestorOf(parentInstance) then
+ --Entering the world, make sure we are connected/synced
+ if not eventConnection then
+ eventConnection = instance[event]:connect(signalFunc)
+ if syncFunc then syncFunc() end
+ end
+ else
+ --Probably leaving the world, so disconnect for now
+ if eventConnection then
+ eventConnection:disconnect()
+ if removeFunc then removeFunc() end
+ end
+ end
+ end
+
+ --Hook it up to ancestryChanged signal
+ local connection = parentInstance.AncestryChanged:connect(tryConnect)
+
+ --Now connect us if we're already in the world
+ tryConnect()
+
+ return connection
+end
+
+local function getScreenGuiAncestor(instance)
+ local localInstance = instance
+ while localInstance and not localInstance:IsA("ScreenGui") do
+ localInstance = localInstance.Parent
+ end
+ return localInstance
+end
+
+local function CreateButtons(frame, buttons, yPos, ySize)
+ local buttonNum = 1
+ local buttonObjs = {}
+ for i, obj in ipairs(buttons) do
+ local button = Instance.new("TextButton")
+ button.Name = "Button" .. buttonNum
+ button.Font = Enum.Font.Arial
+ button.FontSize = Enum.FontSize.Size18
+ button.AutoButtonColor = true
+ button.Modal = true
+ if obj["Style"] then
+ button.Style = obj.Style
+ else
+ button.Style = Enum.ButtonStyle.RobloxButton
+ end
+ button.Text = obj.Text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.MouseButton1Click:connect(obj.Function)
+ button.Parent = frame
+ buttonObjs[buttonNum] = button
+
+ buttonNum = buttonNum + 1
+ end
+ local numButtons = buttonNum-1
+
+ if numButtons == 1 then
+ frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
+ elseif numButtons == 2 then
+ frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
+
+ frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
+ frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
+ elseif numButtons >= 3 then
+ local spacing = .1 / numButtons
+ local buttonSize = .9 / numButtons
+
+ buttonNum = 1
+ while buttonNum <= numButtons do
+ buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
+ buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
+ buttonNum = buttonNum + 1
+ end
+ end
+end
+
+local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
+
+ local newStep = steps - 1 --otherwise we really get one more step than we want
+ local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
+ local wholeNum, remainder = math.modf(relativePosX * newStep)
+ if remainder > 0.5 then
+ wholeNum = wholeNum + 1
+ end
+ relativePosX = wholeNum/newStep
+
+ local result = math.ceil(relativePosX * newStep)
+ if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
+ sliderPosition.Value = result + 1
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end
+
+end
+
+local function cancelSlide(areaSoak)
+ areaSoak.Visible = false
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+end
+
+t.CreateStyledMessageDialog = function(title, message, style, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0, 165)
+ frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local styleImage = Instance.new("ImageLabel")
+ styleImage.Name = "StyleImage"
+ styleImage.BackgroundTransparency = 1
+ styleImage.Position = UDim2.new(0,5,0,15)
+ if style == "error" or style == "Error" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "rbxasset://ui/error.png"
+ elseif style == "notify" or style == "Notify" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "rbxasset://ui/notify.png"
+ elseif style == "confirm" or style == "Confirm" then
+ styleImage.Size = UDim2.new(0, 74, 0, 76)
+ styleImage.Image = "rbxasset://ui/confirm.png"
+ else
+ return t.CreateMessageDialog(title,message,buttons)
+ end
+ styleImage.Parent = frame
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.TextStrokeTransparency = 0
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 80, 0, 0)
+ titleLabel.Size = UDim2.new(1, -80, 0, 40)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextStrokeTransparency = 0
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
+ messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
+
+ return frame
+end
+
+t.CreateMessageDialog = function(title, message, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0.5, 0)
+ frame.Position = UDim2.new(0.25, 0, 0.25, 0)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 0, 0, 0)
+ titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
+ messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
+
+ return frame
+end
+
+t.CreateDropDownMenu = function(items, onSelect, forRoblox)
+ local width = UDim.new(0, 100)
+ local height = UDim.new(0, 32)
+
+ local xPos = 0.055
+ local frame = Instance.new("Frame")
+ frame.Name = "DropDownMenu"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(width, height)
+
+ local dropDownMenu = Instance.new("TextButton")
+ dropDownMenu.Name = "DropDownMenuButton"
+ dropDownMenu.TextWrap = true
+ dropDownMenu.TextColor3 = Color3.new(1,1,1)
+ dropDownMenu.Text = "Choose One"
+ dropDownMenu.Font = Enum.Font.ArialBold
+ dropDownMenu.FontSize = Enum.FontSize.Size18
+ dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
+ dropDownMenu.BackgroundTransparency = 1
+ dropDownMenu.AutoButtonColor = true
+ dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ dropDownMenu.Size = UDim2.new(1,0,1,0)
+ dropDownMenu.Parent = frame
+ dropDownMenu.ZIndex = 2
+
+ local dropDownIcon = Instance.new("ImageLabel")
+ dropDownIcon.Name = "Icon"
+ dropDownIcon.Active = false
+ dropDownIcon.Image = "rbxasset://ui/dropdownicon.png"
+ dropDownIcon.BackgroundTransparency = 1
+ dropDownIcon.Size = UDim2.new(0,11,0,6)
+ dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
+ dropDownIcon.Parent = dropDownMenu
+ dropDownIcon.ZIndex = 2
+
+ local itemCount = #items
+ local dropDownItemCount = #items
+ local useScrollButtons = false
+ if dropDownItemCount > 6 then
+ useScrollButtons = true
+ dropDownItemCount = 6
+ end
+
+ local droppedDownMenu = Instance.new("TextButton")
+ droppedDownMenu.Name = "List"
+ droppedDownMenu.Text = ""
+ droppedDownMenu.BackgroundTransparency = 1
+ --droppedDownMenu.AutoButtonColor = true
+ droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ droppedDownMenu.Visible = false
+ droppedDownMenu.Active = true --Blocks clicks
+ droppedDownMenu.Position = UDim2.new(0,0,0,0)
+ droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
+ droppedDownMenu.Parent = frame
+ droppedDownMenu.ZIndex = 2
+
+ local choiceButton = Instance.new("TextButton")
+ choiceButton.Name = "ChoiceButton"
+ choiceButton.BackgroundTransparency = 1
+ choiceButton.BorderSizePixel = 0
+ choiceButton.Text = "ReplaceMe"
+ choiceButton.TextColor3 = Color3.new(1,1,1)
+ choiceButton.TextXAlignment = Enum.TextXAlignment.Left
+ choiceButton.TextYAlignment = Enum.TextYAlignment.Center
+ choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
+ choiceButton.Font = Enum.Font.Arial
+ choiceButton.FontSize = Enum.FontSize.Size18
+ if useScrollButtons then
+ choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
+ else
+ choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
+ end
+ choiceButton.TextWrap = true
+ choiceButton.ZIndex = 2
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = true
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 3
+
+ local dropDownSelected = false
+
+ local scrollUpButton
+ local scrollDownButton
+ local scrollMouseCount = 0
+
+ local setZIndex = function(baseZIndex)
+ droppedDownMenu.ZIndex = baseZIndex +1
+ if scrollUpButton then
+ scrollUpButton.ZIndex = baseZIndex + 3
+ end
+ if scrollDownButton then
+ scrollDownButton.ZIndex = baseZIndex + 3
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child.Name == "ChoiceButton" then
+ child.ZIndex = baseZIndex + 2
+ elseif child.Name == "ClickCaptureButton" then
+ child.ZIndex = baseZIndex
+ end
+ end
+ end
+ end
+
+ local scrollBarPosition = 1
+ local updateScroll = function()
+ if scrollUpButton then
+ scrollUpButton.Active = scrollBarPosition > 1
+ end
+ if scrollDownButton then
+ scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if not children then return end
+
+ local childNum = 1
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
+ obj.Visible = false
+ else
+ obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
+ obj.Visible = true
+ end
+ obj.TextColor3 = Color3.new(1,1,1)
+ obj.BackgroundTransparency = 1
+
+ childNum = childNum + 1
+ end
+ end
+ end
+ local toggleVisibility = function()
+ dropDownSelected = not dropDownSelected
+
+ areaSoak.Visible = not areaSoak.Visible
+ dropDownMenu.Visible = not dropDownSelected
+ droppedDownMenu.Visible = dropDownSelected
+ if dropDownSelected then
+ setZIndex(4)
+ else
+ setZIndex(2)
+ end
+ if useScrollButtons then
+ updateScroll()
+ end
+ end
+ droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
+
+ local updateSelection = function(text)
+ local foundItem = false
+ local children = droppedDownMenu:GetChildren()
+ local childNum = 1
+ if children then
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if obj.Text == text then
+ obj.Font = Enum.Font.ArialBold
+ foundItem = true
+ scrollBarPosition = childNum
+ else
+ obj.Font = Enum.Font.Arial
+ end
+ childNum = childNum + 1
+ end
+ end
+ end
+ if not text then
+ dropDownMenu.Text = "Choose One"
+ scrollBarPosition = 1
+ else
+ if not foundItem then
+ error("Invalid Selection Update -- " .. text)
+ end
+
+ if scrollBarPosition + dropDownItemCount > itemCount + 1 then
+ scrollBarPosition = itemCount - dropDownItemCount + 1
+ end
+
+ dropDownMenu.Text = text
+ end
+ end
+
+ local function scrollDown()
+ if scrollBarPosition + dropDownItemCount <= itemCount then
+ scrollBarPosition = scrollBarPosition + 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+ local function scrollUp()
+ if scrollBarPosition > 1 then
+ scrollBarPosition = scrollBarPosition - 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+
+ if useScrollButtons then
+ --Make some scroll buttons
+ scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+ scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
+ scrollUpButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollUp()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollUp() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ scrollUpButton.Parent = droppedDownMenu
+
+ scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+ scrollDownButton.Position = UDim2.new(1,-11,1,-11)
+ scrollDownButton.Parent = droppedDownMenu
+ scrollDownButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollDown()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollDown() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ local scrollbar = Instance.new("ImageLabel")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
+ scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
+ scrollbar.Parent = droppedDownMenu
+ end
+
+ for i,item in ipairs(items) do
+ -- needed to maintain local scope for items in event listeners below
+ local button = choiceButton:clone()
+ if forRoblox then
+ button.RobloxLocked = true
+ end
+ button.Text = item
+ button.Parent = droppedDownMenu
+ button.MouseButton1Click:connect(function()
+ --Remove Highlight
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundTransparency = 1
+
+ updateSelection(item)
+ onSelect(item)
+
+ toggleVisibility()
+ end)
+ button.MouseEnter:connect(function()
+ --Add Highlight
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ end)
+
+ button.MouseLeave:connect(function()
+ --Remove Highlight
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundTransparency = 1
+ end)
+ end
+
+ --This does the initial layout of the buttons
+ updateScroll()
+
+ frame.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(frame)
+ end
+ end)
+
+ dropDownMenu.MouseButton1Click:connect(toggleVisibility)
+ areaSoak.MouseButton1Click:connect(toggleVisibility)
+ return frame, updateSelection
+end
+
+t.CreatePropertyDropDownMenu = function(instance, property, enum)
+
+ local items = enum:GetEnumItems()
+ local names = {}
+ local nameToItem = {}
+ for i,obj in ipairs(items) do
+ names[i] = obj.Name
+ nameToItem[obj.Name] = obj
+ end
+
+ local frame
+ local updateSelection
+ frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
+
+ ScopedConnect(frame, instance, "Changed",
+ function(prop)
+ if prop == property then
+ updateSelection(instance[property].Name)
+ end
+ end,
+ function()
+ updateSelection(instance[property].Name)
+ end)
+
+ return frame
+end
+
+t.GetFontHeight = function(font, fontSize)
+ if font == nil or fontSize == nil then
+ error("Font and FontSize must be non-nil")
+ end
+
+ if font == Enum.Font.Legacy then
+ if fontSize == Enum.FontSize.Size8 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 15
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 17
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 21
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 27
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 54
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 72
+ else
+ error("Unknown FontSize")
+ end
+ elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
+ if fontSize == Enum.FontSize.Size8 then
+ return 8
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 9
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 10
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 11
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 24
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 48
+ else
+ error("Unknown FontSize")
+ end
+ else
+ error("Unknown Font " .. font)
+ end
+end
+
+local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+ for i, child in ipairs(guiObjects) do
+ if child:IsA("TextLabel") or child:IsA("TextButton") then
+ local isLabel = child:IsA("TextLabel")
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
+
+ if child.TextFits and child.TextBounds.Y < pixelsRemaining then
+ child.Visible = true
+ if isLabel then
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
+ else
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
+ end
+
+ while not child.TextFits do
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
+ end
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ else
+ child.Visible = false
+ pixelsRemaining = -1
+ end
+
+ else
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ child.Visible = (pixelsRemaining >= 0)
+ end
+ end
+end
+
+t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
+ if not frame:IsA("GuiObject") then
+ error("Frame must be a GuiObject")
+ end
+ for i, child in ipairs(guiObjects) do
+ if not child:IsA("GuiObject") then
+ error("All elements that are layed out must be of type GuiObject")
+ end
+ end
+
+ if not settingsTable then
+ settingsTable = {}
+ end
+
+ if not settingsTable["TextLabelSizePadY"] then
+ settingsTable["TextLabelSizePadY"] = 0
+ end
+ if not settingsTable["TextLabelPositionPadY"] then
+ settingsTable["TextLabelPositionPadY"] = 0
+ end
+ if not settingsTable["TextButtonSizePadY"] then
+ settingsTable["TextButtonSizePadY"] = 12
+ end
+ if not settingsTable["TextButtonPositionPadY"] then
+ settingsTable["TextButtonPositionPadY"] = 2
+ end
+
+ --Wrapper frame takes care of styled objects
+ local wrapperFrame = Instance.new("Frame")
+ wrapperFrame.Name = "WrapperFrame"
+ wrapperFrame.BackgroundTransparency = 1
+ wrapperFrame.Size = UDim2.new(1,0,1,0)
+ wrapperFrame.Parent = frame
+
+ for i, child in ipairs(guiObjects) do
+ child.Parent = wrapperFrame
+ end
+
+ local recalculate = function()
+ wait()
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(recalculate)
+
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+end
+
+
+t.CreateSlider = function(steps,width,position)
+ local sliderGui = Instance.new("Frame")
+ sliderGui.Size = UDim2.new(1,0,1,0)
+ sliderGui.BackgroundTransparency = 1
+ sliderGui.Name = "SliderGui"
+
+ local sliderSteps = Instance.new("IntValue")
+ sliderSteps.Name = "SliderSteps"
+ sliderSteps.Value = steps
+ sliderSteps.Parent = sliderGui
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = false
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 4
+
+ sliderGui.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(sliderGui)
+ end
+ end)
+
+ local sliderPosition = Instance.new("IntValue")
+ sliderPosition.Name = "SliderPosition"
+ sliderPosition.Value = 0
+ sliderPosition.Parent = sliderGui
+
+ local id = math.random(1,100)
+
+ local bar = Instance.new("TextButton")
+ bar.Text = ""
+ bar.AutoButtonColor = false
+ bar.Name = "Bar"
+ bar.BackgroundColor3 = Color3.new(0,0,0)
+ if type(width) == "number" then
+ bar.Size = UDim2.new(0,width,0,5)
+ else
+ bar.Size = UDim2.new(0,200,0,5)
+ end
+ bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
+ bar.ZIndex = 2
+ bar.Parent = sliderGui
+
+ if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
+ bar.Position = position
+ end
+
+ local slider = Instance.new("ImageButton")
+ slider.Name = "Slider"
+ slider.BackgroundTransparency = 1
+ slider.Image = "rbxasset://textures/ui/Slider.png"
+ slider.Position = UDim2.new(0,0,0.5,-10)
+ slider.Size = UDim2.new(0,20,0,20)
+ slider.ZIndex = 3
+ slider.Parent = bar
+
+ local areaSoakMouseMoveCon = nil
+
+ areaSoak.MouseLeave:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+ areaSoak.MouseButton1Up:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+
+ slider.MouseButton1Down:connect(function()
+ areaSoak.Visible = true
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+ end)
+
+ slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
+
+ sliderPosition.Changed:connect(function(prop)
+ sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
+ local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end)
+
+ bar.MouseButton1Down:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+
+ return sliderGui, sliderPosition, sliderSteps
+
+end
+
+t.CreateTrueScrollingFrame = function()
+ local lowY = nil
+ local highY = nil
+
+ local dragCon = nil
+ local upCon = nil
+
+ local internalChange = false
+
+ local descendantsChangeConMap = {}
+
+ local scrollingFrame = Instance.new("Frame")
+ scrollingFrame.Name = "ScrollingFrame"
+ scrollingFrame.Active = true
+ scrollingFrame.Size = UDim2.new(1,0,1,0)
+ scrollingFrame.ClipsDescendants = true
+
+ local controlFrame = Instance.new("Frame")
+ controlFrame.Name = "ControlFrame"
+ controlFrame.BackgroundTransparency = 1
+ controlFrame.Size = UDim2.new(0,18,1,0)
+ controlFrame.Position = UDim2.new(1,-20,0,0)
+ controlFrame.Parent = scrollingFrame
+
+ local scrollBottom = Instance.new("BoolValue")
+ scrollBottom.Value = false
+ scrollBottom.Name = "ScrollBottom"
+ scrollBottom.Parent = controlFrame
+
+ local scrollUp = Instance.new("BoolValue")
+ scrollUp.Value = false
+ scrollUp.Name = "scrollUp"
+ scrollUp.Parent = controlFrame
+
+ local scrollUpButton = Instance.new("TextButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.Text = ""
+ scrollUpButton.AutoButtonColor = false
+ scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
+ scrollUpButton.BorderColor3 = Color3.new(1,1,1)
+ scrollUpButton.BackgroundTransparency = 0.5
+ scrollUpButton.Size = UDim2.new(0,18,0,18)
+ scrollUpButton.ZIndex = 2
+ scrollUpButton.Parent = controlFrame
+ for i = 1, 6 do
+ local triFrame = Instance.new("Frame")
+ triFrame.BorderColor3 = Color3.new(1,1,1)
+ triFrame.Name = "tri" .. tostring(i)
+ triFrame.ZIndex = 3
+ triFrame.BackgroundTransparency = 0.5
+ triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
+ triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
+ triFrame.Parent = scrollUpButton
+ end
+ scrollUpButton.MouseEnter:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.1
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollUpButton.MouseLeave:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.5
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+
+ local scrollDownButton = scrollUpButton:clone()
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.Position = UDim2.new(0,0,1,-18)
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
+ end
+ scrollDownButton.MouseEnter:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.1
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollDownButton.MouseLeave:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.5
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+ scrollDownButton.Parent = controlFrame
+
+ local scrollTrack = Instance.new("Frame")
+ scrollTrack.Name = "ScrollTrack"
+ scrollTrack.BackgroundTransparency = 1
+ scrollTrack.Size = UDim2.new(0,18,1,-38)
+ scrollTrack.Position = UDim2.new(0,0,0,19)
+ scrollTrack.Parent = controlFrame
+
+ local scrollbar = Instance.new("TextButton")
+ scrollbar.BackgroundColor3 = Color3.new(0,0,0)
+ scrollbar.BorderColor3 = Color3.new(1,1,1)
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.AutoButtonColor = false
+ scrollbar.Text = ""
+ scrollbar.Active = true
+ scrollbar.Name = "ScrollBar"
+ scrollbar.ZIndex = 2
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
+ scrollbar.Position = UDim2.new(0,0,0,0)
+ scrollbar.Parent = scrollTrack
+
+ local scrollNub = Instance.new("Frame")
+ scrollNub.Name = "ScrollNub"
+ scrollNub.BorderColor3 = Color3.new(1,1,1)
+ scrollNub.Size = UDim2.new(0,10,0,0)
+ scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
+ scrollNub.ZIndex = 2
+ scrollNub.BackgroundTransparency = 0.5
+ scrollNub.Parent = scrollbar
+
+ local newNub = scrollNub:clone()
+ newNub.Position = UDim2.new(0.5,-5,0.5,-2)
+ newNub.Parent = scrollbar
+
+ local lastNub = scrollNub:clone()
+ lastNub.Position = UDim2.new(0.5,-5,0.5,2)
+ lastNub.Parent = scrollbar
+
+ scrollbar.MouseEnter:connect(function()
+ scrollbar.BackgroundTransparency = 0.1
+ scrollNub.BackgroundTransparency = 0.1
+ newNub.BackgroundTransparency = 0.1
+ lastNub.BackgroundTransparency = 0.1
+ end)
+ scrollbar.MouseLeave:connect(function()
+ scrollbar.BackgroundTransparency = 0.5
+ scrollNub.BackgroundTransparency = 0.5
+ newNub.BackgroundTransparency = 0.5
+ lastNub.BackgroundTransparency = 0.5
+ end)
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local function positionScrollBar(x,y,offset)
+ local oldPos = scrollbar.Position
+
+ if y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+
+ if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+ local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
+ if newScaleYPos + relativeSize > 1 then
+ newScaleYPos = 1 - relativeSize
+ scrollBottom.Value = true
+ scrollUp.Value = false
+ elseif newScaleYPos <= 0 then
+ newScaleYPos = 0
+ scrollUp.Value = true
+ scrollBottom.Value = false
+ else
+ scrollUp.Value = false
+ scrollBottom.Value = false
+ end
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
+
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local function drillDownSetHighLow(instance)
+ if not instance or not instance:IsA("GuiObject") then return end
+ if instance == controlFrame then return end
+ if instance:IsDescendantOf(controlFrame) then return end
+ if not instance.Visible then return end
+
+ if lowY and lowY > instance.AbsolutePosition.Y then
+ lowY = instance.AbsolutePosition.Y
+ elseif not lowY then
+ lowY = instance.AbsolutePosition.Y
+ end
+ if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ local children = instance:GetChildren()
+ for i = 1, #children do
+ drillDownSetHighLow(children[i])
+ end
+ end
+
+ local function resetHighLow()
+ local firstChildren = scrollingFrame:GetChildren()
+
+ for i = 1, #firstChildren do
+ drillDownSetHighLow(firstChildren[i])
+ end
+ end
+
+ local function recalculate()
+ internalChange = true
+
+ local percentFrame = 0
+ if scrollbar.Position.Y.Scale > 0 then
+ if scrollbar.Visible then
+ percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
+ else
+ percentFrame = 0
+ end
+ end
+ if percentFrame > 0.99 then percentFrame = 1 end
+
+ local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
+
+ local guiChildren = scrollingFrame:GetChildren()
+ for i = 1, #guiChildren do
+ if guiChildren[i] ~= controlFrame then
+ guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
+ 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
+ end
+ end
+
+ lowY = nil
+ highY = nil
+ resetHighLow()
+ internalChange = false
+ end
+
+ local function setSliderSizeAndPosition()
+ if not highY or not lowY then return end
+
+ local totalYSpan = math.abs(highY - lowY)
+ if totalYSpan == 0 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ return
+ end
+
+ local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
+ if percentShown >= 1 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+ recalculate()
+ else
+ scrollbar.Visible = true
+ scrollDownButton.Visible = true
+ scrollUpButton.Visible = true
+
+ scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
+ end
+
+ local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
+
+ if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ end
+
+ if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ end
+ end
+
+ local buttonScrollAmountPixels = 7
+ local reentrancyGuardScrollUp = false
+ local function doScrollUp()
+ if reentrancyGuardScrollUp then return end
+
+ reentrancyGuardScrollUp = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollUp = false
+ end
+
+ local reentrancyGuardScrollDown = false
+ local function doScrollDown()
+ if reentrancyGuardScrollDown then return end
+
+ reentrancyGuardScrollDown = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollDown = false
+ end
+
+ local function scrollUp(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local function scrollDown(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ scrollbar.MouseButton1Down:connect(function(x,y)
+ if scrollbar.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollbar.AbsolutePosition.y
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ local prevY = y
+ local reentrancyGuardMouseScroll = false
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ if reentrancyGuardMouseScroll then return end
+
+ reentrancyGuardMouseScroll = true
+ if positionScrollBar(x,y,mouseOffset) then
+ recalculate()
+ end
+ reentrancyGuardMouseScroll = false
+
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ local function heightCheck(instance)
+ if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ setSliderSizeAndPosition()
+ end
+
+ local function highLowRecheck()
+ local oldLowY = lowY
+ local oldHighY = highY
+ lowY = nil
+ highY = nil
+ resetHighLow()
+
+ if (lowY ~= oldLowY) or (highY ~= oldHighY) then
+ setSliderSizeAndPosition()
+ end
+ end
+
+ local function descendantChanged(this, prop)
+ if internalChange then return end
+ if not this.Visible then return end
+
+ if prop == "Size" or prop == "Position" then
+ wait()
+ highLowRecheck()
+ end
+ end
+
+ scrollingFrame.DescendantAdded:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+
+ if instance.Visible then
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end
+
+ descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
+ end)
+
+ scrollingFrame.DescendantRemoving:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+ if descendantsChangeConMap[instance] then
+ descendantsChangeConMap[instance]:disconnect()
+ descendantsChangeConMap[instance] = nil
+ end
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end)
+
+ scrollingFrame.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ if not highY or not lowY then return end
+
+ highLowRecheck()
+ setSliderSizeAndPosition()
+ end
+ end)
+
+ return scrollingFrame, controlFrame
+end
+
+t.CreateScrollingFrame = function(orderList,scrollStyle)
+ local frame = Instance.new("Frame")
+ frame.Name = "ScrollingFrame"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(1,0,1,0)
+
+ local scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+
+
+ local scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+
+ local scrollbar = Instance.new("ImageButton")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, 0, 150)
+
+ local scrollStamp = 0
+
+ local scrollDrag = Instance.new("ImageButton")
+ scrollDrag.Image = "rbxasset://ui/scrolldrag.png"
+ scrollDrag.Size = UDim2.new(1, 0, 0, 16)
+ scrollDrag.BackgroundTransparency = 1
+ scrollDrag.Name = "ScrollDrag"
+ scrollDrag.Active = true
+ scrollDrag.Parent = scrollbar
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local style = "simple"
+ if scrollStyle and tostring(scrollStyle) then
+ style = scrollStyle
+ end
+
+ local scrollPosition = 1
+ local rowSize = 0
+ local howManyDisplayed = 0
+
+ local layoutGridScrollBar = function()
+ howManyDisplayed = 0
+ local guiObjects = {}
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ if scrollPosition < 1 then scrollPosition = 1 end
+
+ local totalPixelsY = frame.AbsoluteSize.Y
+ local pixelsRemainingY = frame.AbsoluteSize.Y
+
+ local totalPixelsX = frame.AbsoluteSize.X
+
+ local xCounter = 0
+ local rowSizeCounter = 0
+ local setRowSize = true
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+
+ local currentRowY = 0
+
+ pos = scrollPosition
+ --count up from current scroll position to fill out grid
+ while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ --previous pos was the end of a row
+ if xCounter >= totalPixelsX then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ end
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+ pos = pos + 1
+ end
+ --Count wherever current row left off
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+
+ pos = scrollPosition - 1
+ xCounter = 0
+
+ --objects with varying X,Y dimensions can rarely cause minor errors
+ --rechecking every new scrollPosition is necessary to avoid 100% of errors
+
+ --count backwards from current scrollPosition to see if we can add more rows
+ while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ rowSizeCounter = rowSizeCounter + 1
+ if xCounter >= totalPixelsX then
+ rowSize = rowSizeCounter - 1
+ rowSizeCounter = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ if scrollPosition <= rowSize then
+ scrollPosition = 1
+ break
+ else
+ scrollPosition = scrollPosition - rowSize
+ end
+ currentRowY = 0
+ else
+ break
+ end
+ end
+
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+
+ pos = pos - 1
+ end
+
+ --Do check last time if pos = 0
+ if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
+ scrollPosition = 1
+ end
+
+ xCounter = 0
+ --pos = scrollPosition
+ rowSizeCounter = 0
+ setRowSize = true
+ local lastChildSize = 0
+
+ local xOffset,yOffset = 0
+ if guiObjects[1] then
+ yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
+ xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
+ end
+
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemainingY < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
+ if xCounter + child.AbsoluteSize.X >= totalPixelsX then
+ if setRowSize then
+ rowSize = rowSizeCounter - 1
+ setRowSize = false
+ end
+ xCounter = 0
+ pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
+ end
+ child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
+ xCounter = xCounter + child.AbsoluteSize.X
+ child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
+ if child.Visible then
+ howManyDisplayed = howManyDisplayed + 1
+ end
+ lastChildSize = child.AbsoluteSize
+ end
+ end
+ end
+
+ scrollUpButton.Active = (scrollPosition > 1)
+ if lastChildSize == 0 then
+ scrollDownButton.Active = false
+ else
+ scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
+ end
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+
+ local layoutSimpleScrollBar = function()
+ local guiObjects = {}
+ howManyDisplayed = 0
+
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+ while pixelsBelowScrollbar < totalPixels and pos >= 1 do
+ if pos >= scrollPosition then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ else
+ if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ if scrollPosition <= 1 then
+ scrollPosition = 1
+ break
+ else
+ --local ("Backing up ScrollPosition from -- " ..scrollPosition)
+ scrollPosition = scrollPosition - 1
+ end
+ else
+ break
+ end
+ end
+ pos = pos - 1
+ end
+
+ pos = scrollPosition
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemaining < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ if (pixelsRemaining >= 0) then
+ child.Visible = true
+ howManyDisplayed = howManyDisplayed + 1
+ else
+ child.Visible = false
+ end
+ end
+ end
+ end
+ scrollUpButton.Active = (scrollPosition > 1)
+ scrollDownButton.Active = (pixelsRemaining < 0)
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+ local moveDragger = function()
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ if not scrollDrag.Parent then return end
+
+ local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
+ if dragSizeY < 16 then dragSizeY = 16 end
+ scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
+
+ local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
+ if relativeYPos > 1 then relativeYPos = 1
+ elseif relativeYPos < 0 then relativeYPos = 0 end
+ local absYPos = 0
+
+ if relativeYPos ~= 0 then
+ absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
+ end
+
+ scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
+ end
+
+ local reentrancyGuard = false
+ local recalculate = function()
+ if reentrancyGuard then
+ return
+ end
+ reentrancyGuard = true
+ wait()
+ local success, err = nil
+ if style == "grid" then
+ success, err = pcall(function() layoutGridScrollBar() end)
+ elseif style == "simple" then
+ success, err = pcall(function() layoutSimpleScrollBar() end)
+ end
+ if not success then print(err) end
+ moveDragger()
+ reentrancyGuard = false
+ end
+
+ local doScrollUp = function()
+ scrollPosition = (scrollPosition) - rowSize
+ if scrollPosition < 1 then scrollPosition = 1 end
+ recalculate(nil)
+ end
+
+ local doScrollDown = function()
+ scrollPosition = (scrollPosition) + rowSize
+ recalculate(nil)
+ end
+
+ local scrollUp = function(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local scrollDown = function(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local y = 0
+ scrollDrag.MouseButton1Down:connect(function(x,y)
+ if scrollDrag.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollDrag.AbsolutePosition.y
+ local dragCon
+ local upCon
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ local barAbsPos = scrollbar.AbsolutePosition.y
+ local barAbsSize = scrollbar.AbsoluteSize.y
+
+ local dragAbsSize = scrollDrag.AbsoluteSize.y
+ local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
+ y = y - mouseOffset
+ y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
+ y = y - barAbsPos
+
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ local doublePercent = y/(barAbsSize-dragAbsSize)
+ local rowDiff = rowSize
+ local totalScrollCount = guiObjects - (howManyDisplayed - 1)
+ local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
+ if newScrollPosition < scrollPosition then
+ rowDiff = -rowDiff
+ end
+
+ if newScrollPosition < 1 then
+ newScrollPosition = 1
+ end
+
+ scrollPosition = newScrollPosition
+ recalculate(nil)
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollbar.MouseButton1Down:connect(
+ function(x,y)
+ if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
+ scrollDown(y)
+ elseif y < (scrollDrag.AbsolutePosition.y) then
+ scrollUp(y)
+ end
+ end)
+
+
+ frame.ChildAdded:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.ChildRemoved:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(function() recalculate(nil) end)
+
+ return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
+end
+local function binaryGrow(min, max, fits)
+ if min > max then
+ return min
+ end
+ local biggestLegal = min
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
+ biggestLegal = mid
+
+ --Try growing
+ min = mid + 1
+ else
+ --Doesn't fit, shrink
+ max = mid - 1
+ end
+ end
+ return biggestLegal
+end
+
+
+local function binaryShrink(min, max, fits)
+ if min > max then
+ return min
+ end
+ local smallestLegal = max
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
+ smallestLegal = mid
+
+ --It fits, shrink
+ max = mid - 1
+ else
+ --Doesn't fit, grow
+ min = mid + 1
+ end
+ end
+ return smallestLegal
+end
+
+
+local function getGuiOwner(instance)
+ while instance ~= nil do
+ if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
+ return instance
+ end
+ instance = instance.Parent
+ end
+ return nil
+end
+
+t.AutoTruncateTextObject = function(textLabel)
+ local text = textLabel.Text
+
+ local fullLabel = textLabel:Clone()
+ fullLabel.Name = "Full" .. textLabel.Name
+ fullLabel.BorderSizePixel = 0
+ fullLabel.BackgroundTransparency = 0
+ fullLabel.Text = text
+ fullLabel.TextXAlignment = Enum.TextXAlignment.Center
+ fullLabel.Position = UDim2.new(0,-3,0,0)
+ fullLabel.Size = UDim2.new(0,100,1,0)
+ fullLabel.Visible = false
+ fullLabel.Parent = textLabel
+
+ local shortText = nil
+ local mouseEnterConnection = nil
+ local mouseLeaveConnection= nil
+
+ local checkForResize = function()
+ if getGuiOwner(textLabel) == nil then
+ return
+ end
+ textLabel.Text = text
+ if textLabel.TextFits then
+ --Tear down the rollover if it is active
+ if mouseEnterConnection then
+ mouseEnterConnection:disconnect()
+ mouseEnterConnection = nil
+ end
+ if mouseLeaveConnection then
+ mouseLeaveConnection:disconnect()
+ mouseLeaveConnection = nil
+ end
+ else
+ local len = string.len(text)
+ textLabel.Text = text .. "~"
+
+ --Shrink the text
+ local textSize = binaryGrow(0, len,
+ function(pos)
+ if pos == 0 then
+ textLabel.Text = "~"
+ else
+ textLabel.Text = string.sub(text, 1, pos) .. "~"
+ end
+ return textLabel.TextFits
+ end)
+ shortText = string.sub(text, 1, textSize) .. "~"
+ textLabel.Text = shortText
+
+ --Make sure the fullLabel fits
+ if not fullLabel.TextFits then
+ --Already too small, grow it really bit to start
+ fullLabel.Size = UDim2.new(0, 10000, 1, 0)
+ end
+
+ --Okay, now try to binary shrink it back down
+ local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
+ function(size)
+ fullLabel.Size = UDim2.new(0, size, 1, 0)
+ return fullLabel.TextFits
+ end)
+ fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
+
+ --Now setup the rollover effects, if they are currently off
+ if mouseEnterConnection == nil then
+ mouseEnterConnection = textLabel.MouseEnter:connect(
+ function()
+ fullLabel.ZIndex = textLabel.ZIndex + 1
+ fullLabel.Visible = true
+ --textLabel.Text = ""
+ end)
+ end
+ if mouseLeaveConnection == nil then
+ mouseLeaveConnection = textLabel.MouseLeave:connect(
+ function()
+ fullLabel.Visible = false
+ --textLabel.Text = shortText
+ end)
+ end
+ end
+ end
+ textLabel.AncestryChanged:connect(checkForResize)
+ textLabel.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ checkForResize()
+ end
+ end)
+
+ checkForResize()
+
+ local function changeText(newText)
+ text = newText
+ fullLabel.Text = text
+ checkForResize()
+ end
+
+ return textLabel, changeText
+end
+
+local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
+ if fromPage then
+ fromPage.Visible = false
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = fromPage.Size
+ transitionFrame.Position = fromPage.Position
+ end
+ else
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
+ transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
+ end
+ end
+ transitionFrame.Visible = true
+ currentPageValue.Value = nil
+
+ local newsize, newPosition
+ if toPage then
+ --Make it visible so it resizes
+ toPage.Visible = true
+
+ newSize = toPage.Size
+ newPosition = toPage.Position
+
+ toPage.Visible = false
+ else
+ newSize = UDim2.new(0.0,50,0.0,50)
+ newPosition = UDim2.new(0.5,-25,0.5,-25)
+ end
+ transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
+ function(state)
+ if state == Enum.TweenStatus.Completed then
+ transitionFrame.Visible = false
+ if toPage then
+ toPage.Visible = true
+ currentPageValue.Value = toPage
+ end
+ end
+ end)
+end
+
+t.CreateTutorial = function(name, tutorialKey, createButtons)
+ local frame = Instance.new("Frame")
+ frame.Name = "Tutorial-" .. name
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+
+ local transitionFrame = Instance.new("Frame")
+ transitionFrame.Name = "TransitionFrame"
+ transitionFrame.Style = Enum.FrameStyle.RobloxRound
+ transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ transitionFrame.Visible = false
+ transitionFrame.Parent = frame
+
+ local currentPageValue = Instance.new("ObjectValue")
+ currentPageValue.Name = "CurrentTutorialPage"
+ currentPageValue.Value = nil
+ currentPageValue.Parent = frame
+
+ local boolValue = Instance.new("BoolValue")
+ boolValue.Name = "Buttons"
+ boolValue.Value = createButtons
+ boolValue.Parent = frame
+
+ local pages = Instance.new("Frame")
+ pages.Name = "Pages"
+ pages.BackgroundTransparency = 1
+ pages.Size = UDim2.new(1,0,1,0)
+ pages.Parent = frame
+
+ local function getVisiblePageAndHideOthers()
+ local visiblePage = nil
+ local children = pages:GetChildren()
+ if children then
+ for i,child in ipairs(children) do
+ if child.Visible then
+ if visiblePage then
+ child.Visible = false
+ else
+ visiblePage = child
+ end
+ end
+ end
+ end
+ return visiblePage
+ end
+
+ local showTutorial = function(alwaysShow)
+ if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
+ print("Showing tutorial-",tutorialKey)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ local firstPage = pages:FindFirstChild("TutorialPage1")
+ if firstPage then
+ TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
+ else
+ error("Could not find TutorialPage1")
+ end
+ end
+ end
+
+ local dismissTutorial = function()
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ if currentTutorialPage then
+ TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
+ end
+
+ UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
+ end
+
+ local gotoPage = function(pageNum)
+ local page = pages:FindFirstChild("TutorialPage" .. pageNum)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+ TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
+ end
+
+ return frame, showTutorial, dismissTutorial, gotoPage
+end
+
+local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
+ local frame = Instance.new("Frame")
+ frame.Name = "TutorialPage"
+ frame.Style = Enum.FrameStyle.RobloxRound
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ frame.Visible = false
+
+ local frameHeader = Instance.new("TextLabel")
+ frameHeader.Name = "Header"
+ frameHeader.Text = name
+ frameHeader.BackgroundTransparency = 1
+ frameHeader.FontSize = Enum.FontSize.Size24
+ frameHeader.Font = Enum.Font.ArialBold
+ frameHeader.TextColor3 = Color3.new(1,1,1)
+ frameHeader.TextXAlignment = Enum.TextXAlignment.Center
+ frameHeader.TextWrap = true
+ frameHeader.Size = UDim2.new(1,-55, 0, 22)
+ frameHeader.Position = UDim2.new(0,0,0,0)
+ frameHeader.Parent = frame
+
+ local skipButton = Instance.new("ImageButton")
+ skipButton.Name = "SkipButton"
+ skipButton.AutoButtonColor = false
+ skipButton.BackgroundTransparency = 1
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ skipButton.MouseButton1Click:connect(function()
+ skipTutorial()
+ end)
+ skipButton.MouseEnter:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
+ end)
+ skipButton.MouseLeave:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ end)
+ skipButton.Size = UDim2.new(0, 25, 0, 25)
+ skipButton.Position = UDim2.new(1, -25, 0, 0)
+ skipButton.Parent = frame
+
+
+ if giveDoneButton then
+ local doneButton = Instance.new("TextButton")
+ doneButton.Name = "DoneButton"
+ doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ doneButton.Text = "Done"
+ doneButton.TextColor3 = Color3.new(1,1,1)
+ doneButton.Font = Enum.Font.ArialBold
+ doneButton.FontSize = Enum.FontSize.Size18
+ doneButton.Size = UDim2.new(0,100,0,50)
+ doneButton.Position = UDim2.new(0.5,-50,1,-50)
+
+ if skipTutorial then
+ doneButton.MouseButton1Click:connect(function() skipTutorial() end)
+ end
+
+ doneButton.Parent = frame
+ end
+
+ local innerFrame = Instance.new("Frame")
+ innerFrame.Name = "ContentFrame"
+ innerFrame.BackgroundTransparency = 1
+ innerFrame.Position = UDim2.new(0,0,0,25)
+ innerFrame.Parent = frame
+
+ local nextButton = Instance.new("TextButton")
+ nextButton.Name = "NextButton"
+ nextButton.Text = "Next"
+ nextButton.TextColor3 = Color3.new(1,1,1)
+ nextButton.Font = Enum.Font.Arial
+ nextButton.FontSize = Enum.FontSize.Size18
+ nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ nextButton.Size = UDim2.new(0,80, 0, 32)
+ nextButton.Position = UDim2.new(0.5, 5, 1, -32)
+ nextButton.Active = false
+ nextButton.Visible = false
+ nextButton.Parent = frame
+
+ local prevButton = Instance.new("TextButton")
+ prevButton.Name = "PrevButton"
+ prevButton.Text = "Previous"
+ prevButton.TextColor3 = Color3.new(1,1,1)
+ prevButton.Font = Enum.Font.Arial
+ prevButton.FontSize = Enum.FontSize.Size18
+ prevButton.Style = Enum.ButtonStyle.RobloxButton
+ prevButton.Size = UDim2.new(0,80, 0, 32)
+ prevButton.Position = UDim2.new(0.5, -85, 1, -32)
+ prevButton.Active = false
+ prevButton.Visible = false
+ prevButton.Parent = frame
+
+ if giveDoneButton then
+ innerFrame.Size = UDim2.new(1,0,1,-75)
+ else
+ innerFrame.Size = UDim2.new(1,0,1,-22)
+ end
+
+ local parentConnection = nil
+
+ local function basicHandleResize()
+ if frame.Visible and frame.Parent then
+ local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
+ handleResize(200,maxSize)
+ end
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "Parent" then
+ if parentConnection ~= nil then
+ parentConnection:disconnect()
+ parentConnection = nil
+ end
+ if frame.Parent and frame.Parent:IsA("GuiObject") then
+ parentConnection = frame.Parent.Changed:connect(
+ function(parentProp)
+ if parentProp == "AbsoluteSize" then
+ wait()
+ basicHandleResize()
+ end
+ end)
+ basicHandleResize()
+ end
+ end
+
+ if prop == "Visible" then
+ basicHandleResize()
+ end
+ end)
+
+ return frame, innerFrame
+end
+
+t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
+ local frame = nil
+ local contentFrame = nil
+
+ local textLabel = Instance.new("TextLabel")
+ textLabel.BackgroundTransparency = 1
+ textLabel.TextColor3 = Color3.new(1,1,1)
+ textLabel.Text = text
+ textLabel.TextWrap = true
+ textLabel.TextXAlignment = Enum.TextXAlignment.Left
+ textLabel.TextYAlignment = Enum.TextYAlignment.Center
+ textLabel.Font = Enum.Font.Arial
+ textLabel.FontSize = Enum.FontSize.Size14
+ textLabel.Size = UDim2.new(1,0,1,0)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ frame.Size = UDim2.new(0, size, 0, size)
+ return textLabel.TextFits
+ end)
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
+ textLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
+ local frame = nil
+ local contentFrame = nil
+
+ local imageLabel = Instance.new("ImageLabel")
+ imageLabel.BackgroundTransparency = 1
+ imageLabel.Image = imageAsset
+ imageLabel.Size = UDim2.new(0,x,0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ return size >= x and size >= y
+ end)
+ if size >= x and size >= y then
+ imageLabel.Size = UDim2.new(0,x, 0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
+ else
+ if x > y then
+ --X is limiter, so
+ imageLabel.Size = UDim2.new(1,0,y/x,0)
+ imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
+ else
+ --Y is limiter
+ imageLabel.Size = UDim2.new(x/y,0,1, 0)
+ imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
+ end
+ end
+ size = size + 50
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
+ imageLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.AddTutorialPage = function(tutorial, tutorialPage)
+ local transitionFrame = tutorial.TransitionFrame
+ local currentPageValue = tutorial.CurrentTutorialPage
+
+ if not tutorial.Buttons.Value then
+ tutorialPage.NextButton.Parent = nil
+ tutorialPage.PrevButton.Parent = nil
+ end
+
+ local children = tutorial.Pages:GetChildren()
+ if children and #children > 0 then
+ tutorialPage.Name = "TutorialPage" .. (#children+1)
+ local previousPage = children[#children]
+ if not previousPage:IsA("GuiObject") then
+ error("All elements under Pages must be GuiObjects")
+ end
+
+ if tutorial.Buttons.Value then
+ if previousPage.NextButton.Active then
+ error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
+ end
+ previousPage.NextButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
+ end)
+ previousPage.NextButton.Active = true
+ previousPage.NextButton.Visible = true
+
+ if tutorialPage.PrevButton.Active then
+ error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
+ end
+ tutorialPage.PrevButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
+ end)
+ tutorialPage.PrevButton.Active = true
+ tutorialPage.PrevButton.Visible = true
+ end
+
+ tutorialPage.Parent = tutorial.Pages
+ else
+ --First child
+ tutorialPage.Name = "TutorialPage1"
+ tutorialPage.Parent = tutorial.Pages
+ end
+end
+
+t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
+
+ if not userIdsForSets then
+ error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
+ end
+ if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
+ error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
+ end
+ if not objectSelected then
+ error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
+ end
+ if type(objectSelected) ~= "function" then
+ error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
+ end
+ if dialogClosed and type(dialogClosed) ~= "function" then
+ error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
+ end
+
+ if showAdminCategories == nil then -- by default, don't show beta sets
+ showAdminCategories = false
+ end
+
+ local arrayPosition = 1
+ local insertButtons = {}
+ local insertButtonCons = {}
+ local contents = nil
+ local setGui = nil
+
+ -- used for water selections
+ local waterForceDirection = "NegX"
+ local waterForce = "None"
+ local waterGui, waterTypeChangedEvent = nil
+
+ local Data = {}
+ Data.CurrentCategory = nil
+ Data.Category = {}
+ local SetCache = {}
+
+ local userCategoryButtons = nil
+
+ local buttonWidth = 64
+ local buttonHeight = buttonWidth
+
+ local SmallThumbnailUrl = nil
+ local LargeThumbnailUrl = nil
+ local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
+
+ if useAssetVersionId then
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
+ else
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
+ end
+
+ local function drillDownSetZIndex(parent, index)
+ local children = parent:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("GuiObject") then
+ children[i].ZIndex = index
+ end
+ drillDownSetZIndex(children[i], index)
+ end
+ end
+
+ -- for terrain stamping
+ local currTerrainDropDownFrame = nil
+ local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
+ local terrainShapeMap = {}
+ for i = 1, #terrainShapes do
+ terrainShapeMap[terrainShapes[i]] = i - 1
+ end
+ terrainShapeMap[terrainShapes[#terrainShapes]] = 6
+
+ local function createWaterGui()
+ local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
+ local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
+
+ local waterFrame = Instance.new("Frame")
+ waterFrame.Name = "WaterFrame"
+ waterFrame.Style = Enum.FrameStyle.RobloxSquare
+ waterFrame.Size = UDim2.new(0,150,0,110)
+ waterFrame.Visible = false
+
+ local waterForceLabel = Instance.new("TextLabel")
+ waterForceLabel.Name = "WaterForceLabel"
+ waterForceLabel.BackgroundTransparency = 1
+ waterForceLabel.Size = UDim2.new(1,0,0,12)
+ waterForceLabel.Font = Enum.Font.ArialBold
+ waterForceLabel.FontSize = Enum.FontSize.Size12
+ waterForceLabel.TextColor3 = Color3.new(1,1,1)
+ waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
+ waterForceLabel.Text = "Water Force"
+ waterForceLabel.Parent = waterFrame
+
+ local waterForceDirLabel = waterForceLabel:Clone()
+ waterForceDirLabel.Name = "WaterForceDirectionLabel"
+ waterForceDirLabel.Text = "Water Force Direction"
+ waterForceDirLabel.Position = UDim2.new(0,0,0,50)
+ waterForceDirLabel.Parent = waterFrame
+
+ local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
+ waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
+
+ local waterForceDirectionSelectedFunc = function(newForceDirection)
+ waterForceDirection = newForceDirection
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+ local waterForceSelectedFunc = function(newForce)
+ waterForce = newForce
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+
+ local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
+ waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
+ forceWaterDirectionSelection("NegX")
+ waterForceDirectionDropDown.Parent = waterForceDirLabel
+
+ local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
+ forceWaterForceSelection("None")
+ waterForceDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDropDown.Position = UDim2.new(0,0,1,3)
+ waterForceDropDown.Parent = waterForceLabel
+
+ return waterFrame, waterTypeChangedEvent
+ end
+
+ -- Helper Function that contructs gui elements
+ local function createSetGui()
+
+ local setGui = Instance.new("ScreenGui")
+ setGui.Name = "SetGui"
+
+ local setPanel = Instance.new("Frame")
+ setPanel.Name = "SetPanel"
+ setPanel.Active = true
+ setPanel.BackgroundTransparency = 1
+ if position then
+ setPanel.Position = position
+ else
+ setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
+ end
+ if size then
+ setPanel.Size = size
+ else
+ setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
+ end
+ setPanel.Style = Enum.FrameStyle.RobloxRound
+ setPanel.ZIndex = 6
+ setPanel.Parent = setGui
+
+ -- Children of SetPanel
+ local itemPreview = Instance.new("Frame")
+ itemPreview.Name = "ItemPreview"
+ itemPreview.BackgroundTransparency = 1
+ itemPreview.Position = UDim2.new(0.8,5,0.085,0)
+ itemPreview.Size = UDim2.new(0.21,0,0.9,0)
+ itemPreview.ZIndex = 6
+ itemPreview.Parent = setPanel
+
+ -- Children of ItemPreview
+ local textPanel = Instance.new("Frame")
+ textPanel.Name = "TextPanel"
+ textPanel.BackgroundTransparency = 1
+ textPanel.Position = UDim2.new(0,0,0.45,0)
+ textPanel.Size = UDim2.new(1,0,0.55,0)
+ textPanel.ZIndex = 6
+ textPanel.Parent = itemPreview
+
+ -- Children of TextPanel
+ local rolloverText = Instance.new("TextLabel")
+ rolloverText.Name = "RolloverText"
+ rolloverText.BackgroundTransparency = 1
+ rolloverText.Size = UDim2.new(1,0,0,48)
+ rolloverText.ZIndex = 6
+ rolloverText.Font = Enum.Font.ArialBold
+ rolloverText.FontSize = Enum.FontSize.Size24
+ rolloverText.Text = ""
+ rolloverText.TextColor3 = Color3.new(1,1,1)
+ rolloverText.TextWrap = true
+ rolloverText.TextXAlignment = Enum.TextXAlignment.Left
+ rolloverText.TextYAlignment = Enum.TextYAlignment.Top
+ rolloverText.Parent = textPanel
+
+ local largePreview = Instance.new("ImageLabel")
+ largePreview.Name = "LargePreview"
+ largePreview.BackgroundTransparency = 1
+ largePreview.Image = ""
+ largePreview.Size = UDim2.new(1,0,0,170)
+ largePreview.ZIndex = 6
+ largePreview.Parent = itemPreview
+
+ local sets = Instance.new("Frame")
+ sets.Name = "Sets"
+ sets.BackgroundTransparency = 1
+ sets.Position = UDim2.new(0,0,0,5)
+ sets.Size = UDim2.new(0.23,0,1,-5)
+ sets.ZIndex = 6
+ sets.Parent = setPanel
+
+ -- Children of Sets
+ local line = Instance.new("Frame")
+ line.Name = "Line"
+ line.BackgroundColor3 = Color3.new(1,1,1)
+ line.BackgroundTransparency = 0.7
+ line.BorderSizePixel = 0
+ line.Position = UDim2.new(1,-3,0.06,0)
+ line.Size = UDim2.new(0,3,0.9,0)
+ line.ZIndex = 6
+ line.Parent = sets
+
+ local setsLists, controlFrame = t.CreateTrueScrollingFrame()
+ setsLists.Size = UDim2.new(1,-6,0.94,0)
+ setsLists.Position = UDim2.new(0,0,0.06,0)
+ setsLists.BackgroundTransparency = 1
+ setsLists.Name = "SetsLists"
+ setsLists.ZIndex = 6
+ setsLists.Parent = sets
+ drillDownSetZIndex(controlFrame, 7)
+
+ local setsHeader = Instance.new("TextLabel")
+ setsHeader.Name = "SetsHeader"
+ setsHeader.BackgroundTransparency = 1
+ setsHeader.Size = UDim2.new(0,47,0,24)
+ setsHeader.ZIndex = 6
+ setsHeader.Font = Enum.Font.ArialBold
+ setsHeader.FontSize = Enum.FontSize.Size24
+ setsHeader.Text = "Sets"
+ setsHeader.TextColor3 = Color3.new(1,1,1)
+ setsHeader.TextXAlignment = Enum.TextXAlignment.Left
+ setsHeader.TextYAlignment = Enum.TextYAlignment.Top
+ setsHeader.Parent = sets
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(1,-32,0,-2)
+ cancelButton.Size = UDim2.new(0,34,0,34)
+ cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ cancelButton.ZIndex = 6
+ cancelButton.Text = ""
+ cancelButton.Modal = true
+ cancelButton.Parent = setPanel
+
+ -- Children of Cancel Button
+ local cancelImage = Instance.new("ImageLabel")
+ cancelImage.Name = "CancelImage"
+ cancelImage.BackgroundTransparency = 1
+ cancelImage.Image = "rbxasset://ui/cancel.png"
+ cancelImage.Position = UDim2.new(0,-2,0,-2)
+ cancelImage.Size = UDim2.new(0,16,0,16)
+ cancelImage.ZIndex = 6
+ cancelImage.Parent = cancelButton
+
+ return setGui
+ end
+
+ local function createSetButton(text)
+ local setButton = Instance.new("TextButton")
+
+ if text then setButton.Text = text
+ else setButton.Text = "" end
+
+ setButton.AutoButtonColor = false
+ setButton.BackgroundTransparency = 1
+ setButton.BackgroundColor3 = Color3.new(1,1,1)
+ setButton.BorderSizePixel = 0
+ setButton.Size = UDim2.new(1,-5,0,18)
+ setButton.ZIndex = 6
+ setButton.Visible = false
+ setButton.Font = Enum.Font.Arial
+ setButton.FontSize = Enum.FontSize.Size18
+ setButton.TextColor3 = Color3.new(1,1,1)
+ setButton.TextXAlignment = Enum.TextXAlignment.Left
+
+ return setButton
+ end
+
+ local function buildSetButton(name, setId, setImageId, i, count)
+ local button = createSetButton(name)
+ button.Text = name
+ button.Name = "SetButton"
+ button.Visible = true
+
+ local setValue = Instance.new("IntValue")
+ setValue.Name = "SetId"
+ setValue.Value = setId
+ setValue.Parent = button
+
+ local setName = Instance.new("StringValue")
+ setName.Name = "SetName"
+ setName.Value = name
+ setName.Parent = button
+
+ return button
+ end
+
+ local function processCategory(sets)
+ local setButtons = {}
+ local numSkipped = 0
+ for i = 1, #sets do
+ if not showAdminCategories and sets[i].Name == "Beta" then
+ numSkipped = numSkipped + 1
+ else
+ setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
+ end
+ end
+ return setButtons
+ end
+
+ local function handleResize()
+ wait() -- neccessary to insure heartbeat happened
+
+ local itemPreview = setGui.SetPanel.ItemPreview
+
+ itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
+ itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
+ itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
+ itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
+ end
+
+ local function makeInsertAssetButton()
+ local insertAssetButtonExample = Instance.new("Frame")
+ insertAssetButtonExample.Name = "InsertAssetButtonExample"
+ insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
+ insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
+ insertAssetButtonExample.BackgroundTransparency = 1
+ insertAssetButtonExample.ZIndex = 6
+ insertAssetButtonExample.Visible = false
+
+ local assetId = Instance.new("IntValue")
+ assetId.Name = "AssetId"
+ assetId.Value = 0
+ assetId.Parent = insertAssetButtonExample
+
+ local assetName = Instance.new("StringValue")
+ assetName.Name = "AssetName"
+ assetName.Value = ""
+ assetName.Parent = insertAssetButtonExample
+
+ local button = Instance.new("TextButton")
+ button.Name = "Button"
+ button.Text = ""
+ button.Style = Enum.ButtonStyle.RobloxButton
+ button.Position = UDim2.new(0.025,0,0.025,0)
+ button.Size = UDim2.new(0.95,0,0.95,0)
+ button.ZIndex = 6
+ button.Parent = insertAssetButtonExample
+
+ local buttonImage = Instance.new("ImageLabel")
+ buttonImage.Name = "ButtonImage"
+ buttonImage.Image = ""
+ buttonImage.Position = UDim2.new(0,-7,0,-7)
+ buttonImage.Size = UDim2.new(1,14,1,14)
+ buttonImage.BackgroundTransparency = 1
+ buttonImage.ZIndex = 7
+ buttonImage.Parent = button
+
+ local configIcon = buttonImage:clone()
+ configIcon.Name = "ConfigIcon"
+ configIcon.Visible = false
+ configIcon.Position = UDim2.new(1,-23,1,-24)
+ configIcon.Size = UDim2.new(0,16,0,16)
+ configIcon.Image = ""
+ configIcon.ZIndex = 6
+ configIcon.Parent = insertAssetButtonExample
+
+ return insertAssetButtonExample
+ end
+
+ local function showLargePreview(insertButton)
+ if insertButton:FindFirstChild("AssetId") then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
+ setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
+ end)
+ end
+ if insertButton:FindFirstChild("AssetName") then
+ setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
+ end
+ end
+
+ local function selectTerrainShape(shape)
+ if currTerrainDropDownFrame then
+ objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
+ end
+ end
+
+ local function createTerrainTypeButton(name, parent)
+ local dropDownTextButton = Instance.new("TextButton")
+ dropDownTextButton.Name = name .. "Button"
+ dropDownTextButton.Font = Enum.Font.ArialBold
+ dropDownTextButton.FontSize = Enum.FontSize.Size14
+ dropDownTextButton.BorderSizePixel = 0
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ dropDownTextButton.Text = name
+ dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.ZIndex = parent.ZIndex + 1
+ dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
+ dropDownTextButton.Position = UDim2.new(0,1,0,0)
+
+ dropDownTextButton.MouseEnter:connect(function()
+ dropDownTextButton.BackgroundTransparency = 0
+ dropDownTextButton.TextColor3 = Color3.new(0,0,0)
+ end)
+
+ dropDownTextButton.MouseLeave:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ end)
+
+ dropDownTextButton.MouseButton1Click:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
+ dropDownTextButton.Parent.Visible = false
+ end
+ selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
+ end)
+
+ return dropDownTextButton
+ end
+
+ local function createTerrainDropDownMenu(zIndex)
+ local dropDown = Instance.new("Frame")
+ dropDown.Name = "TerrainDropDown"
+ dropDown.BackgroundColor3 = Color3.new(0,0,0)
+ dropDown.BorderColor3 = Color3.new(1,0,0)
+ dropDown.Size = UDim2.new(0,200,0,0)
+ dropDown.Visible = false
+ dropDown.ZIndex = zIndex
+ dropDown.Parent = setGui
+
+ for i = 1, #terrainShapes do
+ local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
+ shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
+ shapeButton.Parent = dropDown
+ dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
+ end
+
+ dropDown.MouseLeave:connect(function()
+ dropDown.Visible = false
+ end)
+ end
+
+
+ local function createDropDownMenuButton(parent)
+ local dropDownButton = Instance.new("ImageButton")
+ dropDownButton.Name = "DropDownButton"
+ dropDownButton.Image = "rbxasset://ui/dropdownbutton.png"
+ dropDownButton.BackgroundTransparency = 1
+ dropDownButton.Size = UDim2.new(0,16,0,16)
+ dropDownButton.Position = UDim2.new(1,-24,0,6)
+ dropDownButton.ZIndex = parent.ZIndex + 2
+ dropDownButton.Parent = parent
+
+ if not setGui:FindFirstChild("TerrainDropDown") then
+ createTerrainDropDownMenu(8)
+ end
+
+ dropDownButton.MouseButton1Click:connect(function()
+ setGui.TerrainDropDown.Visible = true
+ setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
+ currTerrainDropDownFrame = parent
+ end)
+ end
+
+ local function buildInsertButton()
+ local insertButton = makeInsertAssetButton()
+ insertButton.Name = "InsertAssetButton"
+ insertButton.Visible = true
+
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ createDropDownMenuButton(insertButton)
+ end
+
+ local lastEnter = nil
+ local mouseEnterCon = insertButton.MouseEnter:connect(function()
+ lastEnter = insertButton
+ delay(0.1,function()
+ if lastEnter == insertButton then
+ showLargePreview(insertButton)
+ end
+ end)
+ end)
+ return insertButton, mouseEnterCon
+ end
+
+ local function realignButtonGrid(columns)
+ local x = 0
+ local y = 0
+ for i = 1, #insertButtons do
+ insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
+ x = x + 1
+ if x >= columns then
+ x = 0
+ y = y + 1
+ end
+ end
+ end
+
+ local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
+ if visible then
+ insertFrame.AssetName.Value = name
+ insertFrame.AssetId.Value = assetId
+ local newImageUrl = SmallThumbnailUrl .. assetId
+ if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
+ insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
+ end)
+ end
+ table.insert(insertButtonCons,
+ insertFrame.Button.MouseButton1Click:connect(function()
+ -- special case for water, show water selection gui
+ local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
+ waterGui.Visible = isWaterSelected
+ if isWaterSelected then
+ objectSelected(name, tonumber(assetId), nil)
+ else
+ objectSelected(name, tonumber(assetId))
+ end
+ end)
+ )
+ insertFrame.Visible = true
+ else
+ insertFrame.Visible = false
+ end
+ end
+
+ local function loadSectionOfItems(setGui, rows, columns)
+ local pageSize = rows * columns
+
+ if arrayPosition > #contents then return end
+
+ local origArrayPos = arrayPosition
+
+ local yCopy = 0
+ for i = 1, pageSize + 1 do
+ if arrayPosition >= #contents + 1 then
+ break
+ end
+
+ local buttonCon
+ insertButtons[arrayPosition], buttonCon = buildInsertButton()
+ table.insert(insertButtonCons,buttonCon)
+ insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
+ arrayPosition = arrayPosition + 1
+ end
+ realignButtonGrid(columns)
+
+ local indexCopy = origArrayPos
+ for index = origArrayPos, arrayPosition do
+ if insertButtons[index] then
+ if contents[index] then
+
+ -- we don't want water to have a drop down button
+ if contents[index].Name == "Water" then
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
+ end
+ end
+
+ local assetId
+ if useAssetVersionId then
+ assetId = contents[index].AssetVersionId
+ else
+ assetId = contents[index].AssetId
+ end
+ setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
+ else
+ break
+ end
+ else
+ break
+ end
+ indexCopy = index
+ end
+ end
+
+ local function setSetIndex()
+ Data.Category[Data.CurrentCategory].Index = 0
+
+ rows = 7
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ contents = Data.Category[Data.CurrentCategory].Contents
+ if contents then
+ -- remove our buttons and their connections
+ for i = 1, #insertButtons do
+ insertButtons[i]:remove()
+ end
+ for i = 1, #insertButtonCons do
+ if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
+ end
+ insertButtonCons = {}
+ insertButtons = {}
+
+ arrayPosition = 1
+ loadSectionOfItems(setGui, rows, columns)
+ end
+ end
+
+ local function selectSet(button, setName, setId, setIndex)
+ if button and Data.Category[Data.CurrentCategory] ~= nil then
+ if button ~= Data.Category[Data.CurrentCategory].Button then
+ Data.Category[Data.CurrentCategory].Button = button
+
+ if SetCache[setId] == nil then
+ SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
+ end
+ Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
+
+ Data.Category[Data.CurrentCategory].SetName = setName
+ Data.Category[Data.CurrentCategory].SetId = setId
+ end
+ setSetIndex()
+ end
+ end
+
+ local function selectCategoryPage(buttons, page)
+ if buttons ~= Data.CurrentCategory then
+ if Data.CurrentCategory then
+ for key, button in pairs(Data.CurrentCategory) do
+ button.Visible = false
+ end
+ end
+
+ Data.CurrentCategory = buttons
+ if Data.Category[Data.CurrentCategory] == nil then
+ Data.Category[Data.CurrentCategory] = {}
+ if #buttons > 0 then
+ selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
+ end
+ else
+ Data.Category[Data.CurrentCategory].Button = nil
+ selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
+ end
+ end
+ end
+
+ local function selectCategory(category)
+ selectCategoryPage(category, 0)
+ end
+
+ local function resetAllSetButtonSelection()
+ local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+ for i = 1, #setButtons do
+ if setButtons[i]:IsA("TextButton") then
+ setButtons[i].Selected = false
+ setButtons[i].BackgroundTransparency = 1
+ setButtons[i].TextColor3 = Color3.new(1,1,1)
+ setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
+ end
+ end
+ end
+
+ local function populateSetsFrame()
+ local currRow = 0
+ for i = 1, #userCategoryButtons do
+ local button = userCategoryButtons[i]
+ button.Visible = true
+ button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
+ button.Parent = setGui.SetPanel.Sets.SetsLists
+
+ if i == 1 then -- we will have this selected by default, so show it
+ button.Selected = true
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ end
+
+ button.MouseEnter:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 0
+ button.TextColor3 = Color3.new(0,0,0)
+ end
+ end)
+ button.MouseLeave:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 1
+ button.TextColor3 = Color3.new(1,1,1)
+ end
+ end)
+ button.MouseButton1Click:connect(function()
+ resetAllSetButtonSelection()
+ button.Selected = not button.Selected
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
+ end)
+
+ currRow = currRow + 1
+ end
+
+ local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+
+ -- set first category as loaded for default
+ if buttons then
+ for i = 1, #buttons do
+ if buttons[i]:IsA("TextButton") then
+ selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
+ selectCategory(userCategoryButtons)
+ break
+ end
+ end
+ end
+ end
+
+ setGui = createSetGui()
+ waterGui, waterTypeChangedEvent = createWaterGui()
+ waterGui.Position = UDim2.new(0,55,0,0)
+ waterGui.Parent = setGui
+ setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
+ if prop == "AbsoluteSize" then
+ handleResize()
+ setSetIndex()
+ end
+ end)
+
+ local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
+ scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
+ scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
+ scrollFrame.Name = "ItemsFrame"
+ scrollFrame.ZIndex = 6
+ scrollFrame.Parent = setGui.SetPanel
+ scrollFrame.BackgroundTransparency = 1
+
+ drillDownSetZIndex(controlFrame,7)
+
+ controlFrame.Parent = setGui.SetPanel
+ controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
+
+ local debounce = false
+ controlFrame.ScrollBottom.Changed:connect(function(prop)
+ if controlFrame.ScrollBottom.Value == true then
+ if debounce then return end
+ debounce = true
+ loadSectionOfItems(setGui, rows, columns)
+ debounce = false
+ end
+ end)
+
+ local userData = {}
+ for id = 1, #userIdsForSets do
+ local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
+ if newUserData and #newUserData > 2 then
+ -- start at #3 to skip over My Decals and My Models for each account
+ for category = 3, #newUserData do
+ if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
+ table.insert(userData,1,newUserData[category])
+ else
+ table.insert(userData, newUserData[category])
+ end
+ end
+ end
+
+ end
+ if userData then
+ userCategoryButtons = processCategory(userData)
+ end
+
+ rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ populateSetsFrame()
+
+ insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
+ setGui.SetPanel.Visible = false
+ if dialogClosed then dialogClosed() end
+ end)
+
+ local setVisibilityFunction = function(visible)
+ if visible then
+ setGui.SetPanel.Visible = true
+ else
+ setGui.SetPanel.Visible = false
+ end
+ end
+
+ local getVisibilityFunction = function()
+ if setGui then
+ if setGui:FindFirstChild("SetPanel") then
+ return setGui.SetPanel.Visible
+ end
+ end
+
+ return false
+ end
+
+ return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
+end
+
+t.CreateTerrainMaterialSelector = function(size,position)
+ local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
+ terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
+
+ local selectedButton = nil
+
+ local frame = Instance.new("Frame")
+ frame.Name = "TerrainMaterialSelector"
+ if size then
+ frame.Size = size
+ else
+ frame.Size = UDim2.new(0, 245, 0, 230)
+ end
+ if position then
+ frame.Position = position
+ end
+ frame.BorderSizePixel = 0
+ frame.BackgroundColor3 = Color3.new(0,0,0)
+ frame.Active = true
+
+ terrainMaterialSelectionChanged.Parent = frame
+
+ local waterEnabled = true -- todo: turn this on when water is ready
+
+ local materialToImageMap = {}
+ local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
+ if waterEnabled then
+ table.insert(materialNames,"Water")
+ end
+ local currentMaterial = 1
+
+ function getEnumFromName(choice)
+ if choice == "Grass" then return 1 end
+ if choice == "Sand" then return 2 end
+ if choice == "Erase" then return 0 end
+ if choice == "Brick" then return 3 end
+ if choice == "Granite" then return 4 end
+ if choice == "Asphalt" then return 5 end
+ if choice == "Iron" then return 6 end
+ if choice == "Aluminum" then return 7 end
+ if choice == "Gold" then return 8 end
+ if choice == "Plank" then return 9 end
+ if choice == "Log" then return 10 end
+ if choice == "Gravel" then return 11 end
+ if choice == "Cinder Block" then return 12 end
+ if choice == "Stone Wall" then return 13 end
+ if choice == "Concrete" then return 14 end
+ if choice == "Plastic (red)" then return 15 end
+ if choice == "Plastic (blue)" then return 16 end
+ if choice == "Water" then return 17 end
+ end
+
+ function getNameFromEnum(choice)
+ if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
+ if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
+ if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
+ if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
+ if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
+ if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
+ if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
+ if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
+ if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
+ if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
+ if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
+ if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
+ if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
+ if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
+ if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
+ if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
+ if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
+
+ if waterEnabled then
+ if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
+ end
+ end
+
+
+ local function updateMaterialChoice(choice)
+ currentMaterial = getEnumFromName(choice)
+ terrainMaterialSelectionChanged:Fire(currentMaterial)
+ end
+
+ -- we so need a better way to do this
+ for i,v in pairs(materialNames) do
+ materialToImageMap[v] = {}
+ if v == "Grass" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Grass.png"
+ elseif v == "Sand" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Sand.png"
+ elseif v == "Brick" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Brick.png"
+ elseif v == "Granite" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Granite.png"
+ elseif v == "Asphalt" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Asphalt.png"
+ elseif v == "Iron" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Iron.png"
+ elseif v == "Aluminum" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Aluminum.png"
+ elseif v == "Gold" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Gold.png"
+ elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/PlasticRed.png"
+ elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/PlasticBlue.png"
+ elseif v == "Plank" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Plank.png"
+ elseif v == "Log" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Log.png"
+ elseif v == "Gravel" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Gravel.png"
+ elseif v == "Cinder Block" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/CinderBlock.png"
+ elseif v == "Stone Wall" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/StoneWall.png"
+ elseif v == "Concrete" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Concrete.png"
+ elseif v == "Water" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Water.png"
+ else materialToImageMap[v].Regular = "rbxasset://textures/terrain/unknown.png" -- fill in the rest here!!
+ end
+ end
+
+ local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
+ scrollFrame.Size = UDim2.new(0.85,0,1,0)
+ scrollFrame.Position = UDim2.new(0,0,0,0)
+ scrollFrame.Parent = frame
+
+ scrollUp.Parent = frame
+ scrollUp.Visible = true
+ scrollUp.Position = UDim2.new(1,-19,0,0)
+
+ scrollDown.Parent = frame
+ scrollDown.Visible = true
+ scrollDown.Position = UDim2.new(1,-19,1,-17)
+
+ local function goToNewMaterial(buttonWrap, materialName)
+ updateMaterialChoice(materialName)
+ buttonWrap.BackgroundTransparency = 0
+ selectedButton.BackgroundTransparency = 1
+ selectedButton = buttonWrap
+ end
+
+ local function createMaterialButton(name)
+ local buttonWrap = Instance.new("TextButton")
+ buttonWrap.Text = ""
+ buttonWrap.Size = UDim2.new(0,32,0,32)
+ buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
+ buttonWrap.BorderSizePixel = 0
+ buttonWrap.BackgroundTransparency = 1
+ buttonWrap.AutoButtonColor = false
+ buttonWrap.Name = tostring(name)
+
+ local imageButton = Instance.new("ImageButton")
+ imageButton.AutoButtonColor = false
+ imageButton.BackgroundTransparency = 1
+ imageButton.Size = UDim2.new(0,30,0,30)
+ imageButton.Position = UDim2.new(0,1,0,1)
+ imageButton.Name = tostring(name)
+ imageButton.Parent = buttonWrap
+ imageButton.Image = materialToImageMap[name].Regular
+
+ local enumType = Instance.new("NumberValue")
+ enumType.Name = "EnumType"
+ enumType.Parent = buttonWrap
+ enumType.Value = 0
+
+ imageButton.MouseEnter:connect(function()
+ buttonWrap.BackgroundTransparency = 0
+ end)
+ imageButton.MouseLeave:connect(function()
+ if selectedButton ~= buttonWrap then
+ buttonWrap.BackgroundTransparency = 1
+ end
+ end)
+ imageButton.MouseButton1Click:connect(function()
+ if selectedButton ~= buttonWrap then
+ goToNewMaterial(buttonWrap, tostring(name))
+ end
+ end)
+
+ return buttonWrap
+ end
+
+ for i = 1, #materialNames do
+ local imageButton = createMaterialButton(materialNames[i])
+
+ if materialNames[i] == "Grass" then -- always start with grass as the default
+ selectedButton = imageButton
+ imageButton.BackgroundTransparency = 0
+ end
+
+ imageButton.Parent = scrollFrame
+ end
+
+ local forceTerrainMaterialSelection = function(newMaterialType)
+ if not newMaterialType then return end
+ if currentMaterial == newMaterialType then return end
+
+ local matName = getNameFromEnum(newMaterialType)
+ local buttons = scrollFrame:GetChildren()
+ for i = 1, #buttons do
+ if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
+ if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
+ if string.find(buttons[i].Name, matName) then
+ goToNewMaterial(buttons[i],matName)
+ return
+ end
+ end
+ end
+
+ frame.Changed:connect(function ( prop )
+ if prop == "AbsoluteSize" then
+ recalculateScroll()
+ end
+ end)
+
+ recalculateScroll()
+ return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
+end
+
+t.CreateLoadingFrame = function(name,size,position)
+ game:GetService("ContentProvider"):Preload("rbxasset://ui/loadingbar.png")
+
+ local loadingFrame = Instance.new("Frame")
+ loadingFrame.Name = "LoadingFrame"
+ loadingFrame.Style = Enum.FrameStyle.RobloxRound
+
+ if size then loadingFrame.Size = size
+ else loadingFrame.Size = UDim2.new(0,300,0,160) end
+ if position then loadingFrame.Position = position
+ else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
+
+ local loadingBar = Instance.new("Frame")
+ loadingBar.Name = "LoadingBar"
+ loadingBar.BackgroundColor3 = Color3.new(0,0,0)
+ loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
+ loadingBar.Position = UDim2.new(0,0,0,41)
+ loadingBar.Size = UDim2.new(1,0,0,30)
+ loadingBar.Parent = loadingFrame
+
+ local loadingGreenBar = Instance.new("ImageLabel")
+ loadingGreenBar.Name = "LoadingGreenBar"
+ loadingGreenBar.Image = "rbxasset://ui/loadingbar.png"
+ loadingGreenBar.Position = UDim2.new(0,0,0,0)
+ loadingGreenBar.Size = UDim2.new(0,0,1,0)
+ loadingGreenBar.Visible = false
+ loadingGreenBar.Parent = loadingBar
+
+ local loadingPercent = Instance.new("TextLabel")
+ loadingPercent.Name = "LoadingPercent"
+ loadingPercent.BackgroundTransparency = 1
+ loadingPercent.Position = UDim2.new(0,0,1,0)
+ loadingPercent.Size = UDim2.new(1,0,0,14)
+ loadingPercent.Font = Enum.Font.Arial
+ loadingPercent.Text = "0%"
+ loadingPercent.FontSize = Enum.FontSize.Size14
+ loadingPercent.TextColor3 = Color3.new(1,1,1)
+ loadingPercent.Parent = loadingBar
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(0.5,-60,1,-40)
+ cancelButton.Size = UDim2.new(0,120,0,40)
+ cancelButton.Font = Enum.Font.Arial
+ cancelButton.FontSize = Enum.FontSize.Size18
+ cancelButton.TextColor3 = Color3.new(1,1,1)
+ cancelButton.Text = "Cancel"
+ cancelButton.Style = Enum.ButtonStyle.RobloxButton
+ cancelButton.Parent = loadingFrame
+
+ local loadingName = Instance.new("TextLabel")
+ loadingName.Name = "loadingName"
+ loadingName.BackgroundTransparency = 1
+ loadingName.Size = UDim2.new(1,0,0,18)
+ loadingName.Position = UDim2.new(0,0,0,2)
+ loadingName.Font = Enum.Font.Arial
+ loadingName.Text = name
+ loadingName.TextColor3 = Color3.new(1,1,1)
+ loadingName.TextStrokeTransparency = 1
+ loadingName.FontSize = Enum.FontSize.Size18
+ loadingName.Parent = loadingFrame
+
+ local cancelButtonClicked = Instance.new("BindableEvent")
+ cancelButtonClicked.Name = "CancelButtonClicked"
+ cancelButtonClicked.Parent = cancelButton
+ cancelButton.MouseButton1Click:connect(function()
+ cancelButtonClicked:Fire()
+ end)
+
+ local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
+ if percent and type(percent) ~= "number" then
+ error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
+ end
+
+ local newSize = nil
+ if percent < 0 then
+ newSize = UDim2.new(0,0,1,0)
+ elseif percent > 1 then
+ newSize = UDim2.new(1,0,1,0)
+ else
+ newSize = UDim2.new(percent,0,1,0)
+ end
+
+ if tweenAction then
+ if not tweenLength then
+ error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
+ end
+
+ if (newSize.X.Scale > 0) then
+ loadingGreenBar.Visible = true
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true)
+ else
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true,
+ function()
+ if (newSize.X.Scale < 0) then
+ loadingGreenBar.Visible = false
+ end
+ end)
+ end
+
+ else
+ loadingGreenBar.Size = newSize
+ loadingGreenBar.Visible = (newSize.X.Scale > 0)
+ end
+ end
+
+ loadingGreenBar.Changed:connect(function(prop)
+ if prop == "Size" then
+ loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
+ end
+ end)
+
+ return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
+end
+
+t.CreatePluginFrame = function (name,size,position,scrollable,parent)
+ function createMenuButton(size,position,text,fontsize,name,parent)
+ local button = Instance.new("TextButton",parent)
+ button.AutoButtonColor = false
+ button.Name = name
+ button.BackgroundTransparency = 1
+ button.Position = position
+ button.Size = size
+ button.Font = Enum.Font.ArialBold
+ button.FontSize = fontsize
+ button.Text = text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BorderSizePixel = 0
+ button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
+
+ button.MouseEnter:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 0
+ end)
+ button.MouseLeave:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 1
+ end)
+
+ return button
+
+ end
+
+ local dragBar = Instance.new("Frame",parent)
+ dragBar.Name = tostring(name) .. "DragBar"
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ dragBar.BorderColor3 = Color3.new(0,0,0)
+ if size then
+ dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
+ else
+ dragBar.Size = UDim2.new(0,183,0,20)
+ end
+ if position then
+ dragBar.Position = position
+ end
+ dragBar.Active = true
+ dragBar.Draggable = true
+ --dragBar.Visible = false
+ dragBar.MouseEnter:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
+ end)
+ dragBar.MouseLeave:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ end)
+
+ -- plugin name label
+ local pluginNameLabel = Instance.new("TextLabel",dragBar)
+ pluginNameLabel.Name = "BarNameLabel"
+ pluginNameLabel.Text = " " .. tostring(name)
+ pluginNameLabel.TextColor3 = Color3.new(1,1,1)
+ pluginNameLabel.TextStrokeTransparency = 0
+ pluginNameLabel.Size = UDim2.new(1,0,1,0)
+ pluginNameLabel.Font = Enum.Font.ArialBold
+ pluginNameLabel.FontSize = Enum.FontSize.Size18
+ pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
+ pluginNameLabel.BackgroundTransparency = 1
+
+ -- close button
+ local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
+ local closeEvent = Instance.new("BindableEvent")
+ closeEvent.Name = "CloseEvent"
+ closeEvent.Parent = closeButton
+ closeButton.MouseButton1Click:connect(function ()
+ closeEvent:Fire()
+ closeButton.BackgroundTransparency = 1
+ end)
+
+ -- help button
+ local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
+ local helpFrame = Instance.new("Frame",dragBar)
+ helpFrame.Name = "HelpFrame"
+ helpFrame.BackgroundColor3 = Color3.new(0,0,0)
+ helpFrame.Size = UDim2.new(0,300,0,552)
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ helpFrame.Active = true
+ helpFrame.BorderSizePixel = 0
+ helpFrame.Visible = false
+
+ helpButton.MouseButton1Click:connect(function( )
+ helpFrame.Visible = not helpFrame.Visible
+ if helpFrame.Visible then
+ helpButton.Selected = true
+ helpButton.BackgroundTransparency = 0
+ local screenGui = getScreenGuiAncestor(helpFrame)
+ if screenGui then
+ if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
+ helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
+ else -- position on right hand side
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpButton.Selected = false
+ helpButton.BackgroundTransparency = 1
+ end
+ end)
+
+ local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
+ minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
+
+ local minimizeFrame = Instance.new("Frame",dragBar)
+ minimizeFrame.Name = "MinimizeFrame"
+ minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
+ minimizeFrame.BorderColor3 = Color3.new(0,0,0)
+ minimizeFrame.Position = UDim2.new(0,0,1,0)
+ if size then
+ minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
+ else
+ minimizeFrame.Size = UDim2.new(0,183,0,50)
+ end
+ minimizeFrame.Visible = false
+
+ local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
+ minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
+ minimizeBigButton.Name = "MinimizeButton"
+ minimizeBigButton.Size = UDim2.new(0,100,0,40)
+ minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
+ minimizeBigButton.Font = Enum.Font.ArialBold
+ minimizeBigButton.FontSize = Enum.FontSize.Size18
+ minimizeBigButton.TextColor3 = Color3.new(1,1,1)
+ minimizeBigButton.Text = "Show"
+
+ local separatingLine = Instance.new("Frame",dragBar)
+ separatingLine.Name = "SeparatingLine"
+ separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
+ separatingLine.BorderSizePixel = 0
+ separatingLine.Position = UDim2.new(1,-18,0.5,-7)
+ separatingLine.Size = UDim2.new(0,1,0,14)
+
+ local otherSeparatingLine = separatingLine:clone()
+ otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
+ otherSeparatingLine.Parent = dragBar
+
+ local widgetContainer = Instance.new("Frame",dragBar)
+ widgetContainer.Name = "WidgetContainer"
+ widgetContainer.BackgroundTransparency = 1
+ widgetContainer.Position = UDim2.new(0,0,1,0)
+ widgetContainer.BorderColor3 = Color3.new(0,0,0)
+ if not scrollable then
+ widgetContainer.BackgroundTransparency = 0
+ widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ end
+
+ if size then
+ if scrollable then
+ widgetContainer.Size = size
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
+ end
+ else
+ if scrollable then
+ widgetContainer.Size = UDim2.new(0,163,0,400)
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
+ end
+ end
+ if position then
+ widgetContainer.Position = position + UDim2.new(0,0,0,20)
+ end
+
+ local frame,control,verticalDragger = nil
+ if scrollable then
+ --frame for widgets
+ frame,control = t.CreateTrueScrollingFrame()
+ frame.Size = UDim2.new(1, 0, 1, 0)
+ frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ frame.BorderColor3 = Color3.new(0,0,0)
+ frame.Active = true
+ frame.Parent = widgetContainer
+ control.Parent = dragBar
+ control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ control.BorderSizePixel = 0
+ control.BackgroundTransparency = 0
+ control.Position = UDim2.new(1,-21,1,1)
+ if size then
+ control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
+ else
+ control.Size = UDim2.new(0,21,0,400)
+ end
+ control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
+
+ local fakeLine = Instance.new("Frame",control)
+ fakeLine.Name = "FakeLine"
+ fakeLine.BorderSizePixel = 0
+ fakeLine.BackgroundColor3 = Color3.new(0,0,0)
+ fakeLine.Size = UDim2.new(0,1,1,1)
+ fakeLine.Position = UDim2.new(1,0,0,0)
+
+ verticalDragger = Instance.new("TextButton",widgetContainer)
+ verticalDragger.ZIndex = 2
+ verticalDragger.AutoButtonColor = false
+ verticalDragger.Name = "VerticalDragger"
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ verticalDragger.BorderColor3 = Color3.new(0,0,0)
+ verticalDragger.Size = UDim2.new(1,20,0,20)
+ verticalDragger.Position = UDim2.new(0,0,1,0)
+ verticalDragger.Active = true
+ verticalDragger.Text = ""
+
+ local scrubFrame = Instance.new("Frame",verticalDragger)
+ scrubFrame.Name = "ScrubFrame"
+ scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
+ scrubFrame.BorderSizePixel = 0
+ scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
+ scrubFrame.Size = UDim2.new(0,10,0,1)
+ scrubFrame.ZIndex = 5
+ local scrubTwo = scrubFrame:clone()
+ scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
+ scrubTwo.Parent = verticalDragger
+ local scrubThree = scrubFrame:clone()
+ scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
+ scrubThree.Parent = verticalDragger
+
+ local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.BorderSizePixel = 0
+ areaSoak.Text = ""
+ areaSoak.ZIndex = 10
+ areaSoak.Visible = false
+ areaSoak.Active = true
+
+ local draggingVertical = false
+ local startYPos = nil
+ verticalDragger.MouseEnter:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
+ end)
+ verticalDragger.MouseLeave:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ end)
+ verticalDragger.MouseButton1Down:connect(function(x,y)
+ draggingVertical = true
+ areaSoak.Visible = true
+ startYPos = y
+ end)
+ areaSoak.MouseButton1Up:connect(function ( )
+ draggingVertical = false
+ areaSoak.Visible = false
+ end)
+ areaSoak.MouseMoved:connect(function(x,y)
+ if not draggingVertical then return end
+
+ local yDelta = y - startYPos
+ if not control.ScrollDownButton.Visible and yDelta > 0 then
+ return
+ end
+
+ if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
+ control.Size = UDim2.new (0,21,0,150)
+ return
+ end
+
+ startYPos = y
+
+ if widgetContainer.Size.Y.Offset + yDelta >= 0 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
+ control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
+ end
+ end)
+ end
+
+ local function switchMinimize()
+ minimizeFrame.Visible = not minimizeFrame.Visible
+ if scrollable then
+ frame.Visible = not frame.Visible
+ verticalDragger.Visible = not verticalDragger.Visible
+ control.Visible = not control.Visible
+ else
+ widgetContainer.Visible = not widgetContainer.Visible
+ end
+
+ if minimizeFrame.Visible then
+ minimizeButton.Text = "+"
+ else
+ minimizeButton.Text = "-"
+ end
+ end
+
+ minimizeBigButton.MouseButton1Click:connect(function ( )
+ switchMinimize()
+ end)
+
+ minimizeButton.MouseButton1Click:connect(function( )
+ switchMinimize()
+ end)
+
+ if scrollable then
+ return dragBar, frame, helpFrame, closeEvent
+ else
+ return dragBar, widgetContainer, helpFrame, closeEvent
+ end
+end
+
+t.Help =
+ function(funcNameOrFunc)
+ --input argument can be a string or a function. Should return a description (of arguments and expected side effects)
+ if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
+ return "Function CreatePropertyDropDownMenu. " ..
+ "Arguments: (instance, propertyName, enumType). " ..
+ "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
+ end
+ if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
+ return "Function CreateDropDownMenu. " ..
+ "Arguments: (items, onItemSelected). " ..
+ "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
+ end
+ if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
+ return "Function CreateMessageDialog. " ..
+ "Arguments: (title, message, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
+ end
+ if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
+ return "Function CreateStyledMessageDialog. " ..
+ "Arguments: (title, message, style, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
+ end
+ if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
+ return "Function GetFontHeight. " ..
+ "Arguments: (font, fontSize). " ..
+ "Side effect: returns the size in pixels of the given font + fontSize"
+ end
+ if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
+
+ end
+ if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
+ return "Function CreateScrollingFrame. " ..
+ "Arguments: (orderList, style) " ..
+ "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
+ end
+ if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
+ return "Function CreateTrueScrollingFrame. " ..
+ "Arguments: (nil) " ..
+ "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
+ end
+ if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
+ return "Function AutoTruncateTextObject. " ..
+ "Arguments: (textLabel) " ..
+ "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
+ end
+ if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
+ return "Function CreateSlider. " ..
+ "Arguments: (steps, width, position) " ..
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
+ end
+ if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
+ return "Function CreateLoadingFrame. " ..
+ "Arguments: (name, size, position) " ..
+ "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
+ end
+ if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
+ return "Function CreateTerrainMaterialSelector. " ..
+ "Arguments: (size, position) " ..
+ "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
+ end
+ end
+
+--RBXGUI END
+
+-- This script creates almost all gui elements found in the backpack (warning: there are a lot!)
+-- TODO: automate this process
+
+local gui = script.Parent
+
+-- A couple of necessary functions
+local function waitForChild(instance, name)
+ while not instance:FindFirstChild(name) do
+ instance.ChildAdded:wait()
+ end
+end
+local function waitForProperty(instance, property)
+ while not instance[property] do
+ instance.Changed:wait()
+ end
+end
+
+waitForChild(game,"Players")
+waitForProperty(game.Players,"LocalPlayer")
+local player = game.Players.LocalPlayer
+
+-- First up is the current loadout
+local CurrentLoadout = Instance.new("Frame")
+CurrentLoadout.Name = "CurrentLoadout"
+CurrentLoadout.Position = UDim2.new(0.5, -170, 1, -85)
+CurrentLoadout.Size = UDim2.new(0, 480, 0, 48)
+CurrentLoadout.BackgroundTransparency = 1
+
+CurrentLoadout.Parent = gui
+
+local Debounce = Instance.new("BoolValue")
+Debounce.Name = "Debounce"
+
+Debounce.Parent = CurrentLoadout
+
+for i = 0, 9 do
+ local slotFrame = Instance.new("Frame")
+
+ slotFrame.BackgroundColor3 = Color3.new(0,0,0)
+ slotFrame.BackgroundTransparency = 1
+ slotFrame.BorderColor3 = Color3.new(1,1,1)
+ slotFrame.Name = "Slot" .. tostring(i)
+ if i == 0 then
+ slotFrame.Position = UDim2.new(0.9,0,0,0)
+ else
+ slotFrame.Position = UDim2.new((i - 1) * 0.1,0,0,0)
+ end
+ slotFrame.Size = UDim2.new(0.1,0,1,0)
+ slotFrame.Parent = CurrentLoadout
+end
+
+local TempSlot = Instance.new("ImageButton")
+TempSlot.Name = "TempSlot"
+TempSlot.Active = true
+TempSlot.Size = UDim2.new(1,0,1,0)
+TempSlot.Style = Enum.ButtonStyle.RobloxButton
+TempSlot.Visible = false
+
+TempSlot.Parent = CurrentLoadout
+
+ -- TempSlot Children
+ local GearReference = Instance.new("ObjectValue")
+ GearReference.Name = "GearReference"
+
+ GearReference.Parent = TempSlot
+
+ local ToolTipLabel = Instance.new("TextLabel")
+ ToolTipLabel.Name = "ToolTipLabel"
+
+ ToolTipLabel.Text = ""
+ ToolTipLabel.BackgroundTransparency = 0.5
+ ToolTipLabel.BorderSizePixel = 0
+ ToolTipLabel.Visible = false
+ ToolTipLabel.TextColor3 = Color3.new(1,1,1)
+ ToolTipLabel.BackgroundColor3 = Color3.new(0,0,0)
+ ToolTipLabel.TextStrokeTransparency = 0
+ ToolTipLabel.Font = Enum.Font.ArialBold
+ ToolTipLabel.FontSize = Enum.FontSize.Size14
+ --ToolTipLabel.TextWrap = true
+ ToolTipLabel.Size = UDim2.new(1,60,0,20)
+ ToolTipLabel.Position = UDim2.new(0,-30,0,-30)
+ ToolTipLabel.Parent = TempSlot
+
+ local Kill = Instance.new("BoolValue")
+ Kill.Name = "Kill"
+
+ Kill.Parent = TempSlot
+
+ local GearImage = Instance.new("ImageLabel")
+ GearImage.Name = "GearImage"
+ GearImage.BackgroundTransparency = 1
+ GearImage.Position = UDim2.new(0,-7,0,-7)
+ GearImage.Size = UDim2.new(1,14,1,14)
+ GearImage.ZIndex = 2
+
+ GearImage.Parent = TempSlot
+
+ local SlotNumber = Instance.new("TextLabel")
+ SlotNumber.Name = "SlotNumber"
+ SlotNumber.BackgroundTransparency = 1
+ SlotNumber.BorderSizePixel = 0
+ SlotNumber.Font = Enum.Font.ArialBold
+ SlotNumber.FontSize = Enum.FontSize.Size18
+ SlotNumber.Position = UDim2.new(0,-7,0,-7)
+ SlotNumber.Size = UDim2.new(0,10,0,15)
+ SlotNumber.TextColor3 = Color3.new(1,1,1)
+ SlotNumber.TextTransparency = 0
+ SlotNumber.TextXAlignment = Enum.TextXAlignment.Left
+ SlotNumber.TextYAlignment = Enum.TextYAlignment.Bottom
+ SlotNumber.ZIndex = 4
+
+ SlotNumber.Parent = TempSlot
+
+ local SlotNumberDownShadow = SlotNumber:clone()
+ SlotNumberDownShadow.Name = "SlotNumberDownShadow"
+ SlotNumberDownShadow.TextColor3 = Color3.new(0,0,0)
+ SlotNumberDownShadow.ZIndex = 3
+ SlotNumberDownShadow.Position = UDim2.new(0,-6,0,-6)
+ SlotNumberDownShadow.Parent = TempSlot
+
+ local SlotNumberUpShadow = SlotNumberDownShadow:clone()
+ SlotNumberUpShadow.Name = "SlotNumberUpShadow"
+ SlotNumberUpShadow.Position = UDim2.new(0,-8,0,-8)
+ SlotNumberUpShadow.Parent = TempSlot
+
+ local GearText = Instance.new("TextLabel")
+
+ GearText.Name = "GearText"
+ GearText.BackgroundTransparency = 1
+ GearText.Font = Enum.Font.Arial
+ GearText.FontSize = Enum.FontSize.Size14
+ GearText.Position = UDim2.new(0,-8,0,-8)
+ GearText.ZIndex = 2
+ GearText.Size = UDim2.new(1,16,1,16)
+ GearText.Text = ""
+ GearText.TextColor3 = Color3.new(1,1,1)
+ GearText.TextWrap = true
+ GearText.Parent = TempSlot
+
+--- Great, now lets make the inventory!
+
+local Backpack = Instance.new("Frame")
+
+Backpack.Visible = false
+Backpack.Name = "Backpack"
+Backpack.Position = UDim2.new(0.5,0,0.5,0)
+Backpack.BackgroundColor3 = Color3.new(0,0,0)
+Backpack.BackgroundTransparency = 0.08
+Backpack.BorderSizePixel = 0
+Backpack.Parent = gui
+Backpack.Active = true
+
+ -- Backpack Children
+ local SwapSlot = Instance.new("BoolValue")
+
+ SwapSlot.Name = "SwapSlot"
+ SwapSlot.Parent = Backpack
+
+ -- SwapSlot Children
+ local Slot = Instance.new("IntValue")
+
+ Slot.Name = "Slot"
+ Slot.Parent = SwapSlot
+
+ local GearButton = Instance.new("ObjectValue")
+
+ GearButton.Name = "GearButton"
+ GearButton.Parent = SwapSlot
+
+ local Tabs = Instance.new("Frame")
+ Tabs.Name = "Tabs"
+ Tabs.Visible = true
+
+ Tabs.BackgroundColor3 = Color3.new(0,0,0)
+ Tabs.BackgroundTransparency = 0.08
+ Tabs.BorderSizePixel = 0
+ Tabs.Position = UDim2.new(0,0,-0.1,-4)
+ Tabs.Size = UDim2.new(1,0,0.1,4)
+ Tabs.Parent = Backpack
+
+ -- Tabs Children
+
+ local tabLine = Instance.new("Frame")
+
+ tabLine.Name = "TabLine"
+ tabLine.BackgroundColor3 = Color3.new(53/255, 53/255, 53/255)
+ tabLine.BorderSizePixel = 0
+ tabLine.Position = UDim2.new(0,5,1,-4)
+ tabLine.Size = UDim2.new(1,-10,0,4)
+ tabLine.ZIndex = 2
+ tabLine.Parent = Tabs
+
+ local InventoryButton = Instance.new("TextButton")
+
+ InventoryButton.Name = "InventoryButton"
+ InventoryButton.Size = UDim2.new(0,60,0,30)
+ InventoryButton.Position = UDim2.new(0,7,1,-31)
+ InventoryButton.BackgroundColor3 = Color3.new(1,1,1)
+ InventoryButton.BorderColor3 = Color3.new(1,1,1)
+ InventoryButton.Font = Enum.Font.ArialBold
+ InventoryButton.FontSize = Enum.FontSize.Size18
+ InventoryButton.Text = "Gear"
+ InventoryButton.AutoButtonColor = false
+ InventoryButton.TextColor3 = Color3.new(0,0,0)
+ InventoryButton.Selected = true
+ InventoryButton.Active = true
+ InventoryButton.ZIndex = 3
+ InventoryButton.Parent = Tabs
+
+ local closeButton = Instance.new("TextButton")
+
+ closeButton.Name = "CloseButton"
+ closeButton.Font = Enum.Font.ArialBold
+ closeButton.FontSize = Enum.FontSize.Size24
+ closeButton.Position = UDim2.new(1,-33,0,4)
+ closeButton.Size = UDim2.new(0,30,0,30)
+ closeButton.Style = Enum.ButtonStyle.RobloxButton
+ closeButton.Text = ""
+ closeButton.TextColor3 = Color3.new(1,1,1)
+ closeButton.Parent = Tabs
+ closeButton.Modal = true
+
+ --closeButton child
+ local XImage = Instance.new("ImageLabel")
+
+ XImage.Name = "XImage"
+ game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=75547445")
+ XImage.Image = "http://www.roblox.com/asset/?id=75547445" --TODO: move to rbxasset
+ XImage.BackgroundTransparency = 1
+ XImage.Position = UDim2.new(-.25,-1,-.25,-1)
+ XImage.Size = UDim2.new(1.5,2,1.5,2)
+ XImage.ZIndex = 2
+ XImage.Parent = closeButton
+
+ -- Generic Search gui used across backpack
+ local SearchFrame = Instance.new("Frame")
+
+ SearchFrame.Name = "SearchFrame"
+ SearchFrame.BackgroundTransparency = 1
+ SearchFrame.Position = UDim2.new(1,-220,0,2)
+ SearchFrame.Size = UDim2.new(0,220,0,24)
+ SearchFrame.Parent = Backpack
+
+ -- SearchFrame Children
+ local SearchButton = Instance.new("ImageButton")
+
+ SearchButton.Name = "SearchButton"
+ SearchButton.Size = UDim2.new(0,25,0,25)
+ SearchButton.BackgroundTransparency = 1
+ SearchButton.Image = "rbxasset://textures/ui/SearchIcon.png"
+ SearchButton.Parent = SearchFrame
+
+ local SearchBoxFrame = Instance.new("TextButton")
+
+ SearchBoxFrame.Position = UDim2.new(0,25,0,0)
+ SearchBoxFrame.Size = UDim2.new(1,-28,0,26)
+ SearchBoxFrame.Name = "SearchBoxFrame"
+ SearchBoxFrame.Text = ""
+ SearchBoxFrame.Style = Enum.ButtonStyle.RobloxButton
+ SearchBoxFrame.Parent = SearchFrame
+
+ -- SearchBoxFrame Children
+ local SearchBox = Instance.new("TextBox")
+
+ SearchBox.Name = "SearchBox"
+ SearchBox.BackgroundTransparency = 1
+ SearchBox.Font = Enum.Font.ArialBold
+ SearchBox.FontSize = Enum.FontSize.Size12
+ SearchBox.Position = UDim2.new(0,-5,0,-5)
+ SearchBox.Size = UDim2.new(1,10,1,10)
+ SearchBox.TextColor3 = Color3.new(1,1,1)
+ SearchBox.TextXAlignment = Enum.TextXAlignment.Left
+ SearchBox.ZIndex = 2
+ SearchBox.TextWrap = true
+ SearchBox.Text = "Search..."
+ SearchBox.Parent = SearchBoxFrame
+
+
+ local ResetButton = Instance.new("TextButton")
+
+ ResetButton.Visible = false
+ ResetButton.Name = "ResetButton"
+ ResetButton.Position = UDim2.new(1,-26,0,3)
+ ResetButton.Size = UDim2.new(0,20,0,20)
+ ResetButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ ResetButton.Text = "X"
+ ResetButton.TextColor3 = Color3.new(1,1,1)
+ ResetButton.Font = Enum.Font.ArialBold
+ ResetButton.FontSize = Enum.FontSize.Size18
+ ResetButton.ZIndex = 3
+ ResetButton.Parent = SearchFrame
+
+------------------------------- GEAR -------------------------------------------------------
+ local Gear = Instance.new("Frame")
+ Gear.Name = "Gear"
+
+ Gear.BackgroundTransparency = 1
+ Gear.Size = UDim2.new(1,0,1,0)
+ Gear.Parent = Backpack
+
+ -- Gear Children
+ local AssetsList = Instance.new("Frame")
+
+ AssetsList.Name = "AssetsList"
+ AssetsList.BackgroundTransparency = 1
+ AssetsList.Size = UDim2.new(0.2,0,1,0)
+ AssetsList.Style = Enum.FrameStyle.RobloxSquare
+ AssetsList.Visible = false
+ AssetsList.Parent = Gear
+
+ local GearGrid = Instance.new("Frame")
+
+ GearGrid.Name = "GearGrid"
+ GearGrid.Size = UDim2.new(0.69,0,1,0)
+ GearGrid.BackgroundTransparency = 1
+ GearGrid.Parent = Gear
+
+
+ local GearButton = Instance.new("ImageButton")
+
+ GearButton.Visible = false
+ GearButton.Name = "GearButton"
+ GearButton.Size = UDim2.new(0,64,0,64)
+ GearButton.Style = Enum.ButtonStyle.RobloxButton
+ GearButton.Parent = GearGrid
+
+ -- GearButton Children
+ local GearReference = Instance.new("ObjectValue")
+
+ GearReference.Name = "GearReference"
+ GearReference.Parent = GearButton
+
+ local GreyOutButton = Instance.new("Frame")
+
+ GreyOutButton.Name = "GreyOutButton"
+ GreyOutButton.BackgroundTransparency = 0.5
+ GreyOutButton.Size = UDim2.new(1,0,1,0)
+ GreyOutButton.Active = true
+ GreyOutButton.Visible = false
+ GreyOutButton.ZIndex = 3
+ GreyOutButton.Parent = GearButton
+
+ local GearText = Instance.new("TextLabel")
+
+ GearText.Name = "GearText"
+ GearText.BackgroundTransparency = 1
+ GearText.Font = Enum.Font.Arial
+ GearText.FontSize = Enum.FontSize.Size14
+ GearText.Position = UDim2.new(0,-8,0,-8)
+ GearText.Size = UDim2.new(1,16,1,16)
+ GearText.Text = ""
+ GearText.ZIndex = 2
+ GearText.TextColor3 = Color3.new(1,1,1)
+ GearText.TextWrap = true
+ GearText.Parent = GearButton
+
+ local GearGridScrollingArea = Instance.new("Frame")
+
+ GearGridScrollingArea.Name = "GearGridScrollingArea"
+ GearGridScrollingArea.Position = UDim2.new(0.7,0,0,35)
+ GearGridScrollingArea.Size = UDim2.new(0,17,1,-45)
+ GearGridScrollingArea.BackgroundTransparency = 1
+ GearGridScrollingArea.Parent = Gear
+
+ local GearLoadouts = Instance.new("Frame")
+
+ GearLoadouts.Name = "GearLoadouts"
+ GearLoadouts.BackgroundTransparency = 1
+ GearLoadouts.Position = UDim2.new(0.7,23,0.5,1)
+ GearLoadouts.Size = UDim2.new(0.3,-23,0.5,-1)
+ GearLoadouts.Parent = Gear
+ GearLoadouts.Visible = false
+
+ -- GearLoadouts Children
+ local GearLoadoutsHeader = Instance.new("Frame")
+
+ GearLoadoutsHeader.Name = "GearLoadoutsHeader"
+ GearLoadoutsHeader.BackgroundColor3 = Color3.new(0,0,0)
+ GearLoadoutsHeader.BackgroundTransparency = 0.2
+ GearLoadoutsHeader.BorderColor3 = Color3.new(1,0,0)
+ GearLoadoutsHeader.Size = UDim2.new(1,2,0.15,-1)
+ GearLoadoutsHeader.Parent = GearLoadouts
+
+ -- GearLoadoutsHeader Children
+ local LoadoutsHeaderText = Instance.new("TextLabel")
+
+ LoadoutsHeaderText.Name = "LoadoutsHeaderText"
+ LoadoutsHeaderText.BackgroundTransparency = 1
+ LoadoutsHeaderText.Font = Enum.Font.ArialBold
+ LoadoutsHeaderText.FontSize = Enum.FontSize.Size18
+ LoadoutsHeaderText.Size = UDim2.new(1,0,1,0)
+ LoadoutsHeaderText.Text = "Loadouts"
+ LoadoutsHeaderText.TextColor3 = Color3.new(1,1,1)
+ LoadoutsHeaderText.Parent = GearLoadoutsHeader
+
+ local GearLoadoutsScrollingArea = GearGridScrollingArea:clone()
+
+ GearLoadoutsScrollingArea.Name = "GearLoadoutsScrollingArea"
+ GearLoadoutsScrollingArea.Position = UDim2.new(1,-15,0.15,2)
+ GearLoadoutsScrollingArea.Size = UDim2.new(0,17,0.85,-2)
+ GearLoadoutsScrollingArea.Parent = GearLoadouts
+
+ local LoadoutsList = Instance.new("Frame")
+
+ LoadoutsList.Name = "LoadoutsList"
+ LoadoutsList.Position = UDim2.new(0,0,0.15,2)
+ LoadoutsList.Size = UDim2.new(1,-17,0.85,-2)
+ LoadoutsList.Style = Enum.FrameStyle.RobloxSquare
+ LoadoutsList.Parent = GearLoadouts
+
+ local GearPreview = Instance.new("Frame")
+
+ GearPreview.Name = "GearPreview"
+ GearPreview.Position = UDim2.new(0.7,23,0,0)
+ GearPreview.Size = UDim2.new(0.3,-28,0.5,-1)
+ GearPreview.BackgroundTransparency = 1
+ GearPreview.ZIndex = 7
+ GearPreview.Parent = Gear
+
+ -- GearPreview Children
+ local GearStats = Instance.new("Frame")
+
+ GearStats.Name = "GearStats"
+ GearStats.BackgroundTransparency = 1
+ GearStats.Position = UDim2.new(0,0,0.75,0)
+ GearStats.Size = UDim2.new(1,0,0.25,0)
+ GearStats.ZIndex = 8
+ GearStats.Parent = GearPreview
+
+ -- GearStats Children
+ local GearName = Instance.new("TextLabel")
+
+ GearName.Name = "GearName"
+ GearName.BackgroundTransparency = 1
+ GearName.Font = Enum.Font.ArialBold
+ GearName.FontSize = Enum.FontSize.Size18
+ GearName.Position = UDim2.new(0,-3,0,0)
+ GearName.Size = UDim2.new(1,6,1,5)
+ GearName.Text = ""
+ GearName.TextColor3 = Color3.new(1,1,1)
+ GearName.TextWrap = true
+ GearName.ZIndex = 9
+ GearName.Parent = GearStats
+
+ local GearImage = Instance.new("ImageLabel")
+ GearImage.Name = "GearImage"
+ GearImage.Image = ""
+ GearImage.BackgroundTransparency = 1
+ GearImage.Position = UDim2.new(0.125,0,0,0)
+ GearImage.Size = UDim2.new(0.75,0,0.75,0)
+ GearImage.ZIndex = 8
+ GearImage.Parent = GearPreview
+
+ --GearImage Children
+ local GearIcons = Instance.new("Frame")
+ GearIcons.BackgroundColor3 = Color3.new(0,0,0)
+ GearIcons.BackgroundTransparency = 0.5
+ GearIcons.BorderSizePixel = 0
+
+ GearIcons.Name = "GearIcons"
+ GearIcons.Position = UDim2.new(0.4,2,0.85,-2)
+ GearIcons.Size = UDim2.new(0.6,0,0.15,0)
+ GearIcons.Visible = false
+ GearIcons.ZIndex = 9
+ GearIcons.Parent = GearImage
+
+ -- GearIcons Children
+ local GenreImage = Instance.new("ImageLabel")
+
+ GenreImage.Name = "GenreImage"
+ GenreImage.BackgroundColor3 = Color3.new(102/255,153/255,1)
+ GenreImage.BackgroundTransparency = 0.5
+ GenreImage.BorderSizePixel = 0
+ GenreImage.Size = UDim2.new(0.25,0,1,0)
+ GenreImage.Parent = GearIcons
+
+ local AttributeOneImage = GenreImage:clone()
+
+ AttributeOneImage.Name = "AttributeOneImage"
+ AttributeOneImage.BackgroundColor3 = Color3.new(1,51/255,0)
+ AttributeOneImage.Position = UDim2.new(0.25,0,0,0)
+ AttributeOneImage.Parent = GearIcons
+
+ local AttributeTwoImage = GenreImage:clone()
+
+ AttributeTwoImage.Name = "AttributeTwoImage"
+ AttributeTwoImage.BackgroundColor3 = Color3.new(153/255,1,153/255)
+ AttributeTwoImage.Position = UDim2.new(0.5,0,0,0)
+ AttributeTwoImage.Parent = GearIcons
+
+ local AttributeThreeImage = GenreImage:clone()
+
+ AttributeThreeImage.Name = "AttributeThreeImage"
+ AttributeThreeImage.BackgroundColor3 = Color3.new(0,0.5,0.5)
+ AttributeThreeImage.Position = UDim2.new(0.75,0,0,0)
+ AttributeThreeImage.Parent = GearIcons
+
+------------------------------- WARDROBE -------------------------------------------------------
+
+
+
+local t = {}
+
+local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
+ local eventConnection = nil
+
+ --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
+ local tryConnect = function()
+ if game:IsAncestorOf(parentInstance) then
+ --Entering the world, make sure we are connected/synced
+ if not eventConnection then
+ eventConnection = instance[event]:connect(signalFunc)
+ if syncFunc then syncFunc() end
+ end
+ else
+ --Probably leaving the world, so disconnect for now
+ if eventConnection then
+ eventConnection:disconnect()
+ if removeFunc then removeFunc() end
+ end
+ end
+ end
+
+ --Hook it up to ancestryChanged signal
+ local connection = parentInstance.AncestryChanged:connect(tryConnect)
+
+ --Now connect us if we're already in the world
+ tryConnect()
+
+ return connection
+end
+
+local function getScreenGuiAncestor(instance)
+ local localInstance = instance
+ while localInstance and not localInstance:IsA("ScreenGui") do
+ localInstance = localInstance.Parent
+ end
+ return localInstance
+end
+
+local function CreateButtons(frame, buttons, yPos, ySize)
+ local buttonNum = 1
+ local buttonObjs = {}
+ for i, obj in ipairs(buttons) do
+ local button = Instance.new("TextButton")
+ button.Name = "Button" .. buttonNum
+ button.Font = Enum.Font.Arial
+ button.FontSize = Enum.FontSize.Size18
+ button.AutoButtonColor = true
+ button.Modal = true
+ if obj["Style"] then
+ button.Style = obj.Style
+ else
+ button.Style = Enum.ButtonStyle.RobloxButton
+ end
+ if obj["ZIndex"] then
+ button.ZIndex = obj.ZIndex
+ end
+ button.Text = obj.Text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.MouseButton1Click:connect(obj.Function)
+ button.Parent = frame
+ buttonObjs[buttonNum] = button
+
+ buttonNum = buttonNum + 1
+ end
+ local numButtons = buttonNum-1
+
+ if numButtons == 1 then
+ frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
+ elseif numButtons == 2 then
+ frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
+
+ frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
+ frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
+ elseif numButtons >= 3 then
+ local spacing = .1 / numButtons
+ local buttonSize = .9 / numButtons
+
+ buttonNum = 1
+ while buttonNum <= numButtons do
+ buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
+ buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
+ buttonNum = buttonNum + 1
+ end
+ end
+end
+
+local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
+
+ local newStep = steps - 1 --otherwise we really get one more step than we want
+ local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
+ local wholeNum, remainder = math.modf(relativePosX * newStep)
+ if remainder > 0.5 then
+ wholeNum = wholeNum + 1
+ end
+ relativePosX = wholeNum/newStep
+
+ local result = math.ceil(relativePosX * newStep)
+ if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
+ sliderPosition.Value = result + 1
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end
+
+end
+
+local function cancelSlide(areaSoak)
+ areaSoak.Visible = false
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+end
+
+t.CreateStyledMessageDialog = function(title, message, style, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0, 165)
+ frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local styleImage = Instance.new("ImageLabel")
+ styleImage.Name = "StyleImage"
+ styleImage.BackgroundTransparency = 1
+ styleImage.Position = UDim2.new(0,5,0,15)
+ if style == "error" or style == "Error" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "http://www.roblox.com/asset/?id=42565285"
+ elseif style == "notify" or style == "Notify" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "http://www.roblox.com/asset/?id=42604978"
+ elseif style == "confirm" or style == "Confirm" then
+ styleImage.Size = UDim2.new(0, 74, 0, 76)
+ styleImage.Image = "http://www.roblox.com/asset/?id=42557901"
+ else
+ return t.CreateMessageDialog(title,message,buttons)
+ end
+ styleImage.Parent = frame
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.TextStrokeTransparency = 0
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 80, 0, 0)
+ titleLabel.Size = UDim2.new(1, -80, 0, 40)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextStrokeTransparency = 0
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
+ messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
+
+ return frame
+end
+
+t.CreateMessageDialog = function(title, message, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0.5, 0)
+ frame.Position = UDim2.new(0.25, 0, 0.25, 0)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 0, 0, 0)
+ titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
+ messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
+
+ return frame
+end
+
+t.CreateDropDownMenu = function(items, onSelect, forRoblox, whiteSkin, baseZ)
+ local baseZIndex = 0
+ if (type(baseZ) == "number") then
+ baseZIndex = baseZ
+ end
+ local width = UDim.new(0, 100)
+ local height = UDim.new(0, 32)
+
+ local xPos = 0.055
+ local frame = Instance.new("Frame")
+ local textColor = Color3.new(1,1,1)
+ if (whiteSkin) then
+ textColor = Color3.new(0.5, 0.5, 0.5)
+ end
+ frame.Name = "DropDownMenu"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(width, height)
+
+ local dropDownMenu = Instance.new("TextButton")
+ dropDownMenu.Name = "DropDownMenuButton"
+ dropDownMenu.TextWrap = true
+ dropDownMenu.TextColor3 = textColor
+ dropDownMenu.Text = "Choose One"
+ dropDownMenu.Font = Enum.Font.ArialBold
+ dropDownMenu.FontSize = Enum.FontSize.Size18
+ dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
+ dropDownMenu.BackgroundTransparency = 1
+ dropDownMenu.AutoButtonColor = true
+ if (whiteSkin) then
+ dropDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
+ else
+ dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ end
+ dropDownMenu.Size = UDim2.new(1,0,1,0)
+ dropDownMenu.Parent = frame
+ dropDownMenu.ZIndex = 2 + baseZIndex
+
+ local dropDownIcon = Instance.new("ImageLabel")
+ dropDownIcon.Name = "Icon"
+ dropDownIcon.Active = false
+ if (whiteSkin) then
+ dropDownIcon.Image = "rbxasset://textures/ui/dropdown_arrow.png"
+ dropDownIcon.Size = UDim2.new(0,16,0,12)
+ dropDownIcon.Position = UDim2.new(1,-17,0.5, -6)
+ else
+ dropDownIcon.Image = "http://www.roblox.com/asset/?id=45732894"
+ dropDownIcon.Size = UDim2.new(0,11,0,6)
+ dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
+ end
+ dropDownIcon.BackgroundTransparency = 1
+ dropDownIcon.Parent = dropDownMenu
+ dropDownIcon.ZIndex = 2 + baseZIndex
+
+ local itemCount = #items
+ local dropDownItemCount = #items
+ local useScrollButtons = false
+ if dropDownItemCount > 6 then
+ useScrollButtons = true
+ dropDownItemCount = 6
+ end
+
+ local droppedDownMenu = Instance.new("TextButton")
+ droppedDownMenu.Name = "List"
+ droppedDownMenu.Text = ""
+ droppedDownMenu.BackgroundTransparency = 1
+ --droppedDownMenu.AutoButtonColor = true
+ if (whiteSkin) then
+ droppedDownMenu.Style = Enum.ButtonStyle.RobloxRoundDropdownButton
+ else
+ droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ end
+ droppedDownMenu.Visible = false
+ droppedDownMenu.Active = true --Blocks clicks
+ droppedDownMenu.Position = UDim2.new(0,0,0,0)
+ droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
+ droppedDownMenu.Parent = frame
+ droppedDownMenu.ZIndex = 2 + baseZIndex
+
+ local choiceButton = Instance.new("TextButton")
+ choiceButton.Name = "ChoiceButton"
+ choiceButton.BackgroundTransparency = 1
+ choiceButton.BorderSizePixel = 0
+ choiceButton.Text = "ReplaceMe"
+ choiceButton.TextColor3 = textColor
+ choiceButton.TextXAlignment = Enum.TextXAlignment.Left
+ choiceButton.TextYAlignment = Enum.TextYAlignment.Center
+ choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
+ choiceButton.Font = Enum.Font.Arial
+ choiceButton.FontSize = Enum.FontSize.Size18
+ if useScrollButtons then
+ choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
+ else
+ choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
+ end
+ choiceButton.TextWrap = true
+ choiceButton.ZIndex = 2 + baseZIndex
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = true
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 3 + baseZIndex
+
+ local dropDownSelected = false
+
+ local scrollUpButton
+ local scrollDownButton
+ local scrollMouseCount = 0
+
+ local setZIndex = function(baseZIndex)
+ droppedDownMenu.ZIndex = baseZIndex +1
+ if scrollUpButton then
+ scrollUpButton.ZIndex = baseZIndex + 3
+ end
+ if scrollDownButton then
+ scrollDownButton.ZIndex = baseZIndex + 3
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child.Name == "ChoiceButton" then
+ child.ZIndex = baseZIndex + 2
+ elseif child.Name == "ClickCaptureButton" then
+ child.ZIndex = baseZIndex
+ end
+ end
+ end
+ end
+
+ local scrollBarPosition = 1
+ local updateScroll = function()
+ if scrollUpButton then
+ scrollUpButton.Active = scrollBarPosition > 1
+ end
+ if scrollDownButton then
+ scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if not children then return end
+
+ local childNum = 1
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
+ obj.Visible = false
+ else
+ obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
+ obj.Visible = true
+ end
+ obj.TextColor3 = textColor
+ obj.BackgroundTransparency = 1
+
+ childNum = childNum + 1
+ end
+ end
+ end
+ local toggleVisibility = function()
+ dropDownSelected = not dropDownSelected
+
+ areaSoak.Visible = not areaSoak.Visible
+ dropDownMenu.Visible = not dropDownSelected
+ droppedDownMenu.Visible = dropDownSelected
+ if dropDownSelected then
+ setZIndex(4 + baseZIndex)
+ else
+ setZIndex(2 + baseZIndex)
+ end
+ if useScrollButtons then
+ updateScroll()
+ end
+ end
+ droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
+
+ local updateSelection = function(text)
+ local foundItem = false
+ local children = droppedDownMenu:GetChildren()
+ local childNum = 1
+ if children then
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if obj.Text == text then
+ obj.Font = Enum.Font.ArialBold
+ foundItem = true
+ scrollBarPosition = childNum
+ if (whiteSkin) then
+ obj.TextColor3 = Color3.new(90/255,142/255,233/255)
+ end
+ else
+ obj.Font = Enum.Font.Arial
+ if (whiteSkin) then
+ obj.TextColor3 = textColor
+ end
+ end
+ childNum = childNum + 1
+ end
+ end
+ end
+ if not text then
+ dropDownMenu.Text = "Choose One"
+ scrollBarPosition = 1
+ else
+ if not foundItem then
+ error("Invalid Selection Update -- " .. text)
+ end
+
+ if scrollBarPosition + dropDownItemCount > itemCount + 1 then
+ scrollBarPosition = itemCount - dropDownItemCount + 1
+ end
+
+ dropDownMenu.Text = text
+ end
+ end
+
+ local function scrollDown()
+ if scrollBarPosition + dropDownItemCount <= itemCount then
+ scrollBarPosition = scrollBarPosition + 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+ local function scrollUp()
+ if scrollBarPosition > 1 then
+ scrollBarPosition = scrollBarPosition - 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+
+ if useScrollButtons then
+ --Make some scroll buttons
+ scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+ scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
+ scrollUpButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollUp()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollUp() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ scrollUpButton.Parent = droppedDownMenu
+
+ scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+ scrollDownButton.Position = UDim2.new(1,-11,1,-11)
+ scrollDownButton.Parent = droppedDownMenu
+ scrollDownButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollDown()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollDown() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ local scrollbar = Instance.new("ImageLabel")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
+ scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
+ scrollbar.Parent = droppedDownMenu
+ end
+
+ for i,item in ipairs(items) do
+ -- needed to maintain local scope for items in event listeners below
+ local button = choiceButton:clone()
+ if forRoblox then
+
+ end
+ button.Text = item
+ button.Parent = droppedDownMenu
+ if (whiteSkin) then
+ button.TextColor3 = textColor
+ end
+
+ button.MouseButton1Click:connect(function()
+ --Remove Highlight
+ if (not whiteSkin) then
+ button.TextColor3 = Color3.new(1,1,1)
+ end
+ button.BackgroundTransparency = 1
+
+ updateSelection(item)
+ onSelect(item)
+
+ toggleVisibility()
+ end)
+ button.MouseEnter:connect(function()
+ --Add Highlight
+ if (not whiteSkin) then
+ button.TextColor3 = Color3.new(0,0,0)
+ end
+ button.BackgroundTransparency = 0
+ end)
+
+ button.MouseLeave:connect(function()
+ --Remove Highlight
+ if (not whiteSkin) then
+ button.TextColor3 = Color3.new(1,1,1)
+ end
+ button.BackgroundTransparency = 1
+ end)
+ end
+
+ --This does the initial layout of the buttons
+ updateScroll()
+
+ frame.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(frame)
+ end
+ end)
+
+ dropDownMenu.MouseButton1Click:connect(toggleVisibility)
+ areaSoak.MouseButton1Click:connect(toggleVisibility)
+ return frame, updateSelection
+end
+
+t.CreatePropertyDropDownMenu = function(instance, property, enum)
+
+ local items = enum:GetEnumItems()
+ local names = {}
+ local nameToItem = {}
+ for i,obj in ipairs(items) do
+ names[i] = obj.Name
+ nameToItem[obj.Name] = obj
+ end
+
+ local frame
+ local updateSelection
+ frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
+
+ ScopedConnect(frame, instance, "Changed",
+ function(prop)
+ if prop == property then
+ updateSelection(instance[property].Name)
+ end
+ end,
+ function()
+ updateSelection(instance[property].Name)
+ end)
+
+ return frame
+end
+
+t.GetFontHeight = function(font, fontSize)
+ if font == nil or fontSize == nil then
+ error("Font and FontSize must be non-nil")
+ end
+
+ if font == Enum.Font.Legacy then
+ if fontSize == Enum.FontSize.Size8 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 15
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 17
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 21
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 27
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 54
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 72
+ else
+ error("Unknown FontSize")
+ end
+ elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
+ if fontSize == Enum.FontSize.Size8 then
+ return 8
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 9
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 10
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 11
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 24
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 48
+ else
+ error("Unknown FontSize")
+ end
+ else
+ error("Unknown Font " .. font)
+ end
+end
+
+local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+ for i, child in ipairs(guiObjects) do
+ if child:IsA("TextLabel") or child:IsA("TextButton") then
+ local isLabel = child:IsA("TextLabel")
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
+
+ if child.TextFits and child.TextBounds.Y < pixelsRemaining then
+ child.Visible = true
+ if isLabel then
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
+ else
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
+ end
+
+ while not child.TextFits do
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
+ end
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ else
+ child.Visible = false
+ pixelsRemaining = -1
+ end
+
+ else
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ child.Visible = (pixelsRemaining >= 0)
+ end
+ end
+end
+
+t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
+ if not frame:IsA("GuiObject") then
+ error("Frame must be a GuiObject")
+ end
+ for i, child in ipairs(guiObjects) do
+ if not child:IsA("GuiObject") then
+ error("All elements that are layed out must be of type GuiObject")
+ end
+ end
+
+ if not settingsTable then
+ settingsTable = {}
+ end
+
+ if not settingsTable["TextLabelSizePadY"] then
+ settingsTable["TextLabelSizePadY"] = 0
+ end
+ if not settingsTable["TextLabelPositionPadY"] then
+ settingsTable["TextLabelPositionPadY"] = 0
+ end
+ if not settingsTable["TextButtonSizePadY"] then
+ settingsTable["TextButtonSizePadY"] = 12
+ end
+ if not settingsTable["TextButtonPositionPadY"] then
+ settingsTable["TextButtonPositionPadY"] = 2
+ end
+
+ --Wrapper frame takes care of styled objects
+ local wrapperFrame = Instance.new("Frame")
+ wrapperFrame.Name = "WrapperFrame"
+ wrapperFrame.BackgroundTransparency = 1
+ wrapperFrame.Size = UDim2.new(1,0,1,0)
+ wrapperFrame.Parent = frame
+
+ for i, child in ipairs(guiObjects) do
+ child.Parent = wrapperFrame
+ end
+
+ local recalculate = function()
+ wait()
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(recalculate)
+
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+end
+
+
+t.CreateSlider = function(steps,width,position)
+ local sliderGui = Instance.new("Frame")
+ sliderGui.Size = UDim2.new(1,0,1,0)
+ sliderGui.BackgroundTransparency = 1
+ sliderGui.Name = "SliderGui"
+
+ local sliderSteps = Instance.new("IntValue")
+ sliderSteps.Name = "SliderSteps"
+ sliderSteps.Value = steps
+ sliderSteps.Parent = sliderGui
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = false
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 4
+
+ sliderGui.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(sliderGui)
+ end
+ end)
+
+ local sliderPosition = Instance.new("IntValue")
+ sliderPosition.Name = "SliderPosition"
+ sliderPosition.Value = 0
+ sliderPosition.Parent = sliderGui
+
+ local id = math.random(1,100)
+
+ local bar = Instance.new("TextButton")
+ bar.Text = ""
+ bar.AutoButtonColor = false
+ bar.Name = "Bar"
+ bar.BackgroundColor3 = Color3.new(0,0,0)
+ if type(width) == "number" then
+ bar.Size = UDim2.new(0,width,0,5)
+ else
+ bar.Size = UDim2.new(0,200,0,5)
+ end
+ bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
+ bar.ZIndex = 2
+ bar.Parent = sliderGui
+
+ if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
+ bar.Position = position
+ end
+
+ local slider = Instance.new("ImageButton")
+ slider.Name = "Slider"
+ slider.BackgroundTransparency = 1
+ slider.Image = "rbxasset://textures/ui/Slider.png"
+ slider.Position = UDim2.new(0,0,0.5,-10)
+ slider.Size = UDim2.new(0,20,0,20)
+ slider.ZIndex = 3
+ slider.Parent = bar
+
+ local areaSoakMouseMoveCon = nil
+
+ areaSoak.MouseLeave:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+ areaSoak.MouseButton1Up:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+
+ slider.MouseButton1Down:connect(function()
+ areaSoak.Visible = true
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+ end)
+
+ slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
+
+ sliderPosition.Changed:connect(function(prop)
+ sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
+ local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end)
+
+ bar.MouseButton1Down:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+
+ return sliderGui, sliderPosition, sliderSteps
+
+end
+
+
+
+t.CreateSliderNew = function(steps,width,position)
+ local sliderGui = Instance.new("Frame")
+ sliderGui.Size = UDim2.new(1,0,1,0)
+ sliderGui.BackgroundTransparency = 1
+ sliderGui.Name = "SliderGui"
+
+ local sliderSteps = Instance.new("IntValue")
+ sliderSteps.Name = "SliderSteps"
+ sliderSteps.Value = steps
+ sliderSteps.Parent = sliderGui
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = false
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 6
+
+ sliderGui.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(sliderGui)
+ end
+ end)
+
+ local sliderPosition = Instance.new("IntValue")
+ sliderPosition.Name = "SliderPosition"
+ sliderPosition.Value = 0
+ sliderPosition.Parent = sliderGui
+
+ local id = math.random(1,100)
+
+ local sliderBarImgHeight = 7
+ local sliderBarCapImgWidth = 4
+
+ local bar = Instance.new("ImageButton")
+ bar.BackgroundTransparency = 1
+ bar.Image = "rbxasset://textures/ui/Slider-BKG-Center.png"
+ bar.Name = "Bar"
+ local displayWidth = 200
+ if type(width) == "number" then
+ bar.Size = UDim2.new(0,width - (sliderBarCapImgWidth * 2),0,sliderBarImgHeight)
+ displayWidth = width - (sliderBarCapImgWidth * 2)
+ else
+ bar.Size = UDim2.new(0,200,0,sliderBarImgHeight)
+ end
+ bar.ZIndex = 3
+ bar.Parent = sliderGui
+ if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
+ bar.Position = position
+ end
+
+ local barLeft = bar:clone()
+ barLeft.Name = "BarLeft"
+ barLeft.Image = "rbxasset://textures/ui/Slider-BKG-Left-Cap.png"
+ barLeft.Size = UDim2.new(0, sliderBarCapImgWidth, 0, sliderBarImgHeight)
+ barLeft.Position = UDim2.new(position.X.Scale, position.X.Offset - sliderBarCapImgWidth, position.Y.Scale, position.Y.Offset)
+ barLeft.Parent = sliderGui
+ barLeft.ZIndex = 3
+
+ local barRight = barLeft:clone()
+ barRight.Name = "BarRight"
+ barRight.Image = "rbxasset://textures/ui/Slider-BKG-Right-Cap.png"
+ barRight.Position = UDim2.new(position.X.Scale, position.X.Offset + displayWidth, position.Y.Scale, position.Y.Offset)
+ barRight.Parent = sliderGui
+
+ local fillLeft = barLeft:clone()
+ fillLeft.Name = "FillLeft"
+ fillLeft.Image = "rbxasset://textures/ui/Slider-Fill-Left-Cap.png"
+ fillLeft.Parent = sliderGui
+ fillLeft.ZIndex = 4
+
+ local fill = fillLeft:clone()
+ fill.Name = "Fill"
+ fill.Image = "rbxasset://textures/ui/Slider-Fill-Center.png"
+ fill.Parent = bar
+ fill.ZIndex = 4
+ fill.Position = UDim2.new(0, 0, 0, 0)
+ fill.Size = UDim2.new(0.5, 0, 1, 0)
+
+
+-- bar.Visible = false
+
+ local slider = Instance.new("ImageButton")
+ slider.Name = "Slider"
+ slider.BackgroundTransparency = 1
+ slider.Image = "rbxasset://textures/ui/slider_new_tab.png"
+ slider.Position = UDim2.new(0,0,0.5,-14)
+ slider.Size = UDim2.new(0,28,0,28)
+ slider.ZIndex = 5
+ slider.Parent = bar
+
+ local areaSoakMouseMoveCon = nil
+
+ areaSoak.MouseLeave:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+ areaSoak.MouseButton1Up:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+
+ slider.MouseButton1Down:connect(function()
+ areaSoak.Visible = true
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+ end)
+
+ slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
+
+ sliderPosition.Changed:connect(function(prop)
+ sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
+ local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ fill.Size = UDim2.new(relativePosX, 0, 1, 0)
+ end)
+
+ bar.MouseButton1Down:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+
+ return sliderGui, sliderPosition, sliderSteps
+
+end
+
+
+
+
+
+t.CreateTrueScrollingFrame = function()
+ local lowY = nil
+ local highY = nil
+
+ local dragCon = nil
+ local upCon = nil
+
+ local internalChange = false
+
+ local descendantsChangeConMap = {}
+
+ local scrollingFrame = Instance.new("Frame")
+ scrollingFrame.Name = "ScrollingFrame"
+ scrollingFrame.Active = true
+ scrollingFrame.Size = UDim2.new(1,0,1,0)
+ scrollingFrame.ClipsDescendants = true
+
+ local controlFrame = Instance.new("Frame")
+ controlFrame.Name = "ControlFrame"
+ controlFrame.BackgroundTransparency = 1
+ controlFrame.Size = UDim2.new(0,18,1,0)
+ controlFrame.Position = UDim2.new(1,-20,0,0)
+ controlFrame.Parent = scrollingFrame
+
+ local scrollBottom = Instance.new("BoolValue")
+ scrollBottom.Value = false
+ scrollBottom.Name = "ScrollBottom"
+ scrollBottom.Parent = controlFrame
+
+ local scrollUp = Instance.new("BoolValue")
+ scrollUp.Value = false
+ scrollUp.Name = "scrollUp"
+ scrollUp.Parent = controlFrame
+
+ local scrollUpButton = Instance.new("TextButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.Text = ""
+ scrollUpButton.AutoButtonColor = false
+ scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
+ scrollUpButton.BorderColor3 = Color3.new(1,1,1)
+ scrollUpButton.BackgroundTransparency = 0.5
+ scrollUpButton.Size = UDim2.new(0,18,0,18)
+ scrollUpButton.ZIndex = 2
+ scrollUpButton.Parent = controlFrame
+ for i = 1, 6 do
+ local triFrame = Instance.new("Frame")
+ triFrame.BorderColor3 = Color3.new(1,1,1)
+ triFrame.Name = "tri" .. tostring(i)
+ triFrame.ZIndex = 3
+ triFrame.BackgroundTransparency = 0.5
+ triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
+ triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
+ triFrame.Parent = scrollUpButton
+ end
+ scrollUpButton.MouseEnter:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.1
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollUpButton.MouseLeave:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.5
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+
+ local scrollDownButton = scrollUpButton:clone()
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.Position = UDim2.new(0,0,1,-18)
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
+ end
+ scrollDownButton.MouseEnter:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.1
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollDownButton.MouseLeave:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.5
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+ scrollDownButton.Parent = controlFrame
+
+ local scrollTrack = Instance.new("Frame")
+ scrollTrack.Name = "ScrollTrack"
+ scrollTrack.BackgroundTransparency = 1
+ scrollTrack.Size = UDim2.new(0,18,1,-38)
+ scrollTrack.Position = UDim2.new(0,0,0,19)
+ scrollTrack.Parent = controlFrame
+
+ local scrollbar = Instance.new("TextButton")
+ scrollbar.BackgroundColor3 = Color3.new(0,0,0)
+ scrollbar.BorderColor3 = Color3.new(1,1,1)
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.AutoButtonColor = false
+ scrollbar.Text = ""
+ scrollbar.Active = true
+ scrollbar.Name = "ScrollBar"
+ scrollbar.ZIndex = 2
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
+ scrollbar.Position = UDim2.new(0,0,0,0)
+ scrollbar.Parent = scrollTrack
+
+ local scrollNub = Instance.new("Frame")
+ scrollNub.Name = "ScrollNub"
+ scrollNub.BorderColor3 = Color3.new(1,1,1)
+ scrollNub.Size = UDim2.new(0,10,0,0)
+ scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
+ scrollNub.ZIndex = 2
+ scrollNub.BackgroundTransparency = 0.5
+ scrollNub.Parent = scrollbar
+
+ local newNub = scrollNub:clone()
+ newNub.Position = UDim2.new(0.5,-5,0.5,-2)
+ newNub.Parent = scrollbar
+
+ local lastNub = scrollNub:clone()
+ lastNub.Position = UDim2.new(0.5,-5,0.5,2)
+ lastNub.Parent = scrollbar
+
+ scrollbar.MouseEnter:connect(function()
+ scrollbar.BackgroundTransparency = 0.1
+ scrollNub.BackgroundTransparency = 0.1
+ newNub.BackgroundTransparency = 0.1
+ lastNub.BackgroundTransparency = 0.1
+ end)
+ scrollbar.MouseLeave:connect(function()
+ scrollbar.BackgroundTransparency = 0.5
+ scrollNub.BackgroundTransparency = 0.5
+ newNub.BackgroundTransparency = 0.5
+ lastNub.BackgroundTransparency = 0.5
+ end)
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local function positionScrollBar(x,y,offset)
+ local oldPos = scrollbar.Position
+
+ if y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+
+ if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+ local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
+ if newScaleYPos + relativeSize > 1 then
+ newScaleYPos = 1 - relativeSize
+ scrollBottom.Value = true
+ scrollUp.Value = false
+ elseif newScaleYPos <= 0 then
+ newScaleYPos = 0
+ scrollUp.Value = true
+ scrollBottom.Value = false
+ else
+ scrollUp.Value = false
+ scrollBottom.Value = false
+ end
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
+
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local function drillDownSetHighLow(instance)
+ if not instance or not instance:IsA("GuiObject") then return end
+ if instance == controlFrame then return end
+ if instance:IsDescendantOf(controlFrame) then return end
+ if not instance.Visible then return end
+
+ if lowY and lowY > instance.AbsolutePosition.Y then
+ lowY = instance.AbsolutePosition.Y
+ elseif not lowY then
+ lowY = instance.AbsolutePosition.Y
+ end
+ if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ local children = instance:GetChildren()
+ for i = 1, #children do
+ drillDownSetHighLow(children[i])
+ end
+ end
+
+ local function resetHighLow()
+ local firstChildren = scrollingFrame:GetChildren()
+
+ for i = 1, #firstChildren do
+ drillDownSetHighLow(firstChildren[i])
+ end
+ end
+
+ local function recalculate()
+ internalChange = true
+
+ local percentFrame = 0
+ if scrollbar.Position.Y.Scale > 0 then
+ if scrollbar.Visible then
+ percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
+ else
+ percentFrame = 0
+ end
+ end
+ if percentFrame > 0.99 then percentFrame = 1 end
+
+ local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
+
+ local guiChildren = scrollingFrame:GetChildren()
+ for i = 1, #guiChildren do
+ if guiChildren[i] ~= controlFrame then
+ guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
+ 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
+ end
+ end
+
+ lowY = nil
+ highY = nil
+ resetHighLow()
+ internalChange = false
+ end
+
+ local function setSliderSizeAndPosition()
+ if not highY or not lowY then return end
+
+ local totalYSpan = math.abs(highY - lowY)
+ if totalYSpan == 0 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ return
+ end
+
+ local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
+ if percentShown >= 1 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+ recalculate()
+ else
+ scrollbar.Visible = true
+ scrollDownButton.Visible = true
+ scrollUpButton.Visible = true
+
+ scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
+ end
+
+ local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
+
+ if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ end
+
+ if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ end
+ end
+
+ local buttonScrollAmountPixels = 7
+ local reentrancyGuardScrollUp = false
+ local function doScrollUp()
+ if reentrancyGuardScrollUp then return end
+
+ reentrancyGuardScrollUp = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollUp = false
+ end
+
+ local reentrancyGuardScrollDown = false
+ local function doScrollDown()
+ if reentrancyGuardScrollDown then return end
+
+ reentrancyGuardScrollDown = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollDown = false
+ end
+
+ local function scrollUp(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local function scrollDown(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ scrollbar.MouseButton1Down:connect(function(x,y)
+ if scrollbar.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollbar.AbsolutePosition.y
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ local prevY = y
+ local reentrancyGuardMouseScroll = false
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ if reentrancyGuardMouseScroll then return end
+
+ reentrancyGuardMouseScroll = true
+ if positionScrollBar(x,y,mouseOffset) then
+ recalculate()
+ end
+ reentrancyGuardMouseScroll = false
+
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ local function heightCheck(instance)
+ if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ setSliderSizeAndPosition()
+ end
+
+ local function highLowRecheck()
+ local oldLowY = lowY
+ local oldHighY = highY
+ lowY = nil
+ highY = nil
+ resetHighLow()
+
+ if (lowY ~= oldLowY) or (highY ~= oldHighY) then
+ setSliderSizeAndPosition()
+ end
+ end
+
+ local function descendantChanged(this, prop)
+ if internalChange then return end
+ if not this.Visible then return end
+
+ if prop == "Size" or prop == "Position" then
+ wait()
+ highLowRecheck()
+ end
+ end
+
+ scrollingFrame.DescendantAdded:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+
+ if instance.Visible then
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end
+
+ descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
+ end)
+
+ scrollingFrame.DescendantRemoving:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+ if descendantsChangeConMap[instance] then
+ descendantsChangeConMap[instance]:disconnect()
+ descendantsChangeConMap[instance] = nil
+ end
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end)
+
+ scrollingFrame.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ if not highY or not lowY then return end
+
+ highLowRecheck()
+ setSliderSizeAndPosition()
+ end
+ end)
+
+ return scrollingFrame, controlFrame
+end
+
+t.CreateScrollingFrame = function(orderList,scrollStyle)
+ local frame = Instance.new("Frame")
+ frame.Name = "ScrollingFrame"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(1,0,1,0)
+
+ local scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+
+
+ local scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+
+ local scrollbar = Instance.new("ImageButton")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, 0, 150)
+
+ local scrollStamp = 0
+
+ local scrollDrag = Instance.new("ImageButton")
+ scrollDrag.Image = "http://www.roblox.com/asset/?id=61367186"
+ scrollDrag.Size = UDim2.new(1, 0, 0, 16)
+ scrollDrag.BackgroundTransparency = 1
+ scrollDrag.Name = "ScrollDrag"
+ scrollDrag.Active = true
+ scrollDrag.Parent = scrollbar
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local style = "simple"
+ if scrollStyle and tostring(scrollStyle) then
+ style = scrollStyle
+ end
+
+ local scrollPosition = 1
+ local rowSize = 0
+ local howManyDisplayed = 0
+
+ local layoutGridScrollBar = function()
+ howManyDisplayed = 0
+ local guiObjects = {}
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ if scrollPosition < 1 then scrollPosition = 1 end
+
+ local totalPixelsY = frame.AbsoluteSize.Y
+ local pixelsRemainingY = frame.AbsoluteSize.Y
+
+ local totalPixelsX = frame.AbsoluteSize.X
+
+ local xCounter = 0
+ local rowSizeCounter = 0
+ local setRowSize = true
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+
+ local currentRowY = 0
+
+ pos = scrollPosition
+ --count up from current scroll position to fill out grid
+ while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ --previous pos was the end of a row
+ if xCounter >= totalPixelsX then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ end
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+ pos = pos + 1
+ end
+ --Count wherever current row left off
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+
+ pos = scrollPosition - 1
+ xCounter = 0
+
+ --objects with varying X,Y dimensions can rarely cause minor errors
+ --rechecking every new scrollPosition is necessary to avoid 100% of errors
+
+ --count backwards from current scrollPosition to see if we can add more rows
+ while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ rowSizeCounter = rowSizeCounter + 1
+ if xCounter >= totalPixelsX then
+ rowSize = rowSizeCounter - 1
+ rowSizeCounter = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ if scrollPosition <= rowSize then
+ scrollPosition = 1
+ break
+ else
+ scrollPosition = scrollPosition - rowSize
+ end
+ currentRowY = 0
+ else
+ break
+ end
+ end
+
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+
+ pos = pos - 1
+ end
+
+ --Do check last time if pos = 0
+ if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
+ scrollPosition = 1
+ end
+
+ xCounter = 0
+ --pos = scrollPosition
+ rowSizeCounter = 0
+ setRowSize = true
+ local lastChildSize = 0
+
+ local xOffset,yOffset = 0
+ if guiObjects[1] then
+ yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
+ xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
+ end
+
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemainingY < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
+ if xCounter + child.AbsoluteSize.X >= totalPixelsX then
+ if setRowSize then
+ rowSize = rowSizeCounter - 1
+ setRowSize = false
+ end
+ xCounter = 0
+ pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
+ end
+ child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
+ xCounter = xCounter + child.AbsoluteSize.X
+ child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
+ if child.Visible then
+ howManyDisplayed = howManyDisplayed + 1
+ end
+ lastChildSize = child.AbsoluteSize
+ end
+ end
+ end
+
+ scrollUpButton.Active = (scrollPosition > 1)
+ if lastChildSize == 0 then
+ scrollDownButton.Active = false
+ else
+ scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
+ end
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+
+ local layoutSimpleScrollBar = function()
+ local guiObjects = {}
+ howManyDisplayed = 0
+
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+ while pixelsBelowScrollbar < totalPixels and pos >= 1 do
+ if pos >= scrollPosition then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ else
+ if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ if scrollPosition <= 1 then
+ scrollPosition = 1
+ break
+ else
+ --local ("Backing up ScrollPosition from -- " ..scrollPosition)
+ scrollPosition = scrollPosition - 1
+ end
+ else
+ break
+ end
+ end
+ pos = pos - 1
+ end
+
+ pos = scrollPosition
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemaining < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ if (pixelsRemaining >= 0) then
+ child.Visible = true
+ howManyDisplayed = howManyDisplayed + 1
+ else
+ child.Visible = false
+ end
+ end
+ end
+ end
+ scrollUpButton.Active = (scrollPosition > 1)
+ scrollDownButton.Active = (pixelsRemaining < 0)
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+ local moveDragger = function()
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ if not scrollDrag.Parent then return end
+
+ local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
+ if dragSizeY < 16 then dragSizeY = 16 end
+ scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
+
+ local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
+ if relativeYPos > 1 then relativeYPos = 1
+ elseif relativeYPos < 0 then relativeYPos = 0 end
+ local absYPos = 0
+
+ if relativeYPos ~= 0 then
+ absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
+ end
+
+ scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
+ end
+
+ local reentrancyGuard = false
+ local recalculate = function()
+ if reentrancyGuard then
+ return
+ end
+ reentrancyGuard = true
+ wait()
+ local success, err = nil
+ if style == "grid" then
+ success, err = pcall(function() layoutGridScrollBar() end)
+ elseif style == "simple" then
+ success, err = pcall(function() layoutSimpleScrollBar() end)
+ end
+ if not success then print(err) end
+ moveDragger()
+ reentrancyGuard = false
+ end
+
+ local doScrollUp = function()
+ scrollPosition = (scrollPosition) - rowSize
+ if scrollPosition < 1 then scrollPosition = 1 end
+ recalculate(nil)
+ end
+
+ local doScrollDown = function()
+ scrollPosition = (scrollPosition) + rowSize
+ recalculate(nil)
+ end
+
+ local scrollUp = function(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local scrollDown = function(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local y = 0
+ scrollDrag.MouseButton1Down:connect(function(x,y)
+ if scrollDrag.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollDrag.AbsolutePosition.y
+ local dragCon
+ local upCon
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ local barAbsPos = scrollbar.AbsolutePosition.y
+ local barAbsSize = scrollbar.AbsoluteSize.y
+
+ local dragAbsSize = scrollDrag.AbsoluteSize.y
+ local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
+ y = y - mouseOffset
+ y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
+ y = y - barAbsPos
+
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ local doublePercent = y/(barAbsSize-dragAbsSize)
+ local rowDiff = rowSize
+ local totalScrollCount = guiObjects - (howManyDisplayed - 1)
+ local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
+ if newScrollPosition < scrollPosition then
+ rowDiff = -rowDiff
+ end
+
+ if newScrollPosition < 1 then
+ newScrollPosition = 1
+ end
+
+ scrollPosition = newScrollPosition
+ recalculate(nil)
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollbar.MouseButton1Down:connect(
+ function(x,y)
+ if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
+ scrollDown(y)
+ elseif y < (scrollDrag.AbsolutePosition.y) then
+ scrollUp(y)
+ end
+ end)
+
+
+ frame.ChildAdded:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.ChildRemoved:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(function() recalculate(nil) end)
+
+ return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
+end
+local function binaryGrow(min, max, fits)
+ if min > max then
+ return min
+ end
+ local biggestLegal = min
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
+ biggestLegal = mid
+
+ --Try growing
+ min = mid + 1
+ else
+ --Doesn't fit, shrink
+ max = mid - 1
+ end
+ end
+ return biggestLegal
+end
+
+
+local function binaryShrink(min, max, fits)
+ if min > max then
+ return min
+ end
+ local smallestLegal = max
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
+ smallestLegal = mid
+
+ --It fits, shrink
+ max = mid - 1
+ else
+ --Doesn't fit, grow
+ min = mid + 1
+ end
+ end
+ return smallestLegal
+end
+
+
+local function getGuiOwner(instance)
+ while instance ~= nil do
+ if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
+ return instance
+ end
+ instance = instance.Parent
+ end
+ return nil
+end
+
+t.AutoTruncateTextObject = function(textLabel)
+ local text = textLabel.Text
+
+ local fullLabel = textLabel:Clone()
+ fullLabel.Name = "Full" .. textLabel.Name
+ fullLabel.BorderSizePixel = 0
+ fullLabel.BackgroundTransparency = 0
+ fullLabel.Text = text
+ fullLabel.TextXAlignment = Enum.TextXAlignment.Center
+ fullLabel.Position = UDim2.new(0,-3,0,0)
+ fullLabel.Size = UDim2.new(0,100,1,0)
+ fullLabel.Visible = false
+ fullLabel.Parent = textLabel
+
+ local shortText = nil
+ local mouseEnterConnection = nil
+ local mouseLeaveConnection= nil
+
+ local checkForResize = function()
+ if getGuiOwner(textLabel) == nil then
+ return
+ end
+ textLabel.Text = text
+ if textLabel.TextFits then
+ --Tear down the rollover if it is active
+ if mouseEnterConnection then
+ mouseEnterConnection:disconnect()
+ mouseEnterConnection = nil
+ end
+ if mouseLeaveConnection then
+ mouseLeaveConnection:disconnect()
+ mouseLeaveConnection = nil
+ end
+ else
+ local len = string.len(text)
+ textLabel.Text = text .. "~"
+
+ --Shrink the text
+ local textSize = binaryGrow(0, len,
+ function(pos)
+ if pos == 0 then
+ textLabel.Text = "~"
+ else
+ textLabel.Text = string.sub(text, 1, pos) .. "~"
+ end
+ return textLabel.TextFits
+ end)
+ shortText = string.sub(text, 1, textSize) .. "~"
+ textLabel.Text = shortText
+
+ --Make sure the fullLabel fits
+ if not fullLabel.TextFits then
+ --Already too small, grow it really bit to start
+ fullLabel.Size = UDim2.new(0, 10000, 1, 0)
+ end
+
+ --Okay, now try to binary shrink it back down
+ local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
+ function(size)
+ fullLabel.Size = UDim2.new(0, size, 1, 0)
+ return fullLabel.TextFits
+ end)
+ fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
+
+ --Now setup the rollover effects, if they are currently off
+ if mouseEnterConnection == nil then
+ mouseEnterConnection = textLabel.MouseEnter:connect(
+ function()
+ fullLabel.ZIndex = textLabel.ZIndex + 1
+ fullLabel.Visible = true
+ --textLabel.Text = ""
+ end)
+ end
+ if mouseLeaveConnection == nil then
+ mouseLeaveConnection = textLabel.MouseLeave:connect(
+ function()
+ fullLabel.Visible = false
+ --textLabel.Text = shortText
+ end)
+ end
+ end
+ end
+ textLabel.AncestryChanged:connect(checkForResize)
+ textLabel.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ checkForResize()
+ end
+ end)
+
+ checkForResize()
+
+ local function changeText(newText)
+ text = newText
+ fullLabel.Text = text
+ checkForResize()
+ end
+
+ return textLabel, changeText
+end
+
+local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
+ if fromPage then
+ fromPage.Visible = false
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = fromPage.Size
+ transitionFrame.Position = fromPage.Position
+ end
+ else
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
+ transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
+ end
+ end
+ transitionFrame.Visible = true
+ currentPageValue.Value = nil
+
+ local newsize, newPosition
+ if toPage then
+ --Make it visible so it resizes
+ toPage.Visible = true
+
+ newSize = toPage.Size
+ newPosition = toPage.Position
+
+ toPage.Visible = false
+ else
+ newSize = UDim2.new(0.0,50,0.0,50)
+ newPosition = UDim2.new(0.5,-25,0.5,-25)
+ end
+ transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
+ function(state)
+ if state == Enum.TweenStatus.Completed then
+ transitionFrame.Visible = false
+ if toPage then
+ toPage.Visible = true
+ currentPageValue.Value = toPage
+ end
+ end
+ end)
+end
+
+t.CreateTutorial = function(name, tutorialKey, createButtons)
+ local frame = Instance.new("Frame")
+ frame.Name = "Tutorial-" .. name
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+
+ local transitionFrame = Instance.new("Frame")
+ transitionFrame.Name = "TransitionFrame"
+ transitionFrame.Style = Enum.FrameStyle.RobloxRound
+ transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ transitionFrame.Visible = false
+ transitionFrame.Parent = frame
+
+ local currentPageValue = Instance.new("ObjectValue")
+ currentPageValue.Name = "CurrentTutorialPage"
+ currentPageValue.Value = nil
+ currentPageValue.Parent = frame
+
+ local boolValue = Instance.new("BoolValue")
+ boolValue.Name = "Buttons"
+ boolValue.Value = createButtons
+ boolValue.Parent = frame
+
+ local pages = Instance.new("Frame")
+ pages.Name = "Pages"
+ pages.BackgroundTransparency = 1
+ pages.Size = UDim2.new(1,0,1,0)
+ pages.Parent = frame
+
+ local function getVisiblePageAndHideOthers()
+ local visiblePage = nil
+ local children = pages:GetChildren()
+ if children then
+ for i,child in ipairs(children) do
+ if child.Visible then
+ if visiblePage then
+ child.Visible = false
+ else
+ visiblePage = child
+ end
+ end
+ end
+ end
+ return visiblePage
+ end
+
+ local showTutorial = function(alwaysShow)
+ if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
+ print("Showing tutorial-",tutorialKey)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ local firstPage = pages:FindFirstChild("TutorialPage1")
+ if firstPage then
+ TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
+ else
+ error("Could not find TutorialPage1")
+ end
+ end
+ end
+
+ local dismissTutorial = function()
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ if currentTutorialPage then
+ TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
+ end
+
+ UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
+ end
+
+ local gotoPage = function(pageNum)
+ local page = pages:FindFirstChild("TutorialPage" .. pageNum)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+ TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
+ end
+
+ return frame, showTutorial, dismissTutorial, gotoPage
+end
+
+local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
+ local frame = Instance.new("Frame")
+ frame.Name = "TutorialPage"
+ frame.Style = Enum.FrameStyle.RobloxRound
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ frame.Visible = false
+
+ local frameHeader = Instance.new("TextLabel")
+ frameHeader.Name = "Header"
+ frameHeader.Text = name
+ frameHeader.BackgroundTransparency = 1
+ frameHeader.FontSize = Enum.FontSize.Size24
+ frameHeader.Font = Enum.Font.ArialBold
+ frameHeader.TextColor3 = Color3.new(1,1,1)
+ frameHeader.TextXAlignment = Enum.TextXAlignment.Center
+ frameHeader.TextWrap = true
+ frameHeader.Size = UDim2.new(1,-55, 0, 22)
+ frameHeader.Position = UDim2.new(0,0,0,0)
+ frameHeader.Parent = frame
+
+ local skipButton = Instance.new("ImageButton")
+ skipButton.Name = "SkipButton"
+ skipButton.AutoButtonColor = false
+ skipButton.BackgroundTransparency = 1
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ skipButton.MouseButton1Click:connect(function()
+ skipTutorial()
+ end)
+ skipButton.MouseEnter:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
+ end)
+ skipButton.MouseLeave:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ end)
+ skipButton.Size = UDim2.new(0, 25, 0, 25)
+ skipButton.Position = UDim2.new(1, -25, 0, 0)
+ skipButton.Parent = frame
+
+
+ if giveDoneButton then
+ local doneButton = Instance.new("TextButton")
+ doneButton.Name = "DoneButton"
+ doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ doneButton.Text = "Done"
+ doneButton.TextColor3 = Color3.new(1,1,1)
+ doneButton.Font = Enum.Font.ArialBold
+ doneButton.FontSize = Enum.FontSize.Size18
+ doneButton.Size = UDim2.new(0,100,0,50)
+ doneButton.Position = UDim2.new(0.5,-50,1,-50)
+
+ if skipTutorial then
+ doneButton.MouseButton1Click:connect(function() skipTutorial() end)
+ end
+
+ doneButton.Parent = frame
+ end
+
+ local innerFrame = Instance.new("Frame")
+ innerFrame.Name = "ContentFrame"
+ innerFrame.BackgroundTransparency = 1
+ innerFrame.Position = UDim2.new(0,0,0,25)
+ innerFrame.Parent = frame
+
+ local nextButton = Instance.new("TextButton")
+ nextButton.Name = "NextButton"
+ nextButton.Text = "Next"
+ nextButton.TextColor3 = Color3.new(1,1,1)
+ nextButton.Font = Enum.Font.Arial
+ nextButton.FontSize = Enum.FontSize.Size18
+ nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ nextButton.Size = UDim2.new(0,80, 0, 32)
+ nextButton.Position = UDim2.new(0.5, 5, 1, -32)
+ nextButton.Active = false
+ nextButton.Visible = false
+ nextButton.Parent = frame
+
+ local prevButton = Instance.new("TextButton")
+ prevButton.Name = "PrevButton"
+ prevButton.Text = "Previous"
+ prevButton.TextColor3 = Color3.new(1,1,1)
+ prevButton.Font = Enum.Font.Arial
+ prevButton.FontSize = Enum.FontSize.Size18
+ prevButton.Style = Enum.ButtonStyle.RobloxButton
+ prevButton.Size = UDim2.new(0,80, 0, 32)
+ prevButton.Position = UDim2.new(0.5, -85, 1, -32)
+ prevButton.Active = false
+ prevButton.Visible = false
+ prevButton.Parent = frame
+
+ if giveDoneButton then
+ innerFrame.Size = UDim2.new(1,0,1,-75)
+ else
+ innerFrame.Size = UDim2.new(1,0,1,-22)
+ end
+
+ local parentConnection = nil
+
+ local function basicHandleResize()
+ if frame.Visible and frame.Parent then
+ local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
+ handleResize(200,maxSize)
+ end
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "Parent" then
+ if parentConnection ~= nil then
+ parentConnection:disconnect()
+ parentConnection = nil
+ end
+ if frame.Parent and frame.Parent:IsA("GuiObject") then
+ parentConnection = frame.Parent.Changed:connect(
+ function(parentProp)
+ if parentProp == "AbsoluteSize" then
+ wait()
+ basicHandleResize()
+ end
+ end)
+ basicHandleResize()
+ end
+ end
+
+ if prop == "Visible" then
+ basicHandleResize()
+ end
+ end)
+
+ return frame, innerFrame
+end
+
+t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
+ local frame = nil
+ local contentFrame = nil
+
+ local textLabel = Instance.new("TextLabel")
+ textLabel.BackgroundTransparency = 1
+ textLabel.TextColor3 = Color3.new(1,1,1)
+ textLabel.Text = text
+ textLabel.TextWrap = true
+ textLabel.TextXAlignment = Enum.TextXAlignment.Left
+ textLabel.TextYAlignment = Enum.TextYAlignment.Center
+ textLabel.Font = Enum.Font.Arial
+ textLabel.FontSize = Enum.FontSize.Size14
+ textLabel.Size = UDim2.new(1,0,1,0)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ frame.Size = UDim2.new(0, size, 0, size)
+ return textLabel.TextFits
+ end)
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
+ textLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
+ local frame = nil
+ local contentFrame = nil
+
+ local imageLabel = Instance.new("ImageLabel")
+ imageLabel.BackgroundTransparency = 1
+ imageLabel.Image = imageAsset
+ imageLabel.Size = UDim2.new(0,x,0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ return size >= x and size >= y
+ end)
+ if size >= x and size >= y then
+ imageLabel.Size = UDim2.new(0,x, 0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
+ else
+ if x > y then
+ --X is limiter, so
+ imageLabel.Size = UDim2.new(1,0,y/x,0)
+ imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
+ else
+ --Y is limiter
+ imageLabel.Size = UDim2.new(x/y,0,1, 0)
+ imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
+ end
+ end
+ size = size + 50
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
+ imageLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.AddTutorialPage = function(tutorial, tutorialPage)
+ local transitionFrame = tutorial.TransitionFrame
+ local currentPageValue = tutorial.CurrentTutorialPage
+
+ if not tutorial.Buttons.Value then
+ tutorialPage.NextButton.Parent = nil
+ tutorialPage.PrevButton.Parent = nil
+ end
+
+ local children = tutorial.Pages:GetChildren()
+ if children and #children > 0 then
+ tutorialPage.Name = "TutorialPage" .. (#children+1)
+ local previousPage = children[#children]
+ if not previousPage:IsA("GuiObject") then
+ error("All elements under Pages must be GuiObjects")
+ end
+
+ if tutorial.Buttons.Value then
+ if previousPage.NextButton.Active then
+ error("NextButton already Active on previousPage, please only add pages with t.AddTutorialPage function")
+ end
+ previousPage.NextButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
+ end)
+ previousPage.NextButton.Active = true
+ previousPage.NextButton.Visible = true
+
+ if tutorialPage.PrevButton.Active then
+ error("PrevButton already Active on tutorialPage, please only add pages with t.AddTutorialPage function")
+ end
+ tutorialPage.PrevButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
+ end)
+ tutorialPage.PrevButton.Active = true
+ tutorialPage.PrevButton.Visible = true
+ end
+
+ tutorialPage.Parent = tutorial.Pages
+ else
+ --First child
+ tutorialPage.Name = "TutorialPage1"
+ tutorialPage.Parent = tutorial.Pages
+ end
+end
+
+t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
+
+ if not userIdsForSets then
+ error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
+ end
+ if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
+ error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
+ end
+ if not objectSelected then
+ error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
+ end
+ if type(objectSelected) ~= "function" then
+ error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
+ end
+ if dialogClosed and type(dialogClosed) ~= "function" then
+ error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
+ end
+
+ if showAdminCategories == nil then -- by default, don't show beta sets
+ showAdminCategories = false
+ end
+
+ local arrayPosition = 1
+ local insertButtons = {}
+ local insertButtonCons = {}
+ local contents = nil
+ local setGui = nil
+
+ -- used for water selections
+ local waterForceDirection = "NegX"
+ local waterForce = "None"
+ local waterGui, waterTypeChangedEvent = nil
+
+ local Data = {}
+ Data.CurrentCategory = nil
+ Data.Category = {}
+ local SetCache = {}
+
+ local userCategoryButtons = nil
+
+ local buttonWidth = 64
+ local buttonHeight = buttonWidth
+
+ local SmallThumbnailUrl = nil
+ local LargeThumbnailUrl = nil
+ local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
+
+ if useAssetVersionId then
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
+ else
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
+ end
+
+ local function drillDownSetZIndex(parent, index)
+ local children = parent:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("GuiObject") then
+ children[i].ZIndex = index
+ end
+ drillDownSetZIndex(children[i], index)
+ end
+ end
+
+ -- for terrain stamping
+ local currTerrainDropDownFrame = nil
+ local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
+ local terrainShapeMap = {}
+ for i = 1, #terrainShapes do
+ terrainShapeMap[terrainShapes[i]] = i - 1
+ end
+ terrainShapeMap[terrainShapes[#terrainShapes]] = 6
+
+ local function createWaterGui()
+ local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
+ local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
+
+ local waterFrame = Instance.new("Frame")
+ waterFrame.Name = "WaterFrame"
+ waterFrame.Style = Enum.FrameStyle.RobloxSquare
+ waterFrame.Size = UDim2.new(0,150,0,110)
+ waterFrame.Visible = false
+
+ local waterForceLabel = Instance.new("TextLabel")
+ waterForceLabel.Name = "WaterForceLabel"
+ waterForceLabel.BackgroundTransparency = 1
+ waterForceLabel.Size = UDim2.new(1,0,0,12)
+ waterForceLabel.Font = Enum.Font.ArialBold
+ waterForceLabel.FontSize = Enum.FontSize.Size12
+ waterForceLabel.TextColor3 = Color3.new(1,1,1)
+ waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
+ waterForceLabel.Text = "Water Force"
+ waterForceLabel.Parent = waterFrame
+
+ local waterForceDirLabel = waterForceLabel:Clone()
+ waterForceDirLabel.Name = "WaterForceDirectionLabel"
+ waterForceDirLabel.Text = "Water Force Direction"
+ waterForceDirLabel.Position = UDim2.new(0,0,0,50)
+ waterForceDirLabel.Parent = waterFrame
+
+ local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
+ waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
+
+ local waterForceDirectionSelectedFunc = function(newForceDirection)
+ waterForceDirection = newForceDirection
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+ local waterForceSelectedFunc = function(newForce)
+ waterForce = newForce
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+
+ local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
+ waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
+ forceWaterDirectionSelection("NegX")
+ waterForceDirectionDropDown.Parent = waterForceDirLabel
+
+ local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
+ forceWaterForceSelection("None")
+ waterForceDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDropDown.Position = UDim2.new(0,0,1,3)
+ waterForceDropDown.Parent = waterForceLabel
+
+ return waterFrame, waterTypeChangedEvent
+ end
+
+ -- Helper Function that contructs gui elements
+ local function createSetGui()
+
+ local setGui = Instance.new("ScreenGui")
+ setGui.Name = "SetGui"
+
+ local setPanel = Instance.new("Frame")
+ setPanel.Name = "SetPanel"
+ setPanel.Active = true
+ setPanel.BackgroundTransparency = 1
+ if position then
+ setPanel.Position = position
+ else
+ setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
+ end
+ if size then
+ setPanel.Size = size
+ else
+ setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
+ end
+ setPanel.Style = Enum.FrameStyle.RobloxRound
+ setPanel.ZIndex = 6
+ setPanel.Parent = setGui
+
+ -- Children of SetPanel
+ local itemPreview = Instance.new("Frame")
+ itemPreview.Name = "ItemPreview"
+ itemPreview.BackgroundTransparency = 1
+ itemPreview.Position = UDim2.new(0.8,5,0.085,0)
+ itemPreview.Size = UDim2.new(0.21,0,0.9,0)
+ itemPreview.ZIndex = 6
+ itemPreview.Parent = setPanel
+
+ -- Children of ItemPreview
+ local textPanel = Instance.new("Frame")
+ textPanel.Name = "TextPanel"
+ textPanel.BackgroundTransparency = 1
+ textPanel.Position = UDim2.new(0,0,0.45,0)
+ textPanel.Size = UDim2.new(1,0,0.55,0)
+ textPanel.ZIndex = 6
+ textPanel.Parent = itemPreview
+
+ -- Children of TextPanel
+ local rolloverText = Instance.new("TextLabel")
+ rolloverText.Name = "RolloverText"
+ rolloverText.BackgroundTransparency = 1
+ rolloverText.Size = UDim2.new(1,0,0,48)
+ rolloverText.ZIndex = 6
+ rolloverText.Font = Enum.Font.ArialBold
+ rolloverText.FontSize = Enum.FontSize.Size24
+ rolloverText.Text = ""
+ rolloverText.TextColor3 = Color3.new(1,1,1)
+ rolloverText.TextWrap = true
+ rolloverText.TextXAlignment = Enum.TextXAlignment.Left
+ rolloverText.TextYAlignment = Enum.TextYAlignment.Top
+ rolloverText.Parent = textPanel
+
+ local largePreview = Instance.new("ImageLabel")
+ largePreview.Name = "LargePreview"
+ largePreview.BackgroundTransparency = 1
+ largePreview.Image = ""
+ largePreview.Size = UDim2.new(1,0,0,170)
+ largePreview.ZIndex = 6
+ largePreview.Parent = itemPreview
+
+ local sets = Instance.new("Frame")
+ sets.Name = "Sets"
+ sets.BackgroundTransparency = 1
+ sets.Position = UDim2.new(0,0,0,5)
+ sets.Size = UDim2.new(0.23,0,1,-5)
+ sets.ZIndex = 6
+ sets.Parent = setPanel
+
+ -- Children of Sets
+ local line = Instance.new("Frame")
+ line.Name = "Line"
+ line.BackgroundColor3 = Color3.new(1,1,1)
+ line.BackgroundTransparency = 0.7
+ line.BorderSizePixel = 0
+ line.Position = UDim2.new(1,-3,0.06,0)
+ line.Size = UDim2.new(0,3,0.9,0)
+ line.ZIndex = 6
+ line.Parent = sets
+
+ local setsLists, controlFrame = t.CreateTrueScrollingFrame()
+ setsLists.Size = UDim2.new(1,-6,0.94,0)
+ setsLists.Position = UDim2.new(0,0,0.06,0)
+ setsLists.BackgroundTransparency = 1
+ setsLists.Name = "SetsLists"
+ setsLists.ZIndex = 6
+ setsLists.Parent = sets
+ drillDownSetZIndex(controlFrame, 7)
+
+ local setsHeader = Instance.new("TextLabel")
+ setsHeader.Name = "SetsHeader"
+ setsHeader.BackgroundTransparency = 1
+ setsHeader.Size = UDim2.new(0,47,0,24)
+ setsHeader.ZIndex = 6
+ setsHeader.Font = Enum.Font.ArialBold
+ setsHeader.FontSize = Enum.FontSize.Size24
+ setsHeader.Text = "Sets"
+ setsHeader.TextColor3 = Color3.new(1,1,1)
+ setsHeader.TextXAlignment = Enum.TextXAlignment.Left
+ setsHeader.TextYAlignment = Enum.TextYAlignment.Top
+ setsHeader.Parent = sets
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(1,-32,0,-2)
+ cancelButton.Size = UDim2.new(0,34,0,34)
+ cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ cancelButton.ZIndex = 6
+ cancelButton.Text = ""
+ cancelButton.Modal = true
+ cancelButton.Parent = setPanel
+
+ -- Children of Cancel Button
+ local cancelImage = Instance.new("ImageLabel")
+ cancelImage.Name = "CancelImage"
+ cancelImage.BackgroundTransparency = 1
+ cancelImage.Image = "http://www.roblox.com/asset/?id=54135717"
+ cancelImage.Position = UDim2.new(0,-2,0,-2)
+ cancelImage.Size = UDim2.new(0,16,0,16)
+ cancelImage.ZIndex = 6
+ cancelImage.Parent = cancelButton
+
+ return setGui
+ end
+
+ local function createSetButton(text)
+ local setButton = Instance.new("TextButton")
+
+ if text then setButton.Text = text
+ else setButton.Text = "" end
+
+ setButton.AutoButtonColor = false
+ setButton.BackgroundTransparency = 1
+ setButton.BackgroundColor3 = Color3.new(1,1,1)
+ setButton.BorderSizePixel = 0
+ setButton.Size = UDim2.new(1,-5,0,18)
+ setButton.ZIndex = 6
+ setButton.Visible = false
+ setButton.Font = Enum.Font.Arial
+ setButton.FontSize = Enum.FontSize.Size18
+ setButton.TextColor3 = Color3.new(1,1,1)
+ setButton.TextXAlignment = Enum.TextXAlignment.Left
+
+ return setButton
+ end
+
+ local function buildSetButton(name, setId, setImageId, i, count)
+ local button = createSetButton(name)
+ button.Text = name
+ button.Name = "SetButton"
+ button.Visible = true
+
+ local setValue = Instance.new("IntValue")
+ setValue.Name = "SetId"
+ setValue.Value = setId
+ setValue.Parent = button
+
+ local setName = Instance.new("StringValue")
+ setName.Name = "SetName"
+ setName.Value = name
+ setName.Parent = button
+
+ return button
+ end
+
+ local function processCategory(sets)
+ local setButtons = {}
+ local numSkipped = 0
+ for i = 1, #sets do
+ if not showAdminCategories and sets[i].Name == "Beta" then
+ numSkipped = numSkipped + 1
+ else
+ setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
+ end
+ end
+ return setButtons
+ end
+
+ local function handleResize()
+ wait() -- neccessary to insure heartbeat happened
+
+ local itemPreview = setGui.SetPanel.ItemPreview
+
+ itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
+ itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
+ itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
+ itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
+ end
+
+ local function makeInsertAssetButton()
+ local insertAssetButtonExample = Instance.new("Frame")
+ insertAssetButtonExample.Name = "InsertAssetButtonExample"
+ insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
+ insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
+ insertAssetButtonExample.BackgroundTransparency = 1
+ insertAssetButtonExample.ZIndex = 6
+ insertAssetButtonExample.Visible = false
+
+ local assetId = Instance.new("IntValue")
+ assetId.Name = "AssetId"
+ assetId.Value = 0
+ assetId.Parent = insertAssetButtonExample
+
+ local assetName = Instance.new("StringValue")
+ assetName.Name = "AssetName"
+ assetName.Value = ""
+ assetName.Parent = insertAssetButtonExample
+
+ local button = Instance.new("TextButton")
+ button.Name = "Button"
+ button.Text = ""
+ button.Style = Enum.ButtonStyle.RobloxButton
+ button.Position = UDim2.new(0.025,0,0.025,0)
+ button.Size = UDim2.new(0.95,0,0.95,0)
+ button.ZIndex = 6
+ button.Parent = insertAssetButtonExample
+
+ local buttonImage = Instance.new("ImageLabel")
+ buttonImage.Name = "ButtonImage"
+ buttonImage.Image = ""
+ buttonImage.Position = UDim2.new(0,-7,0,-7)
+ buttonImage.Size = UDim2.new(1,14,1,14)
+ buttonImage.BackgroundTransparency = 1
+ buttonImage.ZIndex = 7
+ buttonImage.Parent = button
+
+ local configIcon = buttonImage:clone()
+ configIcon.Name = "ConfigIcon"
+ configIcon.Visible = false
+ configIcon.Position = UDim2.new(1,-23,1,-24)
+ configIcon.Size = UDim2.new(0,16,0,16)
+ configIcon.Image = ""
+ configIcon.ZIndex = 6
+ configIcon.Parent = insertAssetButtonExample
+
+ return insertAssetButtonExample
+ end
+
+ local function showLargePreview(insertButton)
+ if insertButton:FindFirstChild("AssetId") then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
+ setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
+ end)
+ end
+ if insertButton:FindFirstChild("AssetName") then
+ setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
+ end
+ end
+
+ local function selectTerrainShape(shape)
+ if currTerrainDropDownFrame then
+ objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
+ end
+ end
+
+ local function createTerrainTypeButton(name, parent)
+ local dropDownTextButton = Instance.new("TextButton")
+ dropDownTextButton.Name = name .. "Button"
+ dropDownTextButton.Font = Enum.Font.ArialBold
+ dropDownTextButton.FontSize = Enum.FontSize.Size14
+ dropDownTextButton.BorderSizePixel = 0
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ dropDownTextButton.Text = name
+ dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.ZIndex = parent.ZIndex + 1
+ dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
+ dropDownTextButton.Position = UDim2.new(0,1,0,0)
+
+ dropDownTextButton.MouseEnter:connect(function()
+ dropDownTextButton.BackgroundTransparency = 0
+ dropDownTextButton.TextColor3 = Color3.new(0,0,0)
+ end)
+
+ dropDownTextButton.MouseLeave:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ end)
+
+ dropDownTextButton.MouseButton1Click:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
+ dropDownTextButton.Parent.Visible = false
+ end
+ selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
+ end)
+
+ return dropDownTextButton
+ end
+
+ local function createTerrainDropDownMenu(zIndex)
+ local dropDown = Instance.new("Frame")
+ dropDown.Name = "TerrainDropDown"
+ dropDown.BackgroundColor3 = Color3.new(0,0,0)
+ dropDown.BorderColor3 = Color3.new(1,0,0)
+ dropDown.Size = UDim2.new(0,200,0,0)
+ dropDown.Visible = false
+ dropDown.ZIndex = zIndex
+ dropDown.Parent = setGui
+
+ for i = 1, #terrainShapes do
+ local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
+ shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
+ shapeButton.Parent = dropDown
+ dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
+ end
+
+ dropDown.MouseLeave:connect(function()
+ dropDown.Visible = false
+ end)
+ end
+
+
+ local function createDropDownMenuButton(parent)
+ local dropDownButton = Instance.new("ImageButton")
+ dropDownButton.Name = "DropDownButton"
+ dropDownButton.Image = "http://www.roblox.com/asset/?id=67581509"
+ dropDownButton.BackgroundTransparency = 1
+ dropDownButton.Size = UDim2.new(0,16,0,16)
+ dropDownButton.Position = UDim2.new(1,-24,0,6)
+ dropDownButton.ZIndex = parent.ZIndex + 2
+ dropDownButton.Parent = parent
+
+ if not setGui:FindFirstChild("TerrainDropDown") then
+ createTerrainDropDownMenu(8)
+ end
+
+ dropDownButton.MouseButton1Click:connect(function()
+ setGui.TerrainDropDown.Visible = true
+ setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
+ currTerrainDropDownFrame = parent
+ end)
+ end
+
+ local function buildInsertButton()
+ local insertButton = makeInsertAssetButton()
+ insertButton.Name = "InsertAssetButton"
+ insertButton.Visible = true
+
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ createDropDownMenuButton(insertButton)
+ end
+
+ local lastEnter = nil
+ local mouseEnterCon = insertButton.MouseEnter:connect(function()
+ lastEnter = insertButton
+ delay(0.1,function()
+ if lastEnter == insertButton then
+ showLargePreview(insertButton)
+ end
+ end)
+ end)
+ return insertButton, mouseEnterCon
+ end
+
+ local function realignButtonGrid(columns)
+ local x = 0
+ local y = 0
+ for i = 1, #insertButtons do
+ insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
+ x = x + 1
+ if x >= columns then
+ x = 0
+ y = y + 1
+ end
+ end
+ end
+
+ local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
+ if visible then
+ insertFrame.AssetName.Value = name
+ insertFrame.AssetId.Value = assetId
+ local newImageUrl = SmallThumbnailUrl .. assetId
+ if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
+ if insertFrame:findFirstChild("Button") then
+ insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
+ end
+ end)
+ end
+ table.insert(insertButtonCons,
+ insertFrame.Button.MouseButton1Click:connect(function()
+ -- special case for water, show water selection gui
+ local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
+ waterGui.Visible = isWaterSelected
+ if isWaterSelected then
+ objectSelected(name, tonumber(assetId), nil)
+ else
+ objectSelected(name, tonumber(assetId))
+ end
+ end)
+ )
+ insertFrame.Visible = true
+ else
+ insertFrame.Visible = false
+ end
+ end
+
+ local function loadSectionOfItems(setGui, rows, columns)
+ local pageSize = rows * columns
+
+ if arrayPosition > #contents then return end
+
+ local origArrayPos = arrayPosition
+
+ local yCopy = 0
+ for i = 1, pageSize + 1 do
+ if arrayPosition >= #contents + 1 then
+ break
+ end
+
+ local buttonCon
+ insertButtons[arrayPosition], buttonCon = buildInsertButton()
+ table.insert(insertButtonCons,buttonCon)
+ insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
+ arrayPosition = arrayPosition + 1
+ end
+ realignButtonGrid(columns)
+
+ local indexCopy = origArrayPos
+ for index = origArrayPos, arrayPosition do
+ if insertButtons[index] then
+ if contents[index] then
+
+ -- we don't want water to have a drop down button
+ if contents[index].Name == "Water" then
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
+ end
+ end
+
+ local assetId
+ if useAssetVersionId then
+ assetId = contents[index].AssetVersionId
+ else
+ assetId = contents[index].AssetId
+ end
+ setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
+ else
+ break
+ end
+ else
+ break
+ end
+ indexCopy = index
+ end
+ end
+
+ local function setSetIndex()
+ Data.Category[Data.CurrentCategory].Index = 0
+
+ rows = 7
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ contents = Data.Category[Data.CurrentCategory].Contents
+ if contents then
+ -- remove our buttons and their connections
+ for i = 1, #insertButtons do
+ insertButtons[i]:remove()
+ end
+ for i = 1, #insertButtonCons do
+ if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
+ end
+ insertButtonCons = {}
+ insertButtons = {}
+
+ arrayPosition = 1
+ loadSectionOfItems(setGui, rows, columns)
+ end
+ end
+
+ local function selectSet(button, setName, setId, setIndex)
+ if button and Data.Category[Data.CurrentCategory] ~= nil then
+ if button ~= Data.Category[Data.CurrentCategory].Button then
+ Data.Category[Data.CurrentCategory].Button = button
+
+ if SetCache[setId] == nil then
+ SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
+ end
+ Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
+
+ Data.Category[Data.CurrentCategory].SetName = setName
+ Data.Category[Data.CurrentCategory].SetId = setId
+ end
+ setSetIndex()
+ end
+ end
+
+ local function selectCategoryPage(buttons, page)
+ if buttons ~= Data.CurrentCategory then
+ if Data.CurrentCategory then
+ for key, button in pairs(Data.CurrentCategory) do
+ button.Visible = false
+ end
+ end
+
+ Data.CurrentCategory = buttons
+ if Data.Category[Data.CurrentCategory] == nil then
+ Data.Category[Data.CurrentCategory] = {}
+ if #buttons > 0 then
+ selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
+ end
+ else
+ Data.Category[Data.CurrentCategory].Button = nil
+ selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
+ end
+ end
+ end
+
+ local function selectCategory(category)
+ selectCategoryPage(category, 0)
+ end
+
+ local function resetAllSetButtonSelection()
+ local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+ for i = 1, #setButtons do
+ if setButtons[i]:IsA("TextButton") then
+ setButtons[i].Selected = false
+ setButtons[i].BackgroundTransparency = 1
+ setButtons[i].TextColor3 = Color3.new(1,1,1)
+ setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
+ end
+ end
+ end
+
+ local function populateSetsFrame()
+ local currRow = 0
+ for i = 1, #userCategoryButtons do
+ local button = userCategoryButtons[i]
+ button.Visible = true
+ button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
+ button.Parent = setGui.SetPanel.Sets.SetsLists
+
+ if i == 1 then -- we will have this selected by default, so show it
+ button.Selected = true
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ end
+
+ button.MouseEnter:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 0
+ button.TextColor3 = Color3.new(0,0,0)
+ end
+ end)
+ button.MouseLeave:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 1
+ button.TextColor3 = Color3.new(1,1,1)
+ end
+ end)
+ button.MouseButton1Click:connect(function()
+ resetAllSetButtonSelection()
+ button.Selected = not button.Selected
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
+ end)
+
+ currRow = currRow + 1
+ end
+
+ local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+
+ -- set first category as loaded for default
+ if buttons then
+ for i = 1, #buttons do
+ if buttons[i]:IsA("TextButton") then
+ selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
+ selectCategory(userCategoryButtons)
+ break
+ end
+ end
+ end
+ end
+
+ setGui = createSetGui()
+ waterGui, waterTypeChangedEvent = createWaterGui()
+ waterGui.Position = UDim2.new(0,55,0,0)
+ waterGui.Parent = setGui
+ setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
+ if prop == "AbsoluteSize" then
+ handleResize()
+ setSetIndex()
+ end
+ end)
+
+ local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
+ scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
+ scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
+ scrollFrame.Name = "ItemsFrame"
+ scrollFrame.ZIndex = 6
+ scrollFrame.Parent = setGui.SetPanel
+ scrollFrame.BackgroundTransparency = 1
+
+ drillDownSetZIndex(controlFrame,7)
+
+ controlFrame.Parent = setGui.SetPanel
+ controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
+
+ local debounce = false
+ controlFrame.ScrollBottom.Changed:connect(function(prop)
+ if controlFrame.ScrollBottom.Value == true then
+ if debounce then return end
+ debounce = true
+ loadSectionOfItems(setGui, rows, columns)
+ debounce = false
+ end
+ end)
+
+ local userData = {}
+ for id = 1, #userIdsForSets do
+ local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
+ if newUserData and #newUserData > 2 then
+ -- start at #3 to skip over My Decals and My Models for each account
+ for category = 3, #newUserData do
+ if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
+ table.insert(userData,1,newUserData[category])
+ else
+ table.insert(userData, newUserData[category])
+ end
+ end
+ end
+
+ end
+ if userData then
+ userCategoryButtons = processCategory(userData)
+ end
+
+ rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ populateSetsFrame()
+
+ insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
+ setGui.SetPanel.Visible = false
+ if dialogClosed then dialogClosed() end
+ end)
+
+ local setVisibilityFunction = function(visible)
+ if visible then
+ setGui.SetPanel.Visible = true
+ else
+ setGui.SetPanel.Visible = false
+ end
+ end
+
+ local getVisibilityFunction = function()
+ if setGui then
+ if setGui:FindFirstChild("SetPanel") then
+ return setGui.SetPanel.Visible
+ end
+ end
+
+ return false
+ end
+
+ return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
+end
+
+t.CreateTerrainMaterialSelector = function(size,position)
+ local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
+ terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
+
+ local selectedButton = nil
+
+ local frame = Instance.new("Frame")
+ frame.Name = "TerrainMaterialSelector"
+ if size then
+ frame.Size = size
+ else
+ frame.Size = UDim2.new(0, 245, 0, 230)
+ end
+ if position then
+ frame.Position = position
+ end
+ frame.BorderSizePixel = 0
+ frame.BackgroundColor3 = Color3.new(0,0,0)
+ frame.Active = true
+
+ terrainMaterialSelectionChanged.Parent = frame
+
+ local waterEnabled = true -- todo: turn this on when water is ready
+
+ local materialToImageMap = {}
+ local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
+ if waterEnabled then
+ table.insert(materialNames,"Water")
+ end
+ local currentMaterial = 1
+
+ function getEnumFromName(choice)
+ if choice == "Grass" then return 1 end
+ if choice == "Sand" then return 2 end
+ if choice == "Erase" then return 0 end
+ if choice == "Brick" then return 3 end
+ if choice == "Granite" then return 4 end
+ if choice == "Asphalt" then return 5 end
+ if choice == "Iron" then return 6 end
+ if choice == "Aluminum" then return 7 end
+ if choice == "Gold" then return 8 end
+ if choice == "Plank" then return 9 end
+ if choice == "Log" then return 10 end
+ if choice == "Gravel" then return 11 end
+ if choice == "Cinder Block" then return 12 end
+ if choice == "Stone Wall" then return 13 end
+ if choice == "Concrete" then return 14 end
+ if choice == "Plastic (red)" then return 15 end
+ if choice == "Plastic (blue)" then return 16 end
+ if choice == "Water" then return 17 end
+ end
+
+ function getNameFromEnum(choice)
+ if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
+ if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
+ if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
+ if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
+ if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
+ if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
+ if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
+ if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
+ if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
+ if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
+ if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
+ if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
+ if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
+ if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
+ if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
+ if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
+ if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
+
+ if waterEnabled then
+ if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
+ end
+ end
+
+
+ local function updateMaterialChoice(choice)
+ currentMaterial = getEnumFromName(choice)
+ terrainMaterialSelectionChanged:Fire(currentMaterial)
+ end
+
+ -- we so need a better way to do this
+ for i,v in pairs(materialNames) do
+ materialToImageMap[v] = {}
+ if v == "Grass" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=56563112"
+ elseif v == "Sand" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=62356652"
+ elseif v == "Brick" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=65961537"
+ elseif v == "Granite" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532153"
+ elseif v == "Asphalt" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532038"
+ elseif v == "Iron" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532093"
+ elseif v == "Aluminum" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531995"
+ elseif v == "Gold" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532118"
+ elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531848"
+ elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531924"
+ elseif v == "Plank" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532015"
+ elseif v == "Log" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532051"
+ elseif v == "Gravel" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532206"
+ elseif v == "Cinder Block" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532103"
+ elseif v == "Stone Wall" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67531804"
+ elseif v == "Concrete" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=67532059"
+ elseif v == "Water" then materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=81407474"
+ else materialToImageMap[v].Regular = "http://www.roblox.com/asset/?id=66887593" -- fill in the rest here!!
+ end
+ end
+
+ local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
+ scrollFrame.Size = UDim2.new(0.85,0,1,0)
+ scrollFrame.Position = UDim2.new(0,0,0,0)
+ scrollFrame.Parent = frame
+
+ scrollUp.Parent = frame
+ scrollUp.Visible = true
+ scrollUp.Position = UDim2.new(1,-19,0,0)
+
+ scrollDown.Parent = frame
+ scrollDown.Visible = true
+ scrollDown.Position = UDim2.new(1,-19,1,-17)
+
+ local function goToNewMaterial(buttonWrap, materialName)
+ updateMaterialChoice(materialName)
+ buttonWrap.BackgroundTransparency = 0
+ selectedButton.BackgroundTransparency = 1
+ selectedButton = buttonWrap
+ end
+
+ local function createMaterialButton(name)
+ local buttonWrap = Instance.new("TextButton")
+ buttonWrap.Text = ""
+ buttonWrap.Size = UDim2.new(0,32,0,32)
+ buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
+ buttonWrap.BorderSizePixel = 0
+ buttonWrap.BackgroundTransparency = 1
+ buttonWrap.AutoButtonColor = false
+ buttonWrap.Name = tostring(name)
+
+ local imageButton = Instance.new("ImageButton")
+ imageButton.AutoButtonColor = false
+ imageButton.BackgroundTransparency = 1
+ imageButton.Size = UDim2.new(0,30,0,30)
+ imageButton.Position = UDim2.new(0,1,0,1)
+ imageButton.Name = tostring(name)
+ imageButton.Parent = buttonWrap
+ imageButton.Image = materialToImageMap[name].Regular
+
+ local enumType = Instance.new("NumberValue")
+ enumType.Name = "EnumType"
+ enumType.Parent = buttonWrap
+ enumType.Value = 0
+
+ imageButton.MouseEnter:connect(function()
+ buttonWrap.BackgroundTransparency = 0
+ end)
+ imageButton.MouseLeave:connect(function()
+ if selectedButton ~= buttonWrap then
+ buttonWrap.BackgroundTransparency = 1
+ end
+ end)
+ imageButton.MouseButton1Click:connect(function()
+ if selectedButton ~= buttonWrap then
+ goToNewMaterial(buttonWrap, tostring(name))
+ end
+ end)
+
+ return buttonWrap
+ end
+
+ for i = 1, #materialNames do
+ local imageButton = createMaterialButton(materialNames[i])
+
+ if materialNames[i] == "Grass" then -- always start with grass as the default
+ selectedButton = imageButton
+ imageButton.BackgroundTransparency = 0
+ end
+
+ imageButton.Parent = scrollFrame
+ end
+
+ local forceTerrainMaterialSelection = function(newMaterialType)
+ if not newMaterialType then return end
+ if currentMaterial == newMaterialType then return end
+
+ local matName = getNameFromEnum(newMaterialType)
+ local buttons = scrollFrame:GetChildren()
+ for i = 1, #buttons do
+ if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
+ if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
+ if string.find(buttons[i].Name, matName) then
+ goToNewMaterial(buttons[i],matName)
+ return
+ end
+ end
+ end
+
+ frame.Changed:connect(function ( prop )
+ if prop == "AbsoluteSize" then
+ recalculateScroll()
+ end
+ end)
+
+ recalculateScroll()
+ return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
+end
+
+t.CreateLoadingFrame = function(name,size,position)
+ game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=35238053")
+
+ local loadingFrame = Instance.new("Frame")
+ loadingFrame.Name = "LoadingFrame"
+ loadingFrame.Style = Enum.FrameStyle.RobloxRound
+
+ if size then loadingFrame.Size = size
+ else loadingFrame.Size = UDim2.new(0,300,0,160) end
+ if position then loadingFrame.Position = position
+ else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
+
+ local loadingBar = Instance.new("Frame")
+ loadingBar.Name = "LoadingBar"
+ loadingBar.BackgroundColor3 = Color3.new(0,0,0)
+ loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
+ loadingBar.Position = UDim2.new(0,0,0,41)
+ loadingBar.Size = UDim2.new(1,0,0,30)
+ loadingBar.Parent = loadingFrame
+
+ local loadingGreenBar = Instance.new("ImageLabel")
+ loadingGreenBar.Name = "LoadingGreenBar"
+ loadingGreenBar.Image = "http://www.roblox.com/asset/?id=35238053"
+ loadingGreenBar.Position = UDim2.new(0,0,0,0)
+ loadingGreenBar.Size = UDim2.new(0,0,1,0)
+ loadingGreenBar.Visible = false
+ loadingGreenBar.Parent = loadingBar
+
+ local loadingPercent = Instance.new("TextLabel")
+ loadingPercent.Name = "LoadingPercent"
+ loadingPercent.BackgroundTransparency = 1
+ loadingPercent.Position = UDim2.new(0,0,1,0)
+ loadingPercent.Size = UDim2.new(1,0,0,14)
+ loadingPercent.Font = Enum.Font.Arial
+ loadingPercent.Text = "0%"
+ loadingPercent.FontSize = Enum.FontSize.Size14
+ loadingPercent.TextColor3 = Color3.new(1,1,1)
+ loadingPercent.Parent = loadingBar
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(0.5,-60,1,-40)
+ cancelButton.Size = UDim2.new(0,120,0,40)
+ cancelButton.Font = Enum.Font.Arial
+ cancelButton.FontSize = Enum.FontSize.Size18
+ cancelButton.TextColor3 = Color3.new(1,1,1)
+ cancelButton.Text = "Cancel"
+ cancelButton.Style = Enum.ButtonStyle.RobloxButton
+ cancelButton.Parent = loadingFrame
+
+ local loadingName = Instance.new("TextLabel")
+ loadingName.Name = "loadingName"
+ loadingName.BackgroundTransparency = 1
+ loadingName.Size = UDim2.new(1,0,0,18)
+ loadingName.Position = UDim2.new(0,0,0,2)
+ loadingName.Font = Enum.Font.Arial
+ loadingName.Text = name
+ loadingName.TextColor3 = Color3.new(1,1,1)
+ loadingName.TextStrokeTransparency = 1
+ loadingName.FontSize = Enum.FontSize.Size18
+ loadingName.Parent = loadingFrame
+
+ local cancelButtonClicked = Instance.new("BindableEvent")
+ cancelButtonClicked.Name = "CancelButtonClicked"
+ cancelButtonClicked.Parent = cancelButton
+ cancelButton.MouseButton1Click:connect(function()
+ cancelButtonClicked:Fire()
+ end)
+
+ local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
+ if percent and type(percent) ~= "number" then
+ error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
+ end
+
+ local newSize = nil
+ if percent < 0 then
+ newSize = UDim2.new(0,0,1,0)
+ elseif percent > 1 then
+ newSize = UDim2.new(1,0,1,0)
+ else
+ newSize = UDim2.new(percent,0,1,0)
+ end
+
+ if tweenAction then
+ if not tweenLength then
+ error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
+ end
+
+ if (newSize.X.Scale > 0) then
+ loadingGreenBar.Visible = true
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true)
+ else
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true,
+ function()
+ if (newSize.X.Scale < 0) then
+ loadingGreenBar.Visible = false
+ end
+ end)
+ end
+
+ else
+ loadingGreenBar.Size = newSize
+ loadingGreenBar.Visible = (newSize.X.Scale > 0)
+ end
+ end
+
+ loadingGreenBar.Changed:connect(function(prop)
+ if prop == "Size" then
+ loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
+ end
+ end)
+
+ return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
+end
+
+t.CreatePluginFrame = function (name,size,position,scrollable,parent)
+ function createMenuButton(size,position,text,fontsize,name,parent)
+ local button = Instance.new("TextButton",parent)
+ button.AutoButtonColor = false
+ button.Name = name
+ button.BackgroundTransparency = 1
+ button.Position = position
+ button.Size = size
+ button.Font = Enum.Font.ArialBold
+ button.FontSize = fontsize
+ button.Text = text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BorderSizePixel = 0
+ button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
+
+ button.MouseEnter:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 0
+ end)
+ button.MouseLeave:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 1
+ end)
+
+ return button
+
+ end
+
+ local dragBar = Instance.new("Frame",parent)
+ dragBar.Name = tostring(name) .. "DragBar"
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ dragBar.BorderColor3 = Color3.new(0,0,0)
+ if size then
+ dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
+ else
+ dragBar.Size = UDim2.new(0,183,0,20)
+ end
+ if position then
+ dragBar.Position = position
+ end
+ dragBar.Active = true
+ dragBar.Draggable = true
+ --dragBar.Visible = false
+ dragBar.MouseEnter:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
+ end)
+ dragBar.MouseLeave:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ end)
+
+ -- plugin name label
+ local pluginNameLabel = Instance.new("TextLabel",dragBar)
+ pluginNameLabel.Name = "BarNameLabel"
+ pluginNameLabel.Text = " " .. tostring(name)
+ pluginNameLabel.TextColor3 = Color3.new(1,1,1)
+ pluginNameLabel.TextStrokeTransparency = 0
+ pluginNameLabel.Size = UDim2.new(1,0,1,0)
+ pluginNameLabel.Font = Enum.Font.ArialBold
+ pluginNameLabel.FontSize = Enum.FontSize.Size18
+ pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
+ pluginNameLabel.BackgroundTransparency = 1
+
+ -- close button
+ local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
+ local closeEvent = Instance.new("BindableEvent")
+ closeEvent.Name = "CloseEvent"
+ closeEvent.Parent = closeButton
+ closeButton.MouseButton1Click:connect(function ()
+ closeEvent:Fire()
+ closeButton.BackgroundTransparency = 1
+ end)
+
+ -- help button
+ local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
+ local helpFrame = Instance.new("Frame",dragBar)
+ helpFrame.Name = "HelpFrame"
+ helpFrame.BackgroundColor3 = Color3.new(0,0,0)
+ helpFrame.Size = UDim2.new(0,300,0,552)
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ helpFrame.Active = true
+ helpFrame.BorderSizePixel = 0
+ helpFrame.Visible = false
+
+ helpButton.MouseButton1Click:connect(function( )
+ helpFrame.Visible = not helpFrame.Visible
+ if helpFrame.Visible then
+ helpButton.Selected = true
+ helpButton.BackgroundTransparency = 0
+ local screenGui = getScreenGuiAncestor(helpFrame)
+ if screenGui then
+ if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
+ helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
+ else -- position on right hand side
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpButton.Selected = false
+ helpButton.BackgroundTransparency = 1
+ end
+ end)
+
+ local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
+ minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
+
+ local minimizeFrame = Instance.new("Frame",dragBar)
+ minimizeFrame.Name = "MinimizeFrame"
+ minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
+ minimizeFrame.BorderColor3 = Color3.new(0,0,0)
+ minimizeFrame.Position = UDim2.new(0,0,1,0)
+ if size then
+ minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
+ else
+ minimizeFrame.Size = UDim2.new(0,183,0,50)
+ end
+ minimizeFrame.Visible = false
+
+ local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
+ minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
+ minimizeBigButton.Name = "MinimizeButton"
+ minimizeBigButton.Size = UDim2.new(0,100,0,40)
+ minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
+ minimizeBigButton.Font = Enum.Font.ArialBold
+ minimizeBigButton.FontSize = Enum.FontSize.Size18
+ minimizeBigButton.TextColor3 = Color3.new(1,1,1)
+ minimizeBigButton.Text = "Show"
+
+ local separatingLine = Instance.new("Frame",dragBar)
+ separatingLine.Name = "SeparatingLine"
+ separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
+ separatingLine.BorderSizePixel = 0
+ separatingLine.Position = UDim2.new(1,-18,0.5,-7)
+ separatingLine.Size = UDim2.new(0,1,0,14)
+
+ local otherSeparatingLine = separatingLine:clone()
+ otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
+ otherSeparatingLine.Parent = dragBar
+
+ local widgetContainer = Instance.new("Frame",dragBar)
+ widgetContainer.Name = "WidgetContainer"
+ widgetContainer.BackgroundTransparency = 1
+ widgetContainer.Position = UDim2.new(0,0,1,0)
+ widgetContainer.BorderColor3 = Color3.new(0,0,0)
+ if not scrollable then
+ widgetContainer.BackgroundTransparency = 0
+ widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ end
+
+ if size then
+ if scrollable then
+ widgetContainer.Size = size
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
+ end
+ else
+ if scrollable then
+ widgetContainer.Size = UDim2.new(0,163,0,400)
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
+ end
+ end
+ if position then
+ widgetContainer.Position = position + UDim2.new(0,0,0,20)
+ end
+
+ local frame,control,verticalDragger = nil
+ if scrollable then
+ --frame for widgets
+ frame,control = t.CreateTrueScrollingFrame()
+ frame.Size = UDim2.new(1, 0, 1, 0)
+ frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ frame.BorderColor3 = Color3.new(0,0,0)
+ frame.Active = true
+ frame.Parent = widgetContainer
+ control.Parent = dragBar
+ control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ control.BorderSizePixel = 0
+ control.BackgroundTransparency = 0
+ control.Position = UDim2.new(1,-21,1,1)
+ if size then
+ control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
+ else
+ control.Size = UDim2.new(0,21,0,400)
+ end
+ control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
+
+ local fakeLine = Instance.new("Frame",control)
+ fakeLine.Name = "FakeLine"
+ fakeLine.BorderSizePixel = 0
+ fakeLine.BackgroundColor3 = Color3.new(0,0,0)
+ fakeLine.Size = UDim2.new(0,1,1,1)
+ fakeLine.Position = UDim2.new(1,0,0,0)
+
+ verticalDragger = Instance.new("TextButton",widgetContainer)
+ verticalDragger.ZIndex = 2
+ verticalDragger.AutoButtonColor = false
+ verticalDragger.Name = "VerticalDragger"
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ verticalDragger.BorderColor3 = Color3.new(0,0,0)
+ verticalDragger.Size = UDim2.new(1,20,0,20)
+ verticalDragger.Position = UDim2.new(0,0,1,0)
+ verticalDragger.Active = true
+ verticalDragger.Text = ""
+
+ local scrubFrame = Instance.new("Frame",verticalDragger)
+ scrubFrame.Name = "ScrubFrame"
+ scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
+ scrubFrame.BorderSizePixel = 0
+ scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
+ scrubFrame.Size = UDim2.new(0,10,0,1)
+ scrubFrame.ZIndex = 5
+ local scrubTwo = scrubFrame:clone()
+ scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
+ scrubTwo.Parent = verticalDragger
+ local scrubThree = scrubFrame:clone()
+ scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
+ scrubThree.Parent = verticalDragger
+
+ local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.BorderSizePixel = 0
+ areaSoak.Text = ""
+ areaSoak.ZIndex = 10
+ areaSoak.Visible = false
+ areaSoak.Active = true
+
+ local draggingVertical = false
+ local startYPos = nil
+ verticalDragger.MouseEnter:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
+ end)
+ verticalDragger.MouseLeave:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ end)
+ verticalDragger.MouseButton1Down:connect(function(x,y)
+ draggingVertical = true
+ areaSoak.Visible = true
+ startYPos = y
+ end)
+ areaSoak.MouseButton1Up:connect(function ( )
+ draggingVertical = false
+ areaSoak.Visible = false
+ end)
+ areaSoak.MouseMoved:connect(function(x,y)
+ if not draggingVertical then return end
+
+ local yDelta = y - startYPos
+ if not control.ScrollDownButton.Visible and yDelta > 0 then
+ return
+ end
+
+ if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
+ control.Size = UDim2.new (0,21,0,150)
+ return
+ end
+
+ startYPos = y
+
+ if widgetContainer.Size.Y.Offset + yDelta >= 0 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
+ control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
+ end
+ end)
+ end
+
+ local function switchMinimize()
+ minimizeFrame.Visible = not minimizeFrame.Visible
+ if scrollable then
+ frame.Visible = not frame.Visible
+ verticalDragger.Visible = not verticalDragger.Visible
+ control.Visible = not control.Visible
+ else
+ widgetContainer.Visible = not widgetContainer.Visible
+ end
+
+ if minimizeFrame.Visible then
+ minimizeButton.Text = "+"
+ else
+ minimizeButton.Text = "-"
+ end
+ end
+
+ minimizeBigButton.MouseButton1Click:connect(function ( )
+ switchMinimize()
+ end)
+
+ minimizeButton.MouseButton1Click:connect(function( )
+ switchMinimize()
+ end)
+
+ if scrollable then
+ return dragBar, frame, helpFrame, closeEvent
+ else
+ return dragBar, widgetContainer, helpFrame, closeEvent
+ end
+end
+
+t.Help =
+ function(funcNameOrFunc)
+ --input argument can be a string or a function. Should return a description (of arguments and expected side effects)
+ if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
+ return "Function CreatePropertyDropDownMenu. " ..
+ "Arguments: (instance, propertyName, enumType). " ..
+ "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
+ end
+ if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
+ return "Function CreateDropDownMenu. " ..
+ "Arguments: (items, onItemSelected). " ..
+ "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
+ end
+ if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
+ return "Function CreateMessageDialog. " ..
+ "Arguments: (title, message, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
+ end
+ if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
+ return "Function CreateStyledMessageDialog. " ..
+ "Arguments: (title, message, style, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
+ end
+ if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
+ return "Function GetFontHeight. " ..
+ "Arguments: (font, fontSize). " ..
+ "Side effect: returns the size in pixels of the given font + fontSize"
+ end
+ if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
+
+ end
+ if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
+ return "Function CreateScrollingFrame. " ..
+ "Arguments: (orderList, style) " ..
+ "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
+ end
+ if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
+ return "Function CreateTrueScrollingFrame. " ..
+ "Arguments: (nil) " ..
+ "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
+ end
+ if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
+ return "Function AutoTruncateTextObject. " ..
+ "Arguments: (textLabel) " ..
+ "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
+ end
+ if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
+ return "Function CreateSlider. " ..
+ "Arguments: (steps, width, position) " ..
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
+ end
+ if funcNameOrFunc == "CreateSliderNew" or funcNameOrFunc == t.CreateSliderNew then
+ return "Function CreateSliderNew. " ..
+ "Arguments: (steps, width, position) " ..
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
+ end
+ if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
+ return "Function CreateLoadingFrame. " ..
+ "Arguments: (name, size, position) " ..
+ "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
+ end
+ if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
+ return "Function CreateTerrainMaterialSelector. " ..
+ "Arguments: (size, position) " ..
+ "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
+ end
+ end
+
+--rbxsig%S02sfJuSM3Thz5hVIxyf9kDDENER9guz5nwJx/SfET0qAar5EDNQ6VJkwq7L45ZNfqVNd7IxhujzkgYff2V8ee5Mp5MfS9aEcztYGlWumULivAzynGfqkdVh+GzofuzUmMwWqPPsKqvQLiFe9MXMtCqe89S/Y9n6LZgrS1hyuqY=%
+--fixed by iagoMAO --
+
+-- A couple of necessary functions
+local function waitForChild(instance, name)
+ while not instance:FindFirstChild(name) do
+ instance.ChildAdded:wait()
+ end
+end
+local function waitForProperty(instance, property)
+ while not instance[property] do
+ instance.Changed:wait()
+ end
+end
+
+waitForChild(game,"Players")
+waitForProperty(game.Players,"LocalPlayer")
+local player = game.Players.LocalPlayer
+
+local RbxGui,msg = t
+if not RbxGui then print("could not find RbxGui!") return end
+
+--- Begin Locals
+waitForChild(game,"Players")
+
+-- don't do anything if we are in an empty game
+if #game.Players:GetChildren() < 1 then
+ game.Players.ChildAdded:wait()
+end
+
+local tilde = "~"
+local backquote = "`"
+game:GetService("GuiService"):AddKey(tilde) -- register our keys
+game:GetService("GuiService"):AddKey(backquote)
+
+local player = game.Players.LocalPlayer
+
+local backpack = script.Parent.Backpack
+local screen = script.Parent
+local closeButton = backpack.Tabs.CloseButton
+
+local openCloseDebounce = false
+
+local backpackItems = {}
+
+local buttons = {}
+
+local debounce = false
+
+local guiTweenSpeed = 1
+
+local browsingMenu = false
+
+local mouseEnterCons = {}
+local mouseClickCons = {}
+
+local characterChildAddedCon = nil
+local characterChildRemovedCon = nil
+local backpackAddCon = nil
+local humanoidDiedCon = nil
+local backpackButtonClickCon = nil
+local guiServiceKeyPressCon = nil
+
+waitForChild(player,"Backpack")
+local playerBackpack = player.Backpack
+
+waitForChild(backpack,"Gear")
+waitForChild(backpack.Gear,"GearPreview")
+local gearPreview = backpack.Gear.GearPreview
+
+waitForChild(backpack.Gear,"GearGridScrollingArea")
+local scroller = backpack.Gear.GearGridScrollingArea
+
+waitForChild(backpack.Parent,"CurrentLoadout")
+local currentLoadout = backpack.Parent.CurrentLoadout
+
+waitForChild(backpack.Parent,"ControlFrame")
+waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
+local backpackButton = backpack.Parent.ControlFrame.BackpackButton
+
+waitForChild(backpack.Gear,"GearGrid")
+waitForChild(backpack.Gear.GearGrid,"GearButton")
+local gearButton = backpack.Gear.GearGrid.GearButton
+local grid = backpack.Gear.GearGrid
+
+waitForChild(backpack.Gear.GearGrid,"SearchFrame")
+waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchBoxFrame")
+waitForChild(backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame,"SearchBox")
+local searchBox = backpack.Gear.GearGrid.SearchFrame.SearchBoxFrame.SearchBox
+
+waitForChild(backpack.Gear.GearGrid.SearchFrame,"SearchButton")
+local searchButton = backpack.Gear.GearGrid.SearchFrame.SearchButton
+
+waitForChild(backpack.Gear.GearGrid,"ResetFrame")
+local resetFrame = backpack.Gear.GearGrid.ResetFrame
+
+waitForChild(backpack.Gear.GearGrid.ResetFrame,"ResetButtonBorder")
+local resetButton = backpack.Gear.GearGrid.ResetFrame.ResetButtonBorder
+
+waitForChild(script.Parent,"SwapSlot")
+local swapSlot = script.Parent.SwapSlot
+
+
+-- creating scroll bar early as to make sure items get placed correctly
+local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid")
+
+scrollFrame.Position = UDim2.new(0,0,0,30)
+scrollFrame.Size = UDim2.new(1,0,1,-30)
+scrollFrame.Parent = backpack.Gear.GearGrid
+
+local scrollBar = Instance.new("Frame")
+scrollBar.Name = "ScrollBar"
+scrollBar.BackgroundTransparency = 0.9
+scrollBar.BackgroundColor3 = Color3.new(1,1,1)
+scrollBar.BorderSizePixel = 0
+scrollBar.Size = UDim2.new(0, 17, 1, -36)
+scrollBar.Position = UDim2.new(0,0,0,18)
+scrollBar.Parent = scroller
+
+scrollDown.Position = UDim2.new(0,0,1,-17)
+
+scrollUp.Parent = scroller
+scrollDown.Parent = scroller
+
+local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
+
+scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
+scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
+scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
+
+local LoadoutButton = Instance.new("TextButton")
+
+LoadoutButton.Name = "LoadoutButton"
+LoadoutButton.Font = Enum.Font.ArialBold
+LoadoutButton.FontSize = Enum.FontSize.Size14
+LoadoutButton.Position = UDim2.new(0,0,0,0)
+LoadoutButton.Size = UDim2.new(1,0,0,32)
+LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
+LoadoutButton.Text = "Loadout #1"
+LoadoutButton.TextColor3 = Color3.new(1,1,1)
+LoadoutButton.Parent = scrollFrameLoadout
+
+local LoadoutButtonTwo = LoadoutButton:clone()
+LoadoutButtonTwo.Text = "Loadout #2"
+LoadoutButtonTwo.Parent = scrollFrameLoadout
+
+local LoadoutButtonThree = LoadoutButton:clone()
+LoadoutButtonThree.Text = "Loadout #3"
+LoadoutButtonThree.Parent = scrollFrameLoadout
+
+local LoadoutButtonFour = LoadoutButton:clone()
+LoadoutButtonFour.Text = "Loadout #4"
+LoadoutButtonFour.Parent = scrollFrameLoadout
+
+local scrollBarLoadout = Instance.new("Frame")
+scrollBarLoadout.Name = "ScrollBarLoadout"
+scrollBarLoadout.BackgroundTransparency = 0.9
+scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
+scrollBarLoadout.BorderSizePixel = 0
+scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
+scrollBarLoadout.Position = UDim2.new(0,0,0,18)
+scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
+
+scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
+
+scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
+scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
+
+
+-- Begin Functions
+function removeFromMap(map,object)
+ for i = 1, #map do
+ if map[i] == object then
+ table.remove(map,i)
+ break
+ end
+ end
+end
+
+
+function resize()
+ local size = 0
+ if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
+ size = gearPreview.AbsoluteSize.X * 0.75
+ else
+ size = gearPreview.AbsoluteSize.Y * 0.75
+ end
+
+ gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
+ gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
+
+ resizeGrid()
+end
+
+function addToGrid(child)
+ if not child:IsA("Tool") then
+ if not child:IsA("HopperBin") then
+ return
+ end
+ end
+ if child:FindFirstChild("RobloxBuildTool") then return end
+
+ for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
+ if v == child then return end
+ end
+
+ table.insert(backpackItems,child)
+
+ local changeCon = child.Changed:connect(function(prop)
+ if prop == "Name" then
+ if buttons[child] then
+ if buttons[child].Image == "" then
+ buttons[child].GearText.Text = child.Name
+ end
+ end
+ end
+ end)
+ local ancestryCon = nil
+ ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
+ local thisObject = nil
+ for k,v in pairs(backpackItems) do
+ if v == child then
+ thisObject = v
+ break
+ end
+ end
+
+ waitForProperty(player,"Character")
+ waitForChild(player,"Backpack")
+ if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
+ if ancestryCon then ancestryCon:disconnect() end
+ if changeCon then changeCon:disconnect() end
+
+ for k,v in pairs(backpackItems) do
+ if v == thisObject then
+ if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
+ if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
+ buttons[v].Parent = nil
+ buttons[v] = nil
+ break
+ end
+ end
+
+ removeFromMap(backpackItems,thisObject)
+
+ resizeGrid()
+ else
+ resizeGrid()
+ end
+ updateGridActive()
+ end)
+ resizeGrid()
+end
+
+function buttonClick(button)
+ if button:FindFirstChild("UnequipContextMenu") and not button.Active then
+ button.UnequipContextMenu.Visible = true
+ browsingMenu = true
+ end
+end
+
+function previewGear(button)
+ if not browsingMenu then
+ gearPreview.GearImage.Image = button.Image
+ gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
+ end
+end
+
+function findEmptySlot()
+ local smallestNum = nil
+ local loadout = currentLoadout:GetChildren()
+ for i = 1, #loadout do
+ if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
+ local frameNum = tonumber(string.sub(loadout[i].Name,5))
+ if frameNum == 0 then frameNum = 10 end
+ if not smallestNum or (smallestNum > frameNum) then
+ smallestNum = frameNum
+ end
+ end
+ end
+ if smallestNum == 10 then smallestNum = 0 end
+ return smallestNum
+end
+
+function checkForSwap(button,x,y)
+ local loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
+ if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
+ if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
+ local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
+ swapGearSlot(slot,button)
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+function resizeGrid()
+ for k,v in pairs(backpackItems) do
+ if not v:FindFirstChild("RobloxBuildTool") then
+ if not buttons[v] then
+ local buttonClone = gearButton:clone()
+ buttonClone.Parent = grid.ScrollingFrame
+ buttonClone.Visible = true
+ buttonClone.Image = v.TextureId
+ if buttonClone.Image == "" then
+ buttonClone.GearText.Text = v.Name
+ end
+
+ buttonClone.GearReference.Value = v
+ buttonClone.Draggable = true
+ buttons[v] = buttonClone
+
+ local unequipMenu = getGearContextMenu()
+
+ unequipMenu.Visible = false
+ unequipMenu.Parent = buttonClone
+
+ local beginPos = nil
+ buttonClone.DragBegin:connect(function(value)
+ buttonClone.ZIndex = 9
+ beginPos = value
+ end)
+ buttonClone.DragStopped:connect(function(x,y)
+ if beginPos ~= buttonClone.Position then
+ buttonClone.ZIndex = 1
+ if not checkForSwap(buttonClone,x,y) then
+ buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
+ buttonClone.Draggable = false
+ delay(0.5,function()
+ buttonClone.Draggable = true
+ end)
+ else
+ buttonClone.Position = beginPos
+ end
+ end
+ end)
+ local clickTime = tick()
+ mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
+ mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
+ local newClickTime = tick()
+ if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
+ local slot = findEmptySlot()
+ if slot then
+ buttonClone.ZIndex = 1
+ swapGearSlot(slot,buttonClone)
+ end
+ else
+ buttonClick(buttonClone)
+ end
+ clickTime = newClickTime
+ end)
+ end
+ end
+ end
+ recalculateScroll()
+end
+
+function showPartialGrid(subset)
+
+ resetFrame.Visible = true
+
+ for k,v in pairs(buttons) do
+ v.Parent = nil
+ end
+ for k,v in pairs(subset) do
+ v.Parent = grid.ScrollingFrame
+ end
+ recalculateScroll()
+end
+
+function showEntireGrid()
+ resetFrame.Visible = false
+
+ for k,v in pairs(buttons) do
+ v.Parent = grid.ScrollingFrame
+ end
+ recalculateScroll()
+end
+
+function inLoadout(gear)
+ local children = currentLoadout:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ local button = children[i]:GetChildren()
+ if #button > 0 then
+ if button[1].GearReference.Value and button[1].GearReference.Value == gear then
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+function updateGridActive()
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ local gear = nil
+ local gearRef = buttons[v]:FindFirstChild("GearReference")
+
+ if gearRef then gear = gearRef.Value end
+
+ if not gear then
+ buttons[v].Active = false
+ elseif inLoadout(gear) then
+ buttons[v].Active = false
+ else
+ buttons[v].Active = true
+ end
+ end
+ end
+end
+
+function centerGear(loadoutChildren)
+ local gearButtons = {}
+ local lastSlotAdd = nil
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
+ if loadoutChildren[i].Name == "Slot0" then
+ lastSlotAdd = loadoutChildren[i]
+ else
+ table.insert(gearButtons, loadoutChildren[i])
+ end
+ end
+ end
+ if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
+
+ local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
+ for i = 1, #gearButtons do
+ gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
+ end
+end
+
+function spreadOutGear(loadoutChildren)
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
+ if slot == 0 then slot = 10 end
+ loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
+ end
+ end
+end
+
+function openCloseBackpack(close)
+ if openCloseDebounce then return end
+ openCloseDebounce = true
+
+ local visible = not backpack.Visible
+ if visible and not close then
+ updateGridActive()
+ local centerDialogSupported, msg = pcall(function() game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
+ function()
+ backpack.Visible = true
+ loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ loadoutChildren[i].BackgroundTransparency = 0.5
+ end
+ end
+ spreadOutGear(loadoutChildren)
+ end,
+ function()
+ backpack.Visible = false
+ end)
+ end)
+ backpackButton.Selected = true
+ backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
+ delay(guiTweenSpeed/2 + 0.01,
+ function()
+ local children = backpack:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ children[i].Visible = true
+ end
+ end
+ resizeGrid()
+ resize()
+ openCloseDebounce = false
+ end)
+ else
+ backpackButton.Selected = false
+ local children = backpack:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ children[i].Visible = false
+ end
+ end
+ loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ loadoutChildren[i].BackgroundTransparency = 1
+ end
+ end
+ centerGear(loadoutChildren)
+
+ backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
+ delay(guiTweenSpeed/2 + 0.01,
+ function()
+ backpack.Visible = visible
+ resizeGrid()
+ resize()
+ pcall(function() game.GuiService:RemoveCenterDialog(backpack) end)
+ openCloseDebounce = false
+ end)
+ end
+end
+
+function loadoutCheck(child, selectState)
+ if not child:IsA("ImageButton") then return end
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
+ if buttons[v].GearReference.Value == child.GearReference.Value then
+ buttons[v].Active = selectState
+ break
+ end
+ end
+ end
+ end
+end
+
+function clearPreview()
+ gearPreview.GearImage.Image = ""
+ gearPreview.GearStats.GearName.Text = ""
+end
+
+function removeAllEquippedGear(physGear)
+ local stuff = player.Character:GetChildren()
+ for i = 1, #stuff do
+ if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
+ stuff[i].Parent = playerBackpack
+ end
+ end
+end
+
+function equipGear(physGear)
+ removeAllEquippedGear(physGear)
+ physGear.Parent = player.Character
+ updateGridActive()
+end
+
+function unequipGear(physGear)
+ physGear.Parent = playerBackpack
+ updateGridActive()
+end
+
+function highlight(button)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
+end
+function clearHighlight(button)
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundColor3 = Color3.new(0,0,0)
+end
+
+function swapGearSlot(slot,gearButton)
+ if not swapSlot.Value then -- signal loadout to swap a gear out
+ swapSlot.Slot.Value = slot
+ swapSlot.GearButton.Value = gearButton
+ swapSlot.Value = true
+ updateGridActive()
+ end
+end
+
+
+local UnequipGearMenuClick = function(element, menu)
+ if type(element.Action) ~= "number" then return end
+ local num = element.Action
+ if num == 1 then -- remove from loadout
+ unequipGear(menu.Parent.GearReference.Value)
+ local inventoryButton = menu.Parent
+ local gearToUnequip = inventoryButton.GearReference.Value
+ local loadoutChildren = currentLoadout:GetChildren()
+ local slot = -1
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ local button = loadoutChildren[i]:GetChildren()
+ if button[1] and button[1].GearReference.Value == gearToUnequip then
+ slot = button[1].SlotNumber.Text
+ break
+ end
+ end
+ end
+ swapGearSlot(slot,nil)
+ end
+end
+
+-- these next two functions are used to stop any use of backpack while the player is dead (can cause issues)
+function activateBackpack()
+ loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ loadoutChildren[i].BackgroundTransparency = 1
+ end
+ end
+
+ backpackButtonClickCon = backpackButton.MouseButton1Click:connect(function() openCloseBackpack() end)
+ guiServiceKeyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key)
+ if key == tilde or key == backquote then
+ openCloseBackpack()
+ end
+ end)
+end
+function deactivateBackpack()
+ if backpackButtonClickCon then backpackButtonClickCon:disconnect() end
+ if guiServiceKeyPressCon then guiServiceKeyPressCon:disconnect() end
+
+ openCloseBackpack(true)
+end
+
+function setupCharacterConnections()
+
+ if backpackAddCon then backpackAddCon:disconnect() end
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+
+ -- make sure we get all the children
+ local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
+ for i = 1, #backpackChildren do
+ addToGrid(backpackChildren[i])
+ end
+
+ if characterChildAddedCon then characterChildAddedCon:disconnect() end
+ characterChildAddedCon =
+ game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
+ addToGrid(child)
+ updateGridActive()
+ end)
+
+ if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
+ characterChildRemovedCon =
+ game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
+ updateGridActive()
+ end)
+
+
+ if humanoidDiedCon then humanoidDiedCon:disconnect() end
+ local localPlayer = game.Players.LocalPlayer
+ waitForProperty(localPlayer,"Character")
+ waitForChild(localPlayer.Character,"Humanoid")
+ humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(function() deactivateBackpack() end)
+
+ activateBackpack()
+
+ wait()
+ centerGear(currentLoadout:GetChildren())
+end
+
+function removeCharacterConnections()
+ if characterChildAddedCon then characterChildAddedCon:disconnect() end
+ if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
+ if backpackAddCon then backpackAddCon:disconnect() end
+end
+
+function trim(s)
+ return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+function splitByWhiteSpace(text)
+ if type(text) ~= "string" then return nil end
+
+ local terms = {}
+ for token in string.gmatch(text, "[^%s]+") do
+ if string.len(token) > 2 then
+ table.insert(terms,token)
+ end
+ end
+ return terms
+end
+
+function filterGear(searchTerm)
+ string.lower(searchTerm)
+ searchTerm = trim(searchTerm)
+ if string.len(searchTerm) < 2 then return nil end
+ local terms = splitByWhiteSpace(searchTerm)
+
+ local filteredGear = {}
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ local gearString = string.lower(buttons[v].GearReference.Value.Name)
+ gearString = trim(gearString)
+ for i = 1, #terms do
+ if string.match(gearString,terms[i]) then
+ table.insert(filteredGear,buttons[v])
+ break
+ end
+ end
+ end
+ end
+
+ return filteredGear
+end
+
+
+function showSearchGear()
+ local searchText = searchBox.Text
+ searchBox.Text = "Search..."
+ local filteredButtons = filterGear(searchText)
+ if filteredButtons and #filteredButtons > 0 then
+ showPartialGrid(filteredButtons)
+ else
+ showEntireGrid()
+ end
+end
+
+function nukeBackpack()
+ while #buttons > 0 do
+ table.remove(buttons)
+ end
+ buttons = {}
+ while #backpackItems > 0 do
+ table.remove(backpackItems)
+ end
+ backpackItems = {}
+ local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
+ for i = 1, #scrollingFrameChildren do
+ scrollingFrameChildren[i]:remove()
+ end
+end
+
+function getGearContextMenu()
+ local gearContextMenu = Instance.new("Frame")
+ gearContextMenu.Active = true
+ gearContextMenu.Name = "UnequipContextMenu"
+ gearContextMenu.Size = UDim2.new(0,115,0,70)
+ gearContextMenu.Position = UDim2.new(0,-16,0,-16)
+ gearContextMenu.BackgroundTransparency = 1
+ gearContextMenu.Visible = false
+
+ local gearContextMenuButton = Instance.new("TextButton")
+ gearContextMenuButton.Name = "UnequipContextMenuButton"
+ gearContextMenuButton.Text = ""
+ gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ gearContextMenuButton.ZIndex = 4
+ gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
+ gearContextMenuButton.Visible = true
+ gearContextMenuButton.Parent = gearContextMenu
+
+ local elementHeight = 12
+
+ local contextMenuElements = {}
+ local contextMenuElementsName = {"Remove Hotkey"}
+
+ for i = 1, #contextMenuElementsName do
+ local element = {}
+ element.Type = "Button"
+ element.Text = contextMenuElementsName[i]
+ element.Action = i
+ element.DoIt = UnequipGearMenuClick
+ table.insert(contextMenuElements,element)
+ end
+
+ for i, contextElement in ipairs(contextMenuElements) do
+ local element = contextElement
+ if element.Type == "Button" then
+ local button = Instance.new("TextButton")
+ button.Name = "UnequipContextButton" .. i
+ button.BackgroundColor3 = Color3.new(0,0,0)
+ button.BorderSizePixel = 0
+ button.TextXAlignment = Enum.TextXAlignment.Left
+ button.Text = " " .. contextElement.Text
+ button.Font = Enum.Font.Arial
+ button.FontSize = Enum.FontSize.Size14
+ button.Size = UDim2.new(1, 8, 0, elementHeight)
+ button.Position = UDim2.new(0,0,0,elementHeight * i)
+ button.TextColor3 = Color3.new(1,1,1)
+ button.ZIndex = 4
+ button.Parent = gearContextMenuButton
+
+ button.MouseButton1Click:connect(function()
+ if button.Active and not gearContextMenu.Parent.Active then
+ local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
+ browsingMenu = false
+ gearContextMenu.Visible = false
+ clearHighlight(button)
+ clearPreview()
+ end
+ end)
+
+ button.MouseEnter:connect(function()
+ if button.Active and gearContextMenu.Parent.Active then
+ highlight(button)
+ end
+ end)
+ button.MouseLeave:connect(function()
+ if button.Active and gearContextMenu.Parent.Active then
+ clearHighlight(button)
+ end
+ end)
+
+ contextElement.Button = button
+ contextElement.Element = button
+ elseif element.Type == "Label" then
+ local frame = Instance.new("Frame")
+ frame.Name = "ContextLabel" .. i
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(1, 8, 0, elementHeight)
+
+ local label = Instance.new("TextLabel")
+ label.Name = "Text1"
+ label.BackgroundTransparency = 1
+ label.BackgroundColor3 = Color3.new(1,1,1)
+ label.BorderSizePixel = 0
+ label.TextXAlignment = Enum.TextXAlignment.Left
+ label.Font = Enum.Font.ArialBold
+ label.FontSize = Enum.FontSize.Size14
+ label.Position = UDim2.new(0.0, 0, 0, 0)
+ label.Size = UDim2.new(0.5, 0, 1, 0)
+ label.TextColor3 = Color3.new(1,1,1)
+ label.ZIndex = 4
+ label.Parent = frame
+ element.Label1 = label
+
+ if element.GetText2 then
+ label = Instance.new("TextLabel")
+ label.Name = "Text2"
+ label.BackgroundTransparency = 1
+ label.BackgroundColor3 = Color3.new(1,1,1)
+ label.BorderSizePixel = 0
+ label.TextXAlignment = Enum.TextXAlignment.Right
+ label.Font = Enum.Font.Arial
+ label.FontSize = Enum.FontSize.Size14
+ label.Position = UDim2.new(0.5, 0, 0, 0)
+ label.Size = UDim2.new(0.5, 0, 1, 0)
+ label.TextColor3 = Color3.new(1,1,1)
+ label.ZIndex = 4
+ label.Parent = frame
+ element.Label2 = label
+ end
+ frame.Parent = gearContextMenuButton
+ element.Label = frame
+ element.Element = frame
+ end
+ end
+
+ gearContextMenu.ZIndex = 4
+ gearContextMenu.MouseLeave:connect(function()
+ browsingMenu = false
+ gearContextMenu.Visible = false
+ clearPreview()
+ end)
+
+
+ return gearContextMenu
+end
+
+local backpackChildren = player.Backpack:GetChildren()
+for i = 1, #backpackChildren do
+ addToGrid(backpackChildren[i])
+end
+
+------------------------- Start Lifelong Connections -----------------------
+screen.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ if debounce then return end
+ debounce = true
+ wait()
+ resize()
+ resizeGrid()
+ debounce = false
+ end
+end)
+
+currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
+currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
+
+currentLoadout.DescendantAdded:connect(function(descendant)
+ if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
+ centerGear(currentLoadout:GetChildren())
+ end
+end)
+currentLoadout.DescendantRemoving:connect(function(descendant)
+ if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
+ wait()
+ centerGear(currentLoadout:GetChildren())
+ end
+end)
+
+grid.MouseEnter:connect(function() clearPreview() end)
+grid.MouseLeave:connect(function() clearPreview() end)
+
+player.CharacterRemoving:connect(function()
+ removeCharacterConnections()
+ nukeBackpack()
+end)
+player.CharacterAdded:connect(function() setupCharacterConnections() end)
+
+player.ChildAdded:connect(function(child)
+ if child:IsA("Backpack") then
+ playerBackpack = child
+ if backpackAddCon then backpackAddCon:disconnect() end
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+ end
+end)
+
+swapSlot.Changed:connect(function()
+ if not swapSlot.Value then
+ updateGridActive()
+ end
+end)
+
+searchBox.FocusLost:connect(function(enterPressed)
+ if enterPressed then
+ showSearchGear()
+ end
+end)
+
+local loadoutChildren = currentLoadout:GetChildren()
+for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
+ loadoutChildren[i].ChildRemoved:connect(function()
+ updateGridActive()
+ end)
+ loadoutChildren[i].ChildAdded:connect(function()
+ updateGridActive()
+ end)
+ end
+end
+
+pcall(function() closeButton.Modal = true end)
+closeButton.MouseButton1Click:connect(function() openCloseBackpack() end)
+
+searchButton.MouseButton1Click:connect(function() showSearchGear() end)
+resetButton.MouseButton1Click:connect(function() showEntireGrid() end)
+------------------------- End Lifelong Connections -----------------------
+
+resize()
+resizeGrid()
+
+-- make sure any items in the loadout are accounted for in inventory
+local loadoutChildren = currentLoadout:GetChildren()
+for i = 1, #loadoutChildren do
+ loadoutCheck(loadoutChildren[i], false)
+end
+if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
+
+-- make sure that inventory is listening to gear reparenting
+if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
+ setupCharacterConnections()
+end
+if not backpackAddCon then
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+end
+
+recalculateScrollLoadout()
+
+print("Backpack has been built. Time for the resizer script.")
+script.Parent.BackpackResizer.Parent = script.Parent.Backpack
- -
+
-
- true
+ false
- TimeoutScript
- wait(15)
-local dialog = script.Parent
-if dialog:IsA("Dialog") then
- dialog.InUse = false
-end
-script:Remove()
-
- true
+ BackpackScript
+ -- A couple of necessary functions
+local function waitForChild(instance, name)
+ while not instance:FindFirstChild(name) do
+ instance.ChildAdded:wait()
+ end
+end
+local function waitForProperty(instance, property)
+ while not instance[property] do
+ instance.Changed:wait()
+ end
+end
+
+
+
+
+
+--- Begin Locals
+waitForChild(game,"Players")
+waitForProperty(game.Players,"LocalPlayer")
+local player = game.Players.LocalPlayer
+
+local currentLoadout = script.Parent
+local maxNumLoadoutItems = 10
+
+local guiBackpack = currentLoadout.Backpack
+
+local characterChildAddedCon = nil
+local keyPressCon = nil
+local backpackChildCon = nil
+
+local debounce = script.Parent.CurrentLoadout.Debounce
+
+local waitingOnEnlarge = nil
+
+local enlargeFactor = 1.18
+local buttonSizeEnlarge = UDim2.new(1 * enlargeFactor,0,1 * enlargeFactor,0)
+local buttonSizeNormal = UDim2.new(1,0,1,0)
+local enlargeOverride = true
+
+local guiTweenSpeed = 0.5
+
+for i = 0, 9 do
+ game:GetService("GuiService"):AddKey(tostring(i)) -- register our keys
+end
+
+local gearSlots = {}
+for i = 1, maxNumLoadoutItems do
+ gearSlots[i] = "empty"
+end
+
+local inventory = {}
+--- End Locals
+
+
+
+
+
+
+-- Begin Functions
+local function kill(prop,con,gear)
+ if con then con:disconnect() end
+ if prop == true and gear then
+ reorganizeLoadout(gear,false)
+ end
+end
+
+
+
+function centerGear()
+
+ local Loadout = script.Parent.CurrentLoadout
+ Loadout.Position = UDim2.new(0.45, -170, 1, -85)
+ loadoutChildren = Loadout:GetChildren()
+ local gearButtons = {}
+ local lastSlotAdd = nil
+ for i = 1,#loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ if #loadoutChildren[i]:GetChildren() > 0 then
+ if loadoutChildren[i].Name == "Slot0" then
+ lastSlotAdd = loadoutChildren[i]
+ else
+ table.insert(gearButtons,loadoutChildren[i])
+ end
+ end
+ loadoutChildren[i].BackgroundTransparency = 1
+ if script.Parent.Backpack.Visible == true then
+ loadoutChildren[i].BackgroundTransparency = 0.5
+ elseif script.Parent.Backpack.Visible == false then
+ loadoutChildren[i].BackgroundTransparency = 1
+ end
+
+ end
+ end
+ if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
+
+ local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
+ for i = 1,#gearButtons do
+ gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quad,0.25,true)
+ end
+end
+
+function removeGear(gear)
+ local emptySlot = nil
+ for i = 1, #gearSlots do
+ if gearSlots[i] == gear and gear.Parent ~= nil then
+ emptySlot = i
+ break
+ end
+ end
+ if emptySlot then
+ if gearSlots[emptySlot].GearReference.Value then
+ if gearSlots[emptySlot].GearReference.Value.Parent == game.Players.LocalPlayer.Character then -- if we currently have this equipped, unequip it
+ gearSlots[emptySlot].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack
+ end
+
+ if gearSlots[emptySlot].GearReference.Value:IsA("HopperBin") and gearSlots[emptySlot].GearReference.Value.Active then -- this is an active hopperbin
+ gearSlots[emptySlot].GearReference.Value:Disable()
+ gearSlots[emptySlot].GearReference.Value.Active = false
+ end
+ end
+
+ gearSlots[emptySlot] = "empty"
+
+
+
+ delay(guiTweenSpeed/2,
+ function()
+
+ gear:remove()
+ if script.Parent.Backpack.Visible == false then
+ centerGear()
+ else
+ gear:remove()
+ end
+
+ end)
+ end
+end
+
+function insertGear(gear, addToSlot)
+ local pos = nil
+ if not addToSlot then
+ for i = 1, #gearSlots do
+ if gearSlots[i] == "empty" then
+ pos = i
+ break
+ end
+ end
+
+ if pos == 1 and gearSlots[1] ~= "empty" then gear:remove() return end -- we are currently full, can't add in
+ else
+ pos = addToSlot
+ -- push all gear down one slot
+ local start = 1
+ for i = 1, #gearSlots do
+ if gearSlots[i] == "empty" then
+ start = i
+ break
+ end
+ end
+ for i = start, pos + 1, -1 do
+ gearSlots[i] = gearSlots[i - 1]
+ if i == 10 then
+ gearSlots[i].SlotNumber.Text = "0"
+ gearSlots[i].SlotNumberDownShadow.Text = "0"
+ gearSlots[i].SlotNumberUpShadow.Text = "0"
+ else
+ gearSlots[i].SlotNumber.Text = i
+ gearSlots[i].SlotNumberDownShadow.Text = i
+ gearSlots[i].SlotNumberUpShadow.Text = i
+ end
+ end
+ end
+
+ gearSlots[pos] = gear
+ if pos ~= maxNumLoadoutItems then
+ if(type(tostring(pos)) == "string") then
+ local posString = tostring(pos)
+ gear.SlotNumber.Text = posString
+ gear.SlotNumberDownShadow.Text = posString
+ gear.SlotNumberUpShadow.Text = posString
+ end
+ else -- tenth gear doesn't follow mathematical pattern :(
+ gear.SlotNumber.Text = "0"
+ gear.SlotNumberDownShadow.Text = "0"
+ gear.SlotNumberUpShadow.Text = "0"
+ end
+ gear.Visible = true
+
+ if script.Parent.Backpack.Visible == false then
+ centerGear()
+ else
+ return
+ end
+ local con = nil
+ con = gear.Kill.Changed:connect(function(prop) kill(prop,con,gear) end)
+end
+
+
+function reorganizeLoadout(gear, inserting, equipped, addToSlot)
+ if inserting then -- add in gear
+ insertGear(gear, addToSlot)
+ else
+ removeGear(gear)
+ end
+ if gear ~= "empty" then gear.ZIndex = 1 end
+end
+
+function checkToolAncestry(child,parent)
+ if child:FindFirstChild("RobloxBuildTool") then return end -- don't show roblox build tools
+ if child:IsA("Tool") or child:IsA("HopperBin") then
+ for i = 1, #gearSlots do
+ if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then
+ if parent == nil then
+ gearSlots[i].Kill.Value = true
+ return false
+ elseif child.Parent == player.Character then
+ gearSlots[i].Selected = true
+ return true
+ elseif child.Parent == player.Backpack then
+ if child:IsA("Tool") then gearSlots[i].Selected = false end
+ return true
+ else
+ gearSlots[i].Kill.Value = true
+ return false
+ end
+ return true
+ end
+ end
+ end
+end
+
+function removeAllEquippedGear(physGear)
+ local stuff = player.Character:GetChildren()
+ for i = 1, #stuff do
+ if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
+ if stuff[i]:IsA("Tool") then stuff[i].Parent = player.Backpack end
+ if stuff[i]:IsA("HopperBin") then
+ stuff[i]:Disable()
+ end
+ end
+ end
+end
+
+function hopperBinSwitcher(numKey, physGear)
+ if not physGear then return end
+
+ physGear:ToggleSelect()
+
+ if gearSlots[numKey] == "empty" then return end
+
+ if not physGear.Active then
+ gearSlots[numKey].Selected = false
+ normalizeButton(gearSlots[numKey])
+ else
+ gearSlots[numKey].Selected = true
+ enlargeButton(gearSlots[numKey])
+ end
+end
+
+function toolSwitcher(numKey)
+
+ if not gearSlots[numKey] then return end
+ local physGear = gearSlots[numKey].GearReference.Value
+ if physGear == nil then return end
+
+ removeAllEquippedGear(physGear) -- we don't remove this gear, as then we get a double switcheroo
+
+ local key = numKey
+ if numKey == 0 then key = 10 end
+
+ for i = 1, #gearSlots do
+ if gearSlots[i] and gearSlots[i] ~= "empty" and i ~= key then
+ normalizeButton(gearSlots[i])
+ gearSlots[i].Selected = false
+ if gearSlots[i].GearReference.Value:IsA("HopperBin") and gearSlots[i].GearReference.Value.Active then
+ gearSlots[i].GearReference.Value:ToggleSelect()
+ end
+ end
+ end
+
+ if physGear:IsA("HopperBin") then
+ hopperBinSwitcher(numKey,physGear)
+ else
+ if physGear.Parent == player.Character then
+ physGear.Parent = player.Backpack
+ gearSlots[numKey].Selected = false
+
+ normalizeButton(gearSlots[numKey])
+ else
+ physGear.Parent = player.Character
+ gearSlots[numKey].Selected = true
+
+ enlargeButton(gearSlots[numKey])
+ end
+ end
+end
+
+
+function activateGear(num)
+ local numKey = nil
+ if num == "0" then
+ numKey = 10 -- why do lua indexes have to start at 1? :(
+ else
+ numKey = tonumber(num)
+ end
+
+ if(numKey == nil) then return end
+
+ if gearSlots[numKey] ~= "empty" then
+ toolSwitcher(numKey)
+ end
+end
+
+
+enlargeButton = function(button)
+ if button.Size.Y.Scale > 1 then return end
+ if not button.Parent then return end
+ if not button.Selected then return end
+
+ for i = 1, #gearSlots do
+ if gearSlots[i] == "empty" then break end
+ if gearSlots[i] ~= button then
+ normalizeButton(gearSlots[i])
+ end
+ end
+
+ if not enlargeOverride then
+ waitingOnEnlarge = button
+ return
+ end
+
+ if button:IsA("ImageButton") or button:IsA("TextButton") then
+ button.ZIndex = 2
+ local centerizeX = -(buttonSizeEnlarge.X.Scale - button.Size.X.Scale)/2
+ local centerizeY = -(buttonSizeEnlarge.Y.Scale - button.Size.Y.Scale)/2
+ button:TweenSizeAndPosition(buttonSizeEnlarge,
+ UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset),
+ Enum.EasingDirection.Out, Enum.EasingStyle.Quad,guiTweenSpeed/5,enlargeOverride)
+ end
+end
+
+normalizeAllButtons = function()
+ for i = 1, #gearSlots do
+ if gearSlots[i] == "empty" then break end
+ if gearSlots[i] ~= button then
+ normalizeButton(gearSlots[i],0.1)
+ end
+ end
+end
+
+
+normalizeButton = function(button, speed)
+ if not button then return end
+ if button.Size.Y.Scale <= 1 then return end
+ if button.Selected then return end
+ if not button.Parent then return end
+
+ local moveSpeed = speed
+ if moveSpeed == nil or type(moveSpeed) ~= "number" then moveSpeed = guiTweenSpeed/5 end
+
+ if button:IsA("ImageButton") or button:IsA("TextButton") then
+ button.ZIndex = 1
+ local inverseEnlarge = 1/enlargeFactor
+ local centerizeX = -(buttonSizeNormal.X.Scale - button.Size.X.Scale)/2
+ local centerizeY = -(buttonSizeNormal.Y.Scale - button.Size.Y.Scale)/2
+ button:TweenSizeAndPosition(buttonSizeNormal,
+ UDim2.new(button.Position.X.Scale + centerizeX,button.Position.X.Offset,button.Position.Y.Scale + centerizeY,button.Position.Y.Offset),
+ Enum.EasingDirection.Out, Enum.EasingStyle.Quad,moveSpeed,enlargeOverride)
+ end
+end
+
+waitForDebounce = function()
+ if debounce.Value then
+ debounce.Changed:wait()
+ end
+end
+
+function pointInRectangle(point,rectTopLeft,rectSize)
+ if point.x > rectTopLeft.x and point.x < (rectTopLeft.x + rectSize.x) then
+ if point.y > rectTopLeft.y and point.y < (rectTopLeft.y + rectSize.y) then
+ return true
+ end
+ end
+ return false
+end
+
+function swapGear(gearClone,toFrame)
+ local toFrameChildren = toFrame:GetChildren()
+ if #toFrameChildren == 1 then
+ if toFrameChildren[1]:FindFirstChild("SlotNumber") then
+
+ local toSlot = tonumber(toFrameChildren[1].SlotNumber.Text)
+ local gearCloneSlot = tonumber(gearClone.SlotNumber.Text)
+ if toSlot == 0 then toSlot = 10 end
+ if gearCloneSlot == 0 then gearCloneSlot = 10 end
+
+ gearSlots[toSlot] = gearClone
+ gearSlots[gearCloneSlot] = toFrameChildren[1]
+
+ toFrameChildren[1].SlotNumber.Text = gearClone.SlotNumber.Text
+ toFrameChildren[1].SlotNumberDownShadow.Text = gearClone.SlotNumber.Text
+ toFrameChildren[1].SlotNumberUpShadow.Text = gearClone.SlotNumber.Text
+
+ local subString = string.sub(toFrame.Name,5)
+ gearClone.SlotNumber.Text = subString
+ gearClone.SlotNumberDownShadow.Text = subString
+ gearClone.SlotNumberUpShadow.Text = subString
+
+ gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0)
+ toFrameChildren[1].Position = UDim2.new(toFrameChildren[1].Position.X.Scale,0,toFrameChildren[1].Position.Y.Scale,0)
+
+ toFrameChildren[1].Parent = gearClone.Parent
+ gearClone.Parent = toFrame
+ end
+ else
+ local slotNum = tonumber(gearClone.SlotNumber.Text)
+ if slotNum == 0 then slotNum = 10 end
+ gearSlots[slotNum] = "empty" -- reset this gear slot
+
+ local subString = string.sub(toFrame.Name,5)
+ gearClone.SlotNumber.Text = subString
+ gearClone.SlotNumberDownShadow.Text = subString
+ gearClone.SlotNumberUpShadow.Text = subString
+
+ local toSlotNum = tonumber(gearClone.SlotNumber.Text)
+ if toSlotNum == 0 then toSlotNum = 10 end
+ gearSlots[toSlotNum] = gearClone
+ gearClone.Position = UDim2.new(gearClone.Position.X.Scale,0,gearClone.Position.Y.Scale,0)
+ gearClone.Parent = toFrame
+ end
+end
+
+function resolveDrag(gearClone,x,y)
+ local mousePoint = Vector2.new(x,y)
+
+ local frame = gearClone.Parent
+ local frames = frame.Parent:GetChildren()
+
+ for i = 1, #frames do
+ if frames[i]:IsA("Frame") then
+ if pointInRectangle(mousePoint, frames[i].AbsolutePosition,frames[i].AbsoluteSize) then
+ swapGear(gearClone,frames[i])
+ return true
+ end
+ end
+ end
+
+ if x < frame.AbsolutePosition.x or x > ( frame.AbsolutePosition.x + frame.AbsoluteSize.x ) then
+ reorganizeLoadout(gearClone,false)
+ return false
+ elseif y < frame.AbsolutePosition.y or y > ( frame.AbsolutePosition.y + frame.AbsoluteSize.y ) then
+ reorganizeLoadout(gearClone,false)
+ return false
+ else
+ gearClone.Position = dragBeginPos
+ return -1
+ end
+end
+
+function unequipAllItems(dontEquipThis)
+ for i = 1, #gearSlots do
+ if gearSlots[i] == "empty" then break end
+ if gearSlots[i].GearReference.Value ~= dontEquipThis then
+ if gearSlots[i].GearReference.Value:IsA("HopperBin") then
+ gearSlots[i].GearReference.Value:Disable()
+ elseif gearSlots[i].GearReference.Value:IsA("Tool") then
+ gearSlots[i].GearReference.Value.Parent = game.Players.LocalPlayer.Backpack
+ end
+ gearSlots[i].Selected = false
+ end
+ end
+end
+
+local addingPlayerChild = function(child, equipped, addToSlot, inventoryGearButton)
+ waitForDebounce()
+ debounce.Value = true
+
+ if child:FindFirstChild("RobloxBuildTool") then debounce.Value = false return end -- don't show roblox build tools
+ if not child:IsA("Tool") then
+ if not child:IsA("HopperBin") then
+ debounce.Value = false
+ return -- we don't care about anything besides tools (sigh...)
+ end
+ end
+
+ if not addToSlot then
+ for i = 1, #gearSlots do
+ if gearSlots[i] ~= "empty" and gearSlots[i].GearReference.Value == child then -- we already have gear, do nothing
+ debounce.Value = false
+ return
+ end
+ end
+ end
+
+
+ local gearClone = currentLoadout.CurrentLoadout.TempSlot:clone()
+ gearClone.Name = child.Name
+ gearClone.GearImage.Image = child.TextureId
+ if gearClone.GearImage.Image == "" then
+ gearClone.GearText.Text = child.Name
+ end
+ gearClone.GearReference.Value = child
+
+
+
+ local slotToMod = -1
+
+ if not addToSlot then
+ for i = 1, #gearSlots do
+ if gearSlots[i] == "empty" then
+ slotToMod = i
+ break
+ end
+ end
+ else
+ slotToMod = addToSlot
+ end
+
+ if slotToMod == - 1 then debounce.Value = false print("no slots!") return end -- No available slot to add in!
+
+ local slotNum = slotToMod % 10
+ local parent = currentLoadout.CurrentLoadout:FindFirstChild("Slot"..tostring(slotNum))
+ gearClone.Parent = parent
+
+ if inventoryGearButton then
+ local absolutePositionFinal = inventoryGearButton.AbsolutePosition
+ local currentAbsolutePosition = gearClone.AbsolutePosition
+ local diff = absolutePositionFinal - currentAbsolutePosition
+ gearClone.Position = UDim2.new(gearClone.Position.X.Scale,diff.x,gearClone.Position.Y.Scale,diff.y)
+ gearClone.ZIndex = 4
+ end
+
+ if addToSlot then
+ reorganizeLoadout(gearClone, true, equipped, addToSlot)
+ else
+ reorganizeLoadout(gearClone, true)
+ end
+
+ if gearClone.Parent == nil then debounce.Value = false return end -- couldn't fit in (hopper is full!)
+
+ if equipped then
+ gearClone.Selected = true
+ unequipAllItems(child)
+ delay(guiTweenSpeed + 0.01,function() -- if our gear is equipped, we will want to enlarge it when done moving
+ if (gearClone.GearReference.Value:IsA("Tool") and gearClone.GearReference.Value.Parent == player.Character) or
+ (gearClone.GearReference.Value:IsA("HopperBin") and gearClone.GearReference.Value.Active == true) then
+ enlargeButton(gearClone)
+ end
+ end)
+ end
+
+ local dragBeginPos = nil
+ local clickCon, buttonDeleteCon, mouseEnterCon, mouseLeaveCon, dragStop, dragBegin = nil
+ clickCon = gearClone.MouseButton1Click:connect(function() if not gearClone.Draggable then activateGear(gearClone.SlotNumber.Text) end end)
+ mouseEnterCon = gearClone.MouseEnter:connect(function()
+ if guiBackpack.Visible then
+ gearClone.Draggable = true
+ end
+ end)
+ dragBegin = gearClone.DragBegin:connect(function(pos)
+ dragBeginPos = pos
+ gearClone.ZIndex = 7
+ local children = gearClone:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("TextLabel") then
+ if string.find(children[i].Name,"Shadow") then
+ children[i].ZIndex = 8
+ else
+ children[i].ZIndex = 9
+ end
+ elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then
+ children[i].ZIndex = 7
+ end
+ end
+ end)
+ dragStop = gearClone.DragStopped:connect(function(x,y)
+ if gearClone.Selected then
+ gearClone.ZIndex = 2
+ else
+ gearClone.ZIndex = 1
+ end
+ local children = gearClone:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("TextLabel") then
+ if string.find(children[i].Name,"Shadow") then
+ children[i].ZIndex = 3
+ else
+ children[i].ZIndex = 4
+ end
+ elseif children[i]:IsA("Frame") or children[i]:IsA("ImageLabel") then
+ children[i].ZIndex = 2
+ end
+ end
+ resolveDrag(gearClone,x,y)
+ end)
+ mouseLeaveCon = gearClone.MouseLeave:connect(function()
+ gearClone.Draggable = false
+ end)
+ buttonDeleteCon = gearClone.AncestryChanged:connect(function()
+ if gearClone.Parent and gearClone.Parent.Parent == currentLoadout then return end
+ if clickCon then clickCon:disconnect() end
+ if buttonDeleteCon then buttonDeleteCon:disconnect() end
+ if mouseEnterCon then mouseEnterCon:disconnect() end
+ if mouseLeaveCon then mouseLeaveCon:disconnect() end
+ if dragStop then dragStop:disconnect() end
+ if dragBegin then dragBegin:disconnect() end
+ end) -- this probably isn't necessary since objects are being deleted (probably), but this might still leak just in case
+
+ local childCon = nil
+ local childChangeCon = nil
+ childCon = child.AncestryChanged:connect(function(newChild,parent)
+ if not checkToolAncestry(newChild,parent) then
+ if childCon then childCon:disconnect() end
+ if childChangeCon then childChangeCon:disconnect() end
+ removeFromInventory(child)
+ elseif parent == game.Players.LocalPlayer.Backpack then
+ normalizeButton(gearClone)
+ end
+ end)
+
+ childChangeCon = child.Changed:connect(function(prop)
+ if prop == "Name" then
+ if gearClone and gearClone.GearImage.Image == "" then
+ gearClone.GearText.Text = child.Name
+ end
+ end
+ end)
+
+ debounce.Value = false
+
+end
+
+function addToInventory(child)
+ if not child:IsA("Tool") or not child:IsA("HopperBin") then return end
+
+ local slot = nil
+ for i = 1, #inventory do
+ if inventory[i] and inventory[i] == child then return end
+ if not inventory[i] then slot = i end
+ end
+ if slot then
+ inventory[slot] = child
+ elseif #inventory < 1 then
+ inventory[1] = child
+ else
+ inventory[#inventory + 1] = child
+ end
+end
+
+function removeFromInventory(child)
+ for i = 1, #inventory do
+ if inventory[i] == child then
+ table.remove(inventory,i)
+ inventory[i] = nil
+ end
+ end
+end
+
+-- these next two functions are used for safe guarding
+-- when we are waiting for character to come back after dying
+function activateLoadout()
+ keyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) activateGear(key) end)
+ currentLoadout.Visible = true
+end
+
+function deactivateLoadout()
+ if keyPressCon then keyPressCon:disconnect() end
+ currentLoadout.CurrentLoadout.Visible = false
+end
+
+function setupBackpackListener()
+ if backpackChildCon then backpackChildCon:disconnect() end
+ backpackChildCon = player.Backpack.ChildAdded:connect(function(child)
+ addingPlayerChild(child)
+ addToInventory(child)
+ end)
+end
+
+function playerCharacterChildAdded(child)
+ addingPlayerChild(child,true)
+ addToInventory(child)
+end
+-- End Functions
+
+
+
+
+
+
+-- Begin Script
+wait() -- let stuff initialize incase this is first heartbeat...
+
+waitForChild(player,"Backpack")
+local backpackChildren = player.Backpack:GetChildren()
+local size = math.min(10,#backpackChildren)
+for i = 1, size do
+ addingPlayerChild(backpackChildren[i],false)
+end
+setupBackpackListener()
+
+waitForProperty(player,"Character")
+for i,v in ipairs(player.Character:GetChildren()) do
+ playerCharacterChildAdded(v)
+end
+characterChildAddedCon = player.Character.ChildAdded:connect(function(child) playerCharacterChildAdded(child) end)
+
+waitForChild(player.Character,"Humanoid")
+humanoidDiedCon = player.Character.Humanoid.Died:connect(function() deactivateLoadout() end)
+
+player.CharacterRemoving:connect(function()
+ if characterChildAddedCon then characterChildAddedCon:disconnect() end
+ if humanoidDiedCon then humanoidDiedCon:disconnect() end
+ if backpackChildCon then backpackChildCon:disconnect() end
+ deactivateLoadout()
+end)
+player.CharacterAdded:connect(function()
+ player = game.Players.LocalPlayer -- make sure we are still looking at the correct character
+
+ for i = 1, #gearSlots do
+ if gearSlots[i] ~= "empty" then
+ gearSlots[i].Parent = nil
+ gearSlots[i] = "empty"
+ end
+ end
+
+ local backpackChildren = player.Backpack:GetChildren()
+ local size = math.min(10,#backpackChildren)
+ for i = 1, size do
+ addingPlayerChild(backpackChildren[i])
+ end
+
+ setupBackpackListener()
+
+ characterChildAddedCon =
+ player.Character.ChildAdded:connect(function(child)
+ addingPlayerChild(child,true)
+ end)
+
+ waitForChild(player.Character,"Humanoid")
+ humanoidDiedCon =
+ player.Character.Humanoid.Died:connect(function()
+ deactivateLoadout()
+ end)
+ activateLoadout()
+end)
+
+script.Parent.ControlFrame.BackpackButton.MouseButton1Click:connect(function()
+centerGear()
+end)
+
+waitForChild(guiBackpack,"SwapSlot")
+guiBackpack.SwapSlot.Changed:connect(function()
+ if guiBackpack.SwapSlot.Value then
+ local swapSlot = guiBackpack.SwapSlot
+ local pos = swapSlot.Slot.Value
+ if pos == 0 then pos = 10 end
+ if gearSlots[pos] then
+ reorganizeLoadout(gearSlots[pos],false)
+ end
+ if swapSlot.GearButton.Value then
+ addingPlayerChild(swapSlot.GearButton.Value.GearReference.Value,false,pos)
+ end
+ guiBackpack.SwapSlot.Value = false
+ end
+end)
+
+keyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key) activateGear(key) end)
+
+
+ -
+
+ false
+ 4288914085
+ 1
+ 4279970357
+ 1
+ false
+ false
+ ControlFrame
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+ 0
+
+ 0
+ 0
+ true
+ 1
+
+
-
+
+ false
+ 4288914085
+ 1
+ 4279970357
+ 1
+ false
+ false
+ NotificationBox
+
+ 1
+ -200
+ 0.5
+ 0
+
+
+ 0
+ 200
+ 0.419999987
+ 0
+
+ 0
+ true
+ 1
+
+
+
+ -
+
+ false
+
+ BackpackMaker
+ local BackpackButton = Instance.new("ImageButton")
+BackpackButton.Visible = true
+BackpackButton.Name = "BackpackButton"
+BackpackButton.BackgroundTransparency = 1
+BackpackButton.Image = "rbxasset://textures/ui/backpackButton.png"
+BackpackButton.Position = UDim2.new(0.5, -195, 1, -30)
+BackpackButton.Size = UDim2.new(0,107,0,26)
+BackpackButton.Parent = script.Parent.ControlFrame
+
+-- this makes the backpackbutton without making the backpack D I E --
+
+
+ -
+
+ false
+
+ BackpackManager
+ -- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search)
+print("mamanger")
+print("made it past gui version check")
+
+-- basic functions
+local function waitForChild(instance, name)
+ while not instance:FindFirstChild(name) do
+ instance.ChildAdded:wait()
+ end
+ return instance:FindFirstChild(name)
+end
+local function waitForProperty(instance, property)
+ while not instance[property] do
+ instance.Changed:wait()
+ end
+end
+
+-- don't do anything if we are in an empty game
+waitForChild(game,"Players")
+if #game.Players:GetChildren() < 1 then
+ game.Players.ChildAdded:wait()
+end
+-- make sure everything is loaded in before we do anything
+-- get our local player
+waitForProperty(game.Players,"LocalPlayer")
+local player = game.Players.LocalPlayer
+
+
+
+------------------------ Locals ------------------------------
+local backpack = script.Parent.Backpack
+waitForChild(backpack,"Gear")
+
+local screen = script.Parent
+assert(screen:IsA("ScreenGui"))
+
+waitForChild(backpack, "Tabs")
+waitForChild(backpack.Tabs, "CloseButton")
+local closeButton = backpack.Tabs.CloseButton
+
+waitForChild(backpack.Tabs, "InventoryButton")
+local inventoryButton = backpack.Tabs.InventoryButton
+waitForChild(backpack.Parent,"ControlFrame")
+local backpackButton = waitForChild(backpack.Parent.ControlFrame,"BackpackButton")
+local currentTab = "gear"
+
+local searchFrame = waitForChild(backpack,"SearchFrame")
+waitForChild(backpack.SearchFrame,"SearchBoxFrame")
+local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame,"SearchBox")
+local searchButton = waitForChild(backpack.SearchFrame,"SearchButton")
+local resetButton = waitForChild(backpack.SearchFrame,"ResetButton")
+
+local canToggle = true
+local readyForNextEvent = true
+local backpackIsOpen = false
+local active = true
+
+local humanoidDiedCon = nil
+
+local guiTweenSpeed = 0.25 -- how quickly we open/close the backpack
+
+local searchDefaultText = "Search..."
+local tilde = "~"
+local backquote = "`"
+
+------------------------ End Locals ---------------------------
+
+
+---------------------------------------- Public Event Setup ----------------------------------------
+
+function createPublicEvent(eventName)
+ assert(eventName, "eventName is nil")
+ assert(tostring(eventName),"eventName is not a string")
+
+ local newEvent = Instance.new("BindableEvent")
+ newEvent.Name = tostring(eventName)
+ newEvent.Parent = script
+
+ return newEvent
+end
+
+function createPublicFunction(funcName, invokeFunc)
+ assert(funcName, "funcName is nil")
+ assert(tostring(funcName), "funcName is not a string")
+ assert(invokeFunc, "invokeFunc is nil")
+ assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'")
+
+ local newFunction = Instance.new("BindableFunction")
+ newFunction.Name = tostring(funcName)
+ newFunction.OnInvoke = invokeFunc
+ newFunction.Parent = script
+
+ return newFunction
+end
+
+-- Events
+local resizeEvent = createPublicEvent("ResizeEvent")
+local backpackOpenEvent = createPublicEvent("BackpackOpenEvent")
+local backpackCloseEvent = createPublicEvent("BackpackCloseEvent")
+local tabClickedEvent = createPublicEvent("TabClickedEvent")
+local searchRequestedEvent = createPublicEvent("SearchRequestedEvent")
+---------------------------------------- End Public Event Setup ----------------------------------------
+
+
+
+--------------------------- Internal Functions ----------------------------------------
+
+function deactivateBackpack()
+ backpack.Visible = false
+ active = false
+end
+
+function activateBackpack()
+ initHumanoidDiedConnections()
+ active = true
+ backpack.Visible = backpackIsOpen
+end
+
+function initHumanoidDiedConnections()
+ if humanoidDiedCon then
+ humanoidDiedCon:disconnect()
+ end
+ waitForProperty(game.Players.LocalPlayer,"Character")
+ waitForChild(game.Players.LocalPlayer.Character,"Humanoid")
+ humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack)
+end
+
+function resizeGrid()
+ local backpackItems = {}
+ for k,v in pairs(backpackItems) do
+ if not v:FindFirstChild("RobloxBuildTool") then
+ if not buttons[v] then
+ local buttonClone = gearButton:clone()
+ buttonClone.Parent = grid.ScrollingFrame
+ buttonClone.Visible = true
+ buttonClone.Image = v.TextureId
+ if buttonClone.Image == "" then
+ buttonClone.GearText.Text = v.Name
+ end
+ buttonClone.GearReference.Value = v
+ buttonClone.Draggable = true
+ buttons[v] = buttonClone
+
+ local unequipMenu = getGearContextMenu()
+
+ unequipMenu.Visible = false
+ unequipMenu.Parent = buttonClone
+
+ local beginPos = nil
+ buttonClone.DragBegin:connect(function(value)
+ buttonClone.ZIndex = 9
+ beginPos = value
+ end)
+ buttonClone.DragStopped:connect(function(x,y)
+ if beginPos ~= buttonClone.Position then
+ buttonClone.ZIndex = 1
+ if not checkForSwap(buttonClone,x,y) then
+ buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
+ else
+ buttonClone.Position = beginPos
+ end
+ end
+ end)
+
+ mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
+ mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() buttonClick(buttonClone) end)
+ end
+ end
+ end
+end
+
+function spreadOutGear(loadoutChildren)
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
+ if slot == 0 then slot = 10 end
+ loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
+ end
+ end
+end
+
+function resize()
+ local size = 0
+ local gearPreview = script.Parent.Backpack.Gear.GearPreview
+ if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
+ size = gearPreview.AbsoluteSize.X * 0.75
+ else
+ size = gearPreview.AbsoluteSize.Y * 0.75
+ end
+
+ gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
+ gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
+
+ resizeGrid()
+end
+
+function openCloseBackpack()
+ if backpack.Visible == true then
+ updateGridActive()
+
+ loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ loadoutChildren[i].BackgroundTransparency = 0.5
+ end
+ end
+ spreadOutGear(loadoutChildren)
+
+ --[[backpackButton.Selected = true
+ backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
+ delay(guiTweenSpeed/2 + 0.01,
+ function()--]]
+ local children = backpack:getChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ children[i].Visible = true
+ end
+ end
+ resizeGrid()
+ resize()
+ openCloseDebounce = false
+
+
+ end
+end
+
+function centerGear()
+
+ local Loadout = script.Parent.CurrentLoadout
+ Loadout.Position = UDim2.new(0.45, -170, 1, -85)
+ loadoutChildren = Loadout:GetChildren()
+ local gearButtons = {}
+ local lastSlotAdd = nil
+ for i = 1,#loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ if #loadoutChildren[i]:GetChildren() > 0 then
+ if loadoutChildren[i].Name == "Slot0" then
+ lastSlotAdd = loadoutChildren[i]
+ else
+ table.insert(gearButtons,loadoutChildren[i])
+ end
+ end
+ loadoutChildren[i].BackgroundTransparency = 1
+
+ end
+ end
+ if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
+
+ local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
+ for i = 1,#gearButtons do
+ gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0),Enum.EasingDirection.Out,Enum.EasingStyle.Quad,0.25,true)
+ end
+end
+
+local hideBackpack = function()
+ backpackIsOpen = false
+ readyForNextEvent = false
+ backpackButton.Selected = false
+ resetSearch()
+ backpackCloseEvent:Fire(currentTab)
+ backpack.Tabs.Visible = false
+ searchFrame.Visible = false
+ loadoutChildren = script.Parent.CurrentLoadout:GetChildren()
+ for i = 1,#loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ if #loadoutChildren[i]:GetChildren() > 0 then
+ if loadoutChildren[i].Name == "Slot0" then
+ lastSlotAdd = loadoutChildren[i]
+ end
+end
+
+ loadoutChildren[i].BackgroundTransparency = 1
+ centerGear()
+ end
+ backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true,
+ function()
+ game.GuiService:RemoveCenterDialog(backpack)
+ backpack.Visible = false
+ backpackButton.Selected = false
+ end)
+ delay(guiTweenSpeed,function()
+ game.GuiService:RemoveCenterDialog(backpack)
+ backpack.Visible = false
+ backpackButton.Selected = false
+ canToggle = true
+ end)
+end
+
+end
+
+function showBackpack()
+ game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog,
+ function()
+ backpack.Visible = true
+ backpackButton.Selected = true
+ end,
+ function()
+ backpack.Visible = false
+ backpackButton.Selected = false
+ end)
+ backpack.Visible = true
+ backpackButton.Selected = true
+ backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.76, 0),UDim2.new(0.225, 0, 0.09, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true)
+ delay(guiTweenSpeed,function()
+ openCloseBackpack()
+ backpack.Tabs.Visible = true
+ searchFrame.Visible = true
+ backpackOpenEvent:Fire(currentTab)
+ canToggle = true
+ end)
+end
+
+function spreadOutGear(loadoutChildren)
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
+ if slot == 0 then slot = 10 end
+ loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
+ end
+ end
+end
+
+function toggleBackpack()
+ if not game.Players.LocalPlayer then return end
+ if not game.Players.LocalPlayer["Character"] then return end
+
+ if not canToggle then return end
+ if not readyForNextEvent then return end
+ readyForNextEvent = false
+ canToggle = false
+
+ backpackIsOpen = not backpackIsOpen
+
+ if backpackIsOpen then
+
+ showBackpack()
+
+ else
+ backpackButton.Selected = false
+ closeBackpack()
+ end
+end
+
+function updateGridActive()
+ local backpackItems = {}
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ local gear = nil
+ local gearRef = buttons[v]:FindFirstChild("GearReference")
+
+ if gearRef then gear = gearRef.Value end
+
+ if not gear then
+ buttons[v].Active = false
+ elseif inLoadout(gear) then
+ buttons[v].Active = false
+ else
+ buttons[v].Active = true
+ end
+ end
+ end
+end
+
+function openCloseBackpack()
+
+ if backpack.Visible == true then
+ updateGridActive()
+ local currentLoadout = script.Parent.CurrentLoadout
+ backpack.Visible = true
+ loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ loadoutChildren[i].BackgroundTransparency = 0.5
+ end
+ end
+ spreadOutGear(loadoutChildren)
+
+
+ backpackButton.Selected = true
+ backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
+ delay(guiTweenSpeed/2 + 0.01,
+ function()
+ local children = backpack:getChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ children[i].Visible = true
+ end
+ end
+ resizeGrid()
+ resize()
+ openCloseDebounce = false
+ end)
+
+ else
+ backpackButton.Selected = false
+ local children = backpack:getChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ children[i].Visible = false
+ end
+ end
+ loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ loadoutChildren[i].BackgroundTransparency = 1
+ end
+ end
+ centerGear(loadoutChildren)
+
+ backpack:TweenSizeAndPosition(UDim2.new(0,0,0,0),UDim2.new(0.5,0,0.5,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
+ delay(guiTweenSpeed/2 + 0.01,
+ function()
+ backpack.Visible = visible
+ resizeGrid()
+ resize()
+ pcall(function() game.GuiService:RemoveCenterDialog(backpack) end)
+ openCloseDebounce = false
+ end)
+ end
+end
+
+function closeBackpack()
+ if backpackIsOpen then
+ toggleBackpack()
+ end
+end
+
+function setSelected(tab)
+ assert(tab)
+ assert(tab:IsA("TextButton"))
+
+ tab.BackgroundColor3 = Color3.new(1,1,1)
+ tab.TextColor3 = Color3.new(0,0,0)
+ tab.Selected = true
+ tab.ZIndex = 3
+end
+
+function setUnselected(tab)
+ assert(tab)
+ assert(tab:IsA("TextButton"))
+
+ tab.BackgroundColor3 = Color3.new(0,0,0)
+ tab.TextColor3 = Color3.new(1,1,1)
+ tab.Selected = false
+ tab.ZIndex = 1
+end
+
+function updateTabGui(selectedTab)
+ assert(selectedTab)
+
+ if selectedTab == "gear" then
+ setSelected(inventoryButton)
+ setUnselected(wardrobeButton)
+ elseif selectedTab == "wardrobe" then
+ setSelected(wardrobeButton)
+ setUnselected(inventoryButton)
+ end
+end
+
+function mouseLeaveTab(button)
+ assert(button)
+ assert(button:IsA("TextButton"))
+
+ if button.Selected then return end
+
+ button.BackgroundColor3 = Color3.new(0,0,0)
+end
+
+function mouseOverTab(button)
+ assert(button)
+ assert(button:IsA("TextButton"))
+
+ if button.Selected then return end
+
+ button.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+end
+
+function newTabClicked(tabName)
+ assert(tabName)
+ tabName = string.lower(tabName)
+ currentTab = tabName
+
+ updateTabGui(tabName)
+ tabClickedEvent:Fire(tabName)
+ resetSearch()
+end
+
+function trim(s)
+ return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+function splitByWhitespace(text)
+ if type(text) ~= "string" then return nil end
+
+ local terms = {}
+ for token in string.gmatch(text, "[^%s]+") do
+ if string.len(token) > 0 then
+ table.insert(terms,token)
+ end
+ end
+ return terms
+end
+
+function resetSearchBoxGui()
+ resetButton.Visible = false
+ searchBox.Text = searchDefaultText
+end
+
+function doSearch()
+ local searchText = searchBox.Text
+ if searchText == "" then
+ resetSearch()
+ return
+ end
+ searchText = trim(searchText)
+ resetButton.Visible = true
+ termTable = splitByWhitespace(searchText)
+ searchRequestedEvent:Fire(searchText) -- todo: replace this with termtable when table passing is possible
+end
+
+function resetSearch()
+ resetSearchBoxGui()
+ searchRequestedEvent:Fire()
+end
+
+local backpackReady = function()
+ readyForNextEvent = true
+end
+
+--------------------------- End Internal Functions -------------------------------------
+
+
+------------------------------ Public Functions Setup -------------------------------------
+createPublicFunction("CloseBackpack", hideBackpack)
+createPublicFunction("BackpackReady", backpackReady)
+------------------------------ End Public Functions Setup ---------------------------------
+
+
+------------------------ Connections/Script Main -------------------------------------------
+
+inventoryButton.MouseButton1Click:connect(function() newTabClicked("gear") end)
+inventoryButton.MouseEnter:connect(function() mouseOverTab(inventoryButton) end)
+inventoryButton.MouseLeave:connect(function() mouseLeaveTab(inventoryButton) end)
+
+
+closeButton.MouseButton1Click:connect(hideBackpack)
+
+screen.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ resizeEvent:Fire(screen.AbsoluteSize)
+ end
+end)
+
+-- GuiService key setup
+local testkey = "'"
+game:GetService("GuiService"):AddKey(testkey)
+game:GetService("GuiService"):AddKey(tilde)
+game:GetService("GuiService").KeyPressed:connect(function(key)
+ if not active then return end
+ if key == tilde or key == backquote then
+ toggleBackpack()
+ showBackpack()
+ end
+end)
+backpackButton.MouseButton1Click:connect(function()
+
+toggleBackpack()
+showBackpack()
+--openCloseBackpack()
+
+end)
+
+if game.Players.LocalPlayer["Character"] then
+ activateBackpack()
+end
+game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack)
+
+-- search functions
+searchBox.FocusLost:connect(function(enterPressed)
+ if enterPressed or searchBox.Text ~= "" then
+ doSearch()
+ elseif searchBox.Text == "" then
+ resetSearch()
+ end
+end)
+searchButton.MouseButton1Click:connect(doSearch)
+resetButton.MouseButton1Click:connect(resetSearch)
+
+backpackButton.Visible = true
+
+
+ -
+
+ false
+
+ BackpackGear
+ local t = {}
+
+local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
+ local eventConnection = nil
+
+ --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
+ local tryConnect = function()
+ if game:IsAncestorOf(parentInstance) then
+ --Entering the world, make sure we are connected/synced
+ if not eventConnection then
+ eventConnection = instance[event]:connect(signalFunc)
+ if syncFunc then syncFunc() end
+ end
+ else
+ --Probably leaving the world, so disconnect for now
+ if eventConnection then
+ eventConnection:disconnect()
+ if removeFunc then removeFunc() end
+ end
+ end
+ end
+
+ --Hook it up to ancestryChanged signal
+ local connection = parentInstance.AncestryChanged:connect(tryConnect)
+
+ --Now connect us if we're already in the world
+ tryConnect()
+
+ return connection
+end
+
+local function getScreenGuiAncestor(instance)
+ local localInstance = instance
+ while localInstance and not localInstance:IsA("ScreenGui") do
+ localInstance = localInstance.Parent
+ end
+ return localInstance
+end
+
+local function CreateButtons(frame, buttons, yPos, ySize)
+ local buttonNum = 1
+ local buttonObjs = {}
+ for i, obj in ipairs(buttons) do
+ local button = Instance.new("TextButton")
+ button.Name = "Button" .. buttonNum
+ button.Font = Enum.Font.Arial
+ button.FontSize = Enum.FontSize.Size18
+ button.AutoButtonColor = true
+ button.Modal = true
+ if obj["Style"] then
+ button.Style = obj.Style
+ else
+ button.Style = Enum.ButtonStyle.RobloxButton
+ end
+ button.Text = obj.Text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.MouseButton1Click:connect(obj.Function)
+ button.Parent = frame
+ buttonObjs[buttonNum] = button
+
+ buttonNum = buttonNum + 1
+ end
+ local numButtons = buttonNum-1
+
+ if numButtons == 1 then
+ frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
+ elseif numButtons == 2 then
+ frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
+
+ frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
+ frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
+ elseif numButtons >= 3 then
+ local spacing = .1 / numButtons
+ local buttonSize = .9 / numButtons
+
+ buttonNum = 1
+ while buttonNum <= numButtons do
+ buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
+ buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
+ buttonNum = buttonNum + 1
+ end
+ end
+end
+
+local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
+
+ local newStep = steps - 1 --otherwise we really get one more step than we want
+ local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
+ local wholeNum, remainder = math.modf(relativePosX * newStep)
+ if remainder > 0.5 then
+ wholeNum = wholeNum + 1
+ end
+ relativePosX = wholeNum/newStep
+
+ local result = math.ceil(relativePosX * newStep)
+ if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
+ sliderPosition.Value = result + 1
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end
+
+end
+
+local function cancelSlide(areaSoak)
+ areaSoak.Visible = false
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+end
+
+t.CreateStyledMessageDialog = function(title, message, style, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0, 165)
+ frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local styleImage = Instance.new("ImageLabel")
+ styleImage.Name = "StyleImage"
+ styleImage.BackgroundTransparency = 1
+ styleImage.Position = UDim2.new(0,5,0,15)
+ if style == "error" or style == "Error" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "rbxasset://ui/error.png"
+ elseif style == "notify" or style == "Notify" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "rbxasset://ui/notify.png"
+ elseif style == "confirm" or style == "Confirm" then
+ styleImage.Size = UDim2.new(0, 74, 0, 76)
+ styleImage.Image = "rbxasset://ui/confirm.png"
+ else
+ return t.CreateMessageDialog(title,message,buttons)
+ end
+ styleImage.Parent = frame
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.TextStrokeTransparency = 0
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 80, 0, 0)
+ titleLabel.Size = UDim2.new(1, -80, 0, 40)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextStrokeTransparency = 0
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
+ messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
+
+ return frame
+end
+
+t.CreateMessageDialog = function(title, message, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0.5, 0)
+ frame.Position = UDim2.new(0.25, 0, 0.25, 0)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 0, 0, 0)
+ titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
+ messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
+
+ return frame
+end
+
+t.CreateDropDownMenu = function(items, onSelect, forRoblox)
+ local width = UDim.new(0, 100)
+ local height = UDim.new(0, 32)
+
+ local xPos = 0.055
+ local frame = Instance.new("Frame")
+ frame.Name = "DropDownMenu"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(width, height)
+
+ local dropDownMenu = Instance.new("TextButton")
+ dropDownMenu.Name = "DropDownMenuButton"
+ dropDownMenu.TextWrap = true
+ dropDownMenu.TextColor3 = Color3.new(1,1,1)
+ dropDownMenu.Text = "Choose One"
+ dropDownMenu.Font = Enum.Font.ArialBold
+ dropDownMenu.FontSize = Enum.FontSize.Size18
+ dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
+ dropDownMenu.BackgroundTransparency = 1
+ dropDownMenu.AutoButtonColor = true
+ dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ dropDownMenu.Size = UDim2.new(1,0,1,0)
+ dropDownMenu.Parent = frame
+ dropDownMenu.ZIndex = 2
+
+ local dropDownIcon = Instance.new("ImageLabel")
+ dropDownIcon.Name = "Icon"
+ dropDownIcon.Active = false
+ dropDownIcon.Image = "rbxasset://ui/dropdownicon.png"
+ dropDownIcon.BackgroundTransparency = 1
+ dropDownIcon.Size = UDim2.new(0,11,0,6)
+ dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
+ dropDownIcon.Parent = dropDownMenu
+ dropDownIcon.ZIndex = 2
+
+ local itemCount = #items
+ local dropDownItemCount = #items
+ local useScrollButtons = false
+ if dropDownItemCount > 6 then
+ useScrollButtons = true
+ dropDownItemCount = 6
+ end
+
+ local droppedDownMenu = Instance.new("TextButton")
+ droppedDownMenu.Name = "List"
+ droppedDownMenu.Text = ""
+ droppedDownMenu.BackgroundTransparency = 1
+ --droppedDownMenu.AutoButtonColor = true
+ droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ droppedDownMenu.Visible = false
+ droppedDownMenu.Active = true --Blocks clicks
+ droppedDownMenu.Position = UDim2.new(0,0,0,0)
+ droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
+ droppedDownMenu.Parent = frame
+ droppedDownMenu.ZIndex = 2
+
+ local choiceButton = Instance.new("TextButton")
+ choiceButton.Name = "ChoiceButton"
+ choiceButton.BackgroundTransparency = 1
+ choiceButton.BorderSizePixel = 0
+ choiceButton.Text = "ReplaceMe"
+ choiceButton.TextColor3 = Color3.new(1,1,1)
+ choiceButton.TextXAlignment = Enum.TextXAlignment.Left
+ choiceButton.TextYAlignment = Enum.TextYAlignment.Center
+ choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
+ choiceButton.Font = Enum.Font.Arial
+ choiceButton.FontSize = Enum.FontSize.Size18
+ if useScrollButtons then
+ choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
+ else
+ choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
+ end
+ choiceButton.TextWrap = true
+ choiceButton.ZIndex = 2
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = true
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 3
+
+ local dropDownSelected = false
+
+ local scrollUpButton
+ local scrollDownButton
+ local scrollMouseCount = 0
+
+ local setZIndex = function(baseZIndex)
+ droppedDownMenu.ZIndex = baseZIndex +1
+ if scrollUpButton then
+ scrollUpButton.ZIndex = baseZIndex + 3
+ end
+ if scrollDownButton then
+ scrollDownButton.ZIndex = baseZIndex + 3
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child.Name == "ChoiceButton" then
+ child.ZIndex = baseZIndex + 2
+ elseif child.Name == "ClickCaptureButton" then
+ child.ZIndex = baseZIndex
+ end
+ end
+ end
+ end
+
+ local scrollBarPosition = 1
+ local updateScroll = function()
+ if scrollUpButton then
+ scrollUpButton.Active = scrollBarPosition > 1
+ end
+ if scrollDownButton then
+ scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if not children then return end
+
+ local childNum = 1
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
+ obj.Visible = false
+ else
+ obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
+ obj.Visible = true
+ end
+ obj.TextColor3 = Color3.new(1,1,1)
+ obj.BackgroundTransparency = 1
+
+ childNum = childNum + 1
+ end
+ end
+ end
+ local toggleVisibility = function()
+ dropDownSelected = not dropDownSelected
+
+ areaSoak.Visible = not areaSoak.Visible
+ dropDownMenu.Visible = not dropDownSelected
+ droppedDownMenu.Visible = dropDownSelected
+ if dropDownSelected then
+ setZIndex(4)
+ else
+ setZIndex(2)
+ end
+ if useScrollButtons then
+ updateScroll()
+ end
+ end
+ droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
+
+ local updateSelection = function(text)
+ local foundItem = false
+ local children = droppedDownMenu:GetChildren()
+ local childNum = 1
+ if children then
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if obj.Text == text then
+ obj.Font = Enum.Font.ArialBold
+ foundItem = true
+ scrollBarPosition = childNum
+ else
+ obj.Font = Enum.Font.Arial
+ end
+ childNum = childNum + 1
+ end
+ end
+ end
+ if not text then
+ dropDownMenu.Text = "Choose One"
+ scrollBarPosition = 1
+ else
+ if not foundItem then
+ error("Invalid Selection Update -- " .. text)
+ end
+
+ if scrollBarPosition + dropDownItemCount > itemCount + 1 then
+ scrollBarPosition = itemCount - dropDownItemCount + 1
+ end
+
+ dropDownMenu.Text = text
+ end
+ end
+
+ local function scrollDown()
+ if scrollBarPosition + dropDownItemCount <= itemCount then
+ scrollBarPosition = scrollBarPosition + 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+ local function scrollUp()
+ if scrollBarPosition > 1 then
+ scrollBarPosition = scrollBarPosition - 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+
+ if useScrollButtons then
+ --Make some scroll buttons
+ scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+ scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
+ scrollUpButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollUp()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollUp() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ scrollUpButton.Parent = droppedDownMenu
+
+ scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+ scrollDownButton.Position = UDim2.new(1,-11,1,-11)
+ scrollDownButton.Parent = droppedDownMenu
+ scrollDownButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollDown()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollDown() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ local scrollbar = Instance.new("ImageLabel")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
+ scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
+ scrollbar.Parent = droppedDownMenu
+ end
+
+ for i,item in ipairs(items) do
+ -- needed to maintain local scope for items in event listeners below
+ local button = choiceButton:clone()
+ if forRoblox then
+ button.RobloxLocked = true
+ end
+ button.Text = item
+ button.Parent = droppedDownMenu
+ button.MouseButton1Click:connect(function()
+ --Remove Highlight
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundTransparency = 1
+
+ updateSelection(item)
+ onSelect(item)
+
+ toggleVisibility()
+ end)
+ button.MouseEnter:connect(function()
+ --Add Highlight
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ end)
+
+ button.MouseLeave:connect(function()
+ --Remove Highlight
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundTransparency = 1
+ end)
+ end
+
+ --This does the initial layout of the buttons
+ updateScroll()
+
+ frame.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(frame)
+ end
+ end)
+
+ dropDownMenu.MouseButton1Click:connect(toggleVisibility)
+ areaSoak.MouseButton1Click:connect(toggleVisibility)
+ return frame, updateSelection
+end
+
+t.CreatePropertyDropDownMenu = function(instance, property, enum)
+
+ local items = enum:GetEnumItems()
+ local names = {}
+ local nameToItem = {}
+ for i,obj in ipairs(items) do
+ names[i] = obj.Name
+ nameToItem[obj.Name] = obj
+ end
+
+ local frame
+ local updateSelection
+ frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
+
+ ScopedConnect(frame, instance, "Changed",
+ function(prop)
+ if prop == property then
+ updateSelection(instance[property].Name)
+ end
+ end,
+ function()
+ updateSelection(instance[property].Name)
+ end)
+
+ return frame
+end
+
+t.GetFontHeight = function(font, fontSize)
+ if font == nil or fontSize == nil then
+ error("Font and FontSize must be non-nil")
+ end
+
+ if font == Enum.Font.Legacy then
+ if fontSize == Enum.FontSize.Size8 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 15
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 17
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 21
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 27
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 54
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 72
+ else
+ error("Unknown FontSize")
+ end
+ elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
+ if fontSize == Enum.FontSize.Size8 then
+ return 8
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 9
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 10
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 11
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 24
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 48
+ else
+ error("Unknown FontSize")
+ end
+ else
+ error("Unknown Font " .. font)
+ end
+end
+
+local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+ for i, child in ipairs(guiObjects) do
+ if child:IsA("TextLabel") or child:IsA("TextButton") then
+ local isLabel = child:IsA("TextLabel")
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
+
+ if child.TextFits and child.TextBounds.Y < pixelsRemaining then
+ child.Visible = true
+ if isLabel then
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
+ else
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
+ end
+
+ while not child.TextFits do
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
+ end
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ else
+ child.Visible = false
+ pixelsRemaining = -1
+ end
+
+ else
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ child.Visible = (pixelsRemaining >= 0)
+ end
+ end
+end
+
+t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
+ if not frame:IsA("GuiObject") then
+ error("Frame must be a GuiObject")
+ end
+ for i, child in ipairs(guiObjects) do
+ if not child:IsA("GuiObject") then
+ error("All elements that are layed out must be of type GuiObject")
+ end
+ end
+
+ if not settingsTable then
+ settingsTable = {}
+ end
+
+ if not settingsTable["TextLabelSizePadY"] then
+ settingsTable["TextLabelSizePadY"] = 0
+ end
+ if not settingsTable["TextLabelPositionPadY"] then
+ settingsTable["TextLabelPositionPadY"] = 0
+ end
+ if not settingsTable["TextButtonSizePadY"] then
+ settingsTable["TextButtonSizePadY"] = 12
+ end
+ if not settingsTable["TextButtonPositionPadY"] then
+ settingsTable["TextButtonPositionPadY"] = 2
+ end
+
+ --Wrapper frame takes care of styled objects
+ local wrapperFrame = Instance.new("Frame")
+ wrapperFrame.Name = "WrapperFrame"
+ wrapperFrame.BackgroundTransparency = 1
+ wrapperFrame.Size = UDim2.new(1,0,1,0)
+ wrapperFrame.Parent = frame
+
+ for i, child in ipairs(guiObjects) do
+ child.Parent = wrapperFrame
+ end
+
+ local recalculate = function()
+ wait()
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(recalculate)
+
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+end
+
+
+t.CreateSlider = function(steps,width,position)
+ local sliderGui = Instance.new("Frame")
+ sliderGui.Size = UDim2.new(1,0,1,0)
+ sliderGui.BackgroundTransparency = 1
+ sliderGui.Name = "SliderGui"
+
+ local sliderSteps = Instance.new("IntValue")
+ sliderSteps.Name = "SliderSteps"
+ sliderSteps.Value = steps
+ sliderSteps.Parent = sliderGui
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = false
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 4
+
+ sliderGui.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(sliderGui)
+ end
+ end)
+
+ local sliderPosition = Instance.new("IntValue")
+ sliderPosition.Name = "SliderPosition"
+ sliderPosition.Value = 0
+ sliderPosition.Parent = sliderGui
+
+ local id = math.random(1,100)
+
+ local bar = Instance.new("TextButton")
+ bar.Text = ""
+ bar.AutoButtonColor = false
+ bar.Name = "Bar"
+ bar.BackgroundColor3 = Color3.new(0,0,0)
+ if type(width) == "number" then
+ bar.Size = UDim2.new(0,width,0,5)
+ else
+ bar.Size = UDim2.new(0,200,0,5)
+ end
+ bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
+ bar.ZIndex = 2
+ bar.Parent = sliderGui
+
+ if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
+ bar.Position = position
+ end
+
+ local slider = Instance.new("ImageButton")
+ slider.Name = "Slider"
+ slider.BackgroundTransparency = 1
+ slider.Image = "rbxasset://textures/ui/Slider.png"
+ slider.Position = UDim2.new(0,0,0.5,-10)
+ slider.Size = UDim2.new(0,20,0,20)
+ slider.ZIndex = 3
+ slider.Parent = bar
+
+ local areaSoakMouseMoveCon = nil
+
+ areaSoak.MouseLeave:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+ areaSoak.MouseButton1Up:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+
+ slider.MouseButton1Down:connect(function()
+ areaSoak.Visible = true
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+ end)
+
+ slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
+
+ sliderPosition.Changed:connect(function(prop)
+ sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
+ local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end)
+
+ bar.MouseButton1Down:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+
+ return sliderGui, sliderPosition, sliderSteps
+
+end
+
+t.CreateTrueScrollingFrame = function()
+ local lowY = nil
+ local highY = nil
+
+ local dragCon = nil
+ local upCon = nil
+
+ local internalChange = false
+
+ local descendantsChangeConMap = {}
+
+ local scrollingFrame = Instance.new("Frame")
+ scrollingFrame.Name = "ScrollingFrame"
+ scrollingFrame.Active = true
+ scrollingFrame.Size = UDim2.new(1,0,1,0)
+ scrollingFrame.ClipsDescendants = true
+
+ local controlFrame = Instance.new("Frame")
+ controlFrame.Name = "ControlFrame"
+ controlFrame.BackgroundTransparency = 1
+ controlFrame.Size = UDim2.new(0,18,1,0)
+ controlFrame.Position = UDim2.new(1,-20,0,0)
+ controlFrame.Parent = scrollingFrame
+
+ local scrollBottom = Instance.new("BoolValue")
+ scrollBottom.Value = false
+ scrollBottom.Name = "ScrollBottom"
+ scrollBottom.Parent = controlFrame
+
+ local scrollUp = Instance.new("BoolValue")
+ scrollUp.Value = false
+ scrollUp.Name = "scrollUp"
+ scrollUp.Parent = controlFrame
+
+ local scrollUpButton = Instance.new("TextButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.Text = ""
+ scrollUpButton.AutoButtonColor = false
+ scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
+ scrollUpButton.BorderColor3 = Color3.new(1,1,1)
+ scrollUpButton.BackgroundTransparency = 0.5
+ scrollUpButton.Size = UDim2.new(0,18,0,18)
+ scrollUpButton.ZIndex = 2
+ scrollUpButton.Parent = controlFrame
+ for i = 1, 6 do
+ local triFrame = Instance.new("Frame")
+ triFrame.BorderColor3 = Color3.new(1,1,1)
+ triFrame.Name = "tri" .. tostring(i)
+ triFrame.ZIndex = 3
+ triFrame.BackgroundTransparency = 0.5
+ triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
+ triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
+ triFrame.Parent = scrollUpButton
+ end
+ scrollUpButton.MouseEnter:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.1
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollUpButton.MouseLeave:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.5
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+
+ local scrollDownButton = scrollUpButton:clone()
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.Position = UDim2.new(0,0,1,-18)
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
+ end
+ scrollDownButton.MouseEnter:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.1
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollDownButton.MouseLeave:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.5
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+ scrollDownButton.Parent = controlFrame
+
+ local scrollTrack = Instance.new("Frame")
+ scrollTrack.Name = "ScrollTrack"
+ scrollTrack.BackgroundTransparency = 1
+ scrollTrack.Size = UDim2.new(0,18,1,-38)
+ scrollTrack.Position = UDim2.new(0,0,0,19)
+ scrollTrack.Parent = controlFrame
+
+ local scrollbar = Instance.new("TextButton")
+ scrollbar.BackgroundColor3 = Color3.new(0,0,0)
+ scrollbar.BorderColor3 = Color3.new(1,1,1)
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.AutoButtonColor = false
+ scrollbar.Text = ""
+ scrollbar.Active = true
+ scrollbar.Name = "ScrollBar"
+ scrollbar.ZIndex = 2
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
+ scrollbar.Position = UDim2.new(0,0,0,0)
+ scrollbar.Parent = scrollTrack
+
+ local scrollNub = Instance.new("Frame")
+ scrollNub.Name = "ScrollNub"
+ scrollNub.BorderColor3 = Color3.new(1,1,1)
+ scrollNub.Size = UDim2.new(0,10,0,0)
+ scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
+ scrollNub.ZIndex = 2
+ scrollNub.BackgroundTransparency = 0.5
+ scrollNub.Parent = scrollbar
+
+ local newNub = scrollNub:clone()
+ newNub.Position = UDim2.new(0.5,-5,0.5,-2)
+ newNub.Parent = scrollbar
+
+ local lastNub = scrollNub:clone()
+ lastNub.Position = UDim2.new(0.5,-5,0.5,2)
+ lastNub.Parent = scrollbar
+
+ scrollbar.MouseEnter:connect(function()
+ scrollbar.BackgroundTransparency = 0.1
+ scrollNub.BackgroundTransparency = 0.1
+ newNub.BackgroundTransparency = 0.1
+ lastNub.BackgroundTransparency = 0.1
+ end)
+ scrollbar.MouseLeave:connect(function()
+ scrollbar.BackgroundTransparency = 0.5
+ scrollNub.BackgroundTransparency = 0.5
+ newNub.BackgroundTransparency = 0.5
+ lastNub.BackgroundTransparency = 0.5
+ end)
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local function positionScrollBar(x,y,offset)
+ local oldPos = scrollbar.Position
+
+ if y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+
+ if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+ local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
+ if newScaleYPos + relativeSize > 1 then
+ newScaleYPos = 1 - relativeSize
+ scrollBottom.Value = true
+ scrollUp.Value = false
+ elseif newScaleYPos <= 0 then
+ newScaleYPos = 0
+ scrollUp.Value = true
+ scrollBottom.Value = false
+ else
+ scrollUp.Value = false
+ scrollBottom.Value = false
+ end
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
+
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local function drillDownSetHighLow(instance)
+ if not instance or not instance:IsA("GuiObject") then return end
+ if instance == controlFrame then return end
+ if instance:IsDescendantOf(controlFrame) then return end
+ if not instance.Visible then return end
+
+ if lowY and lowY > instance.AbsolutePosition.Y then
+ lowY = instance.AbsolutePosition.Y
+ elseif not lowY then
+ lowY = instance.AbsolutePosition.Y
+ end
+ if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ local children = instance:GetChildren()
+ for i = 1, #children do
+ drillDownSetHighLow(children[i])
+ end
+ end
+
+ local function resetHighLow()
+ local firstChildren = scrollingFrame:GetChildren()
+
+ for i = 1, #firstChildren do
+ drillDownSetHighLow(firstChildren[i])
+ end
+ end
+
+ local function recalculate()
+ internalChange = true
+
+ local percentFrame = 0
+ if scrollbar.Position.Y.Scale > 0 then
+ if scrollbar.Visible then
+ percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
+ else
+ percentFrame = 0
+ end
+ end
+ if percentFrame > 0.99 then percentFrame = 1 end
+
+ local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
+
+ local guiChildren = scrollingFrame:GetChildren()
+ for i = 1, #guiChildren do
+ if guiChildren[i] ~= controlFrame then
+ guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
+ 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
+ end
+ end
+
+ lowY = nil
+ highY = nil
+ resetHighLow()
+ internalChange = false
+ end
+
+ local function setSliderSizeAndPosition()
+ if not highY or not lowY then return end
+
+ local totalYSpan = math.abs(highY - lowY)
+ if totalYSpan == 0 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ return
+ end
+
+ local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
+ if percentShown >= 1 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+ recalculate()
+ else
+ scrollbar.Visible = true
+ scrollDownButton.Visible = true
+ scrollUpButton.Visible = true
+
+ scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
+ end
+
+ local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
+
+ if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ end
+
+ if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ end
+ end
+
+ local buttonScrollAmountPixels = 7
+ local reentrancyGuardScrollUp = false
+ local function doScrollUp()
+ if reentrancyGuardScrollUp then return end
+
+ reentrancyGuardScrollUp = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollUp = false
+ end
+
+ local reentrancyGuardScrollDown = false
+ local function doScrollDown()
+ if reentrancyGuardScrollDown then return end
+
+ reentrancyGuardScrollDown = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollDown = false
+ end
+
+ local function scrollUp(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local function scrollDown(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ scrollbar.MouseButton1Down:connect(function(x,y)
+ if scrollbar.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollbar.AbsolutePosition.y
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ local prevY = y
+ local reentrancyGuardMouseScroll = false
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ if reentrancyGuardMouseScroll then return end
+
+ reentrancyGuardMouseScroll = true
+ if positionScrollBar(x,y,mouseOffset) then
+ recalculate()
+ end
+ reentrancyGuardMouseScroll = false
+
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ local function heightCheck(instance)
+ if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ setSliderSizeAndPosition()
+ end
+
+ local function highLowRecheck()
+ local oldLowY = lowY
+ local oldHighY = highY
+ lowY = nil
+ highY = nil
+ resetHighLow()
+
+ if (lowY ~= oldLowY) or (highY ~= oldHighY) then
+ setSliderSizeAndPosition()
+ end
+ end
+
+ local function descendantChanged(this, prop)
+ if internalChange then return end
+ if not this.Visible then return end
+
+ if prop == "Size" or prop == "Position" then
+ wait()
+ highLowRecheck()
+ end
+ end
+
+ scrollingFrame.DescendantAdded:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+
+ if instance.Visible then
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end
+
+ descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
+ end)
+
+ scrollingFrame.DescendantRemoving:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+ if descendantsChangeConMap[instance] then
+ descendantsChangeConMap[instance]:disconnect()
+ descendantsChangeConMap[instance] = nil
+ end
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end)
+
+ scrollingFrame.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ if not highY or not lowY then return end
+
+ highLowRecheck()
+ setSliderSizeAndPosition()
+ end
+ end)
+
+ return scrollingFrame, controlFrame
+end
+
+t.CreateScrollingFrame = function(orderList,scrollStyle)
+ local frame = Instance.new("Frame")
+ frame.Name = "ScrollingFrame"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(1,0,1,0)
+
+ local scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+
+
+ local scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+
+ local scrollbar = Instance.new("ImageButton")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, 0, 150)
+
+ local scrollStamp = 0
+
+ local scrollDrag = Instance.new("ImageButton")
+ scrollDrag.Image = "rbxasset://ui/scrolldrag.png"
+ scrollDrag.Size = UDim2.new(1, 0, 0, 16)
+ scrollDrag.BackgroundTransparency = 1
+ scrollDrag.Name = "ScrollDrag"
+ scrollDrag.Active = true
+ scrollDrag.Parent = scrollbar
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local style = "simple"
+ if scrollStyle and tostring(scrollStyle) then
+ style = scrollStyle
+ end
+
+ local scrollPosition = 1
+ local rowSize = 0
+ local howManyDisplayed = 0
+
+ local layoutGridScrollBar = function()
+ howManyDisplayed = 0
+ local guiObjects = {}
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ if scrollPosition < 1 then scrollPosition = 1 end
+
+ local totalPixelsY = frame.AbsoluteSize.Y
+ local pixelsRemainingY = frame.AbsoluteSize.Y
+
+ local totalPixelsX = frame.AbsoluteSize.X
+
+ local xCounter = 0
+ local rowSizeCounter = 0
+ local setRowSize = true
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+
+ local currentRowY = 0
+
+ pos = scrollPosition
+ --count up from current scroll position to fill out grid
+ while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ --previous pos was the end of a row
+ if xCounter >= totalPixelsX then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ end
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+ pos = pos + 1
+ end
+ --Count wherever current row left off
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+
+ pos = scrollPosition - 1
+ xCounter = 0
+
+ --objects with varying X,Y dimensions can rarely cause minor errors
+ --rechecking every new scrollPosition is necessary to avoid 100% of errors
+
+ --count backwards from current scrollPosition to see if we can add more rows
+ while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ rowSizeCounter = rowSizeCounter + 1
+ if xCounter >= totalPixelsX then
+ rowSize = rowSizeCounter - 1
+ rowSizeCounter = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ if scrollPosition <= rowSize then
+ scrollPosition = 1
+ break
+ else
+ scrollPosition = scrollPosition - rowSize
+ end
+ currentRowY = 0
+ else
+ break
+ end
+ end
+
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+
+ pos = pos - 1
+ end
+
+ --Do check last time if pos = 0
+ if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
+ scrollPosition = 1
+ end
+
+ xCounter = 0
+ --pos = scrollPosition
+ rowSizeCounter = 0
+ setRowSize = true
+ local lastChildSize = 0
+
+ local xOffset,yOffset = 0
+ if guiObjects[1] then
+ yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
+ xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
+ end
+
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemainingY < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
+ if xCounter + child.AbsoluteSize.X >= totalPixelsX then
+ if setRowSize then
+ rowSize = rowSizeCounter - 1
+ setRowSize = false
+ end
+ xCounter = 0
+ pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
+ end
+ child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
+ xCounter = xCounter + child.AbsoluteSize.X
+ child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
+ if child.Visible then
+ howManyDisplayed = howManyDisplayed + 1
+ end
+ lastChildSize = child.AbsoluteSize
+ end
+ end
+ end
+
+ scrollUpButton.Active = (scrollPosition > 1)
+ if lastChildSize == 0 then
+ scrollDownButton.Active = false
+ else
+ scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
+ end
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+
+ local layoutSimpleScrollBar = function()
+ local guiObjects = {}
+ howManyDisplayed = 0
+
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+ while pixelsBelowScrollbar < totalPixels and pos >= 1 do
+ if pos >= scrollPosition then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ else
+ if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ if scrollPosition <= 1 then
+ scrollPosition = 1
+ break
+ else
+ --local ("Backing up ScrollPosition from -- " ..scrollPosition)
+ scrollPosition = scrollPosition - 1
+ end
+ else
+ break
+ end
+ end
+ pos = pos - 1
+ end
+
+ pos = scrollPosition
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemaining < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ if (pixelsRemaining >= 0) then
+ child.Visible = true
+ howManyDisplayed = howManyDisplayed + 1
+ else
+ child.Visible = false
+ end
+ end
+ end
+ end
+ scrollUpButton.Active = (scrollPosition > 1)
+ scrollDownButton.Active = (pixelsRemaining < 0)
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+ local moveDragger = function()
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ if not scrollDrag.Parent then return end
+
+ local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
+ if dragSizeY < 16 then dragSizeY = 16 end
+ scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
+
+ local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
+ if relativeYPos > 1 then relativeYPos = 1
+ elseif relativeYPos < 0 then relativeYPos = 0 end
+ local absYPos = 0
+
+ if relativeYPos ~= 0 then
+ absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
+ end
+
+ scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
+ end
+
+ local reentrancyGuard = false
+ local recalculate = function()
+ if reentrancyGuard then
+ return
+ end
+ reentrancyGuard = true
+ wait()
+ local success, err = nil
+ if style == "grid" then
+ success, err = pcall(function() layoutGridScrollBar() end)
+ elseif style == "simple" then
+ success, err = pcall(function() layoutSimpleScrollBar() end)
+ end
+ if not success then print(err) end
+ moveDragger()
+ reentrancyGuard = false
+ end
+
+ local doScrollUp = function()
+ scrollPosition = (scrollPosition) - rowSize
+ if scrollPosition < 1 then scrollPosition = 1 end
+ recalculate(nil)
+ end
+
+ local doScrollDown = function()
+ scrollPosition = (scrollPosition) + rowSize
+ recalculate(nil)
+ end
+
+ local scrollUp = function(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local scrollDown = function(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local y = 0
+ scrollDrag.MouseButton1Down:connect(function(x,y)
+ if scrollDrag.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollDrag.AbsolutePosition.y
+ local dragCon
+ local upCon
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ local barAbsPos = scrollbar.AbsolutePosition.y
+ local barAbsSize = scrollbar.AbsoluteSize.y
+
+ local dragAbsSize = scrollDrag.AbsoluteSize.y
+ local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
+ y = y - mouseOffset
+ y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
+ y = y - barAbsPos
+
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ local doublePercent = y/(barAbsSize-dragAbsSize)
+ local rowDiff = rowSize
+ local totalScrollCount = guiObjects - (howManyDisplayed - 1)
+ local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
+ if newScrollPosition < scrollPosition then
+ rowDiff = -rowDiff
+ end
+
+ if newScrollPosition < 1 then
+ newScrollPosition = 1
+ end
+
+ scrollPosition = newScrollPosition
+ recalculate(nil)
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollbar.MouseButton1Down:connect(
+ function(x,y)
+ if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
+ scrollDown(y)
+ elseif y < (scrollDrag.AbsolutePosition.y) then
+ scrollUp(y)
+ end
+ end)
+
+
+ frame.ChildAdded:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.ChildRemoved:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(function() recalculate(nil) end)
+
+ return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
+end
+local function binaryGrow(min, max, fits)
+ if min > max then
+ return min
+ end
+ local biggestLegal = min
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
+ biggestLegal = mid
+
+ --Try growing
+ min = mid + 1
+ else
+ --Doesn't fit, shrink
+ max = mid - 1
+ end
+ end
+ return biggestLegal
+end
+
+
+local function binaryShrink(min, max, fits)
+ if min > max then
+ return min
+ end
+ local smallestLegal = max
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
+ smallestLegal = mid
+
+ --It fits, shrink
+ max = mid - 1
+ else
+ --Doesn't fit, grow
+ min = mid + 1
+ end
+ end
+ return smallestLegal
+end
+
+
+local function getGuiOwner(instance)
+ while instance ~= nil do
+ if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
+ return instance
+ end
+ instance = instance.Parent
+ end
+ return nil
+end
+
+t.AutoTruncateTextObject = function(textLabel)
+ local text = textLabel.Text
+
+ local fullLabel = textLabel:Clone()
+ fullLabel.Name = "Full" .. textLabel.Name
+ fullLabel.BorderSizePixel = 0
+ fullLabel.BackgroundTransparency = 0
+ fullLabel.Text = text
+ fullLabel.TextXAlignment = Enum.TextXAlignment.Center
+ fullLabel.Position = UDim2.new(0,-3,0,0)
+ fullLabel.Size = UDim2.new(0,100,1,0)
+ fullLabel.Visible = false
+ fullLabel.Parent = textLabel
+
+ local shortText = nil
+ local mouseEnterConnection = nil
+ local mouseLeaveConnection= nil
+
+ local checkForResize = function()
+ if getGuiOwner(textLabel) == nil then
+ return
+ end
+ textLabel.Text = text
+ if textLabel.TextFits then
+ --Tear down the rollover if it is active
+ if mouseEnterConnection then
+ mouseEnterConnection:disconnect()
+ mouseEnterConnection = nil
+ end
+ if mouseLeaveConnection then
+ mouseLeaveConnection:disconnect()
+ mouseLeaveConnection = nil
+ end
+ else
+ local len = string.len(text)
+ textLabel.Text = text .. "~"
+
+ --Shrink the text
+ local textSize = binaryGrow(0, len,
+ function(pos)
+ if pos == 0 then
+ textLabel.Text = "~"
+ else
+ textLabel.Text = string.sub(text, 1, pos) .. "~"
+ end
+ return textLabel.TextFits
+ end)
+ shortText = string.sub(text, 1, textSize) .. "~"
+ textLabel.Text = shortText
+
+ --Make sure the fullLabel fits
+ if not fullLabel.TextFits then
+ --Already too small, grow it really bit to start
+ fullLabel.Size = UDim2.new(0, 10000, 1, 0)
+ end
+
+ --Okay, now try to binary shrink it back down
+ local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
+ function(size)
+ fullLabel.Size = UDim2.new(0, size, 1, 0)
+ return fullLabel.TextFits
+ end)
+ fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
+
+ --Now setup the rollover effects, if they are currently off
+ if mouseEnterConnection == nil then
+ mouseEnterConnection = textLabel.MouseEnter:connect(
+ function()
+ fullLabel.ZIndex = textLabel.ZIndex + 1
+ fullLabel.Visible = true
+ --textLabel.Text = ""
+ end)
+ end
+ if mouseLeaveConnection == nil then
+ mouseLeaveConnection = textLabel.MouseLeave:connect(
+ function()
+ fullLabel.Visible = false
+ --textLabel.Text = shortText
+ end)
+ end
+ end
+ end
+ textLabel.AncestryChanged:connect(checkForResize)
+ textLabel.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ checkForResize()
+ end
+ end)
+
+ checkForResize()
+
+ local function changeText(newText)
+ text = newText
+ fullLabel.Text = text
+ checkForResize()
+ end
+
+ return textLabel, changeText
+end
+
+local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
+ if fromPage then
+ fromPage.Visible = false
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = fromPage.Size
+ transitionFrame.Position = fromPage.Position
+ end
+ else
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
+ transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
+ end
+ end
+ transitionFrame.Visible = true
+ currentPageValue.Value = nil
+
+ local newsize, newPosition
+ if toPage then
+ --Make it visible so it resizes
+ toPage.Visible = true
+
+ newSize = toPage.Size
+ newPosition = toPage.Position
+
+ toPage.Visible = false
+ else
+ newSize = UDim2.new(0.0,50,0.0,50)
+ newPosition = UDim2.new(0.5,-25,0.5,-25)
+ end
+ transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
+ function(state)
+ if state == Enum.TweenStatus.Completed then
+ transitionFrame.Visible = false
+ if toPage then
+ toPage.Visible = true
+ currentPageValue.Value = toPage
+ end
+ end
+ end)
+end
+
+t.CreateTutorial = function(name, tutorialKey, createButtons)
+ local frame = Instance.new("Frame")
+ frame.Name = "Tutorial-" .. name
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+
+ local transitionFrame = Instance.new("Frame")
+ transitionFrame.Name = "TransitionFrame"
+ transitionFrame.Style = Enum.FrameStyle.RobloxRound
+ transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ transitionFrame.Visible = false
+ transitionFrame.Parent = frame
+
+ local currentPageValue = Instance.new("ObjectValue")
+ currentPageValue.Name = "CurrentTutorialPage"
+ currentPageValue.Value = nil
+ currentPageValue.Parent = frame
+
+ local boolValue = Instance.new("BoolValue")
+ boolValue.Name = "Buttons"
+ boolValue.Value = createButtons
+ boolValue.Parent = frame
+
+ local pages = Instance.new("Frame")
+ pages.Name = "Pages"
+ pages.BackgroundTransparency = 1
+ pages.Size = UDim2.new(1,0,1,0)
+ pages.Parent = frame
+
+ local function getVisiblePageAndHideOthers()
+ local visiblePage = nil
+ local children = pages:GetChildren()
+ if children then
+ for i,child in ipairs(children) do
+ if child.Visible then
+ if visiblePage then
+ child.Visible = false
+ else
+ visiblePage = child
+ end
+ end
+ end
+ end
+ return visiblePage
+ end
+
+ local showTutorial = function(alwaysShow)
+ if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
+ print("Showing tutorial-",tutorialKey)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ local firstPage = pages:FindFirstChild("TutorialPage1")
+ if firstPage then
+ TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
+ else
+ error("Could not find TutorialPage1")
+ end
+ end
+ end
+
+ local dismissTutorial = function()
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ if currentTutorialPage then
+ TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
+ end
+
+ UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
+ end
+
+ local gotoPage = function(pageNum)
+ local page = pages:FindFirstChild("TutorialPage" .. pageNum)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+ TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
+ end
+
+ return frame, showTutorial, dismissTutorial, gotoPage
+end
+
+local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
+ local frame = Instance.new("Frame")
+ frame.Name = "TutorialPage"
+ frame.Style = Enum.FrameStyle.RobloxRound
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ frame.Visible = false
+
+ local frameHeader = Instance.new("TextLabel")
+ frameHeader.Name = "Header"
+ frameHeader.Text = name
+ frameHeader.BackgroundTransparency = 1
+ frameHeader.FontSize = Enum.FontSize.Size24
+ frameHeader.Font = Enum.Font.ArialBold
+ frameHeader.TextColor3 = Color3.new(1,1,1)
+ frameHeader.TextXAlignment = Enum.TextXAlignment.Center
+ frameHeader.TextWrap = true
+ frameHeader.Size = UDim2.new(1,-55, 0, 22)
+ frameHeader.Position = UDim2.new(0,0,0,0)
+ frameHeader.Parent = frame
+
+ local skipButton = Instance.new("ImageButton")
+ skipButton.Name = "SkipButton"
+ skipButton.AutoButtonColor = false
+ skipButton.BackgroundTransparency = 1
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ skipButton.MouseButton1Click:connect(function()
+ skipTutorial()
+ end)
+ skipButton.MouseEnter:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
+ end)
+ skipButton.MouseLeave:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ end)
+ skipButton.Size = UDim2.new(0, 25, 0, 25)
+ skipButton.Position = UDim2.new(1, -25, 0, 0)
+ skipButton.Parent = frame
+
+
+ if giveDoneButton then
+ local doneButton = Instance.new("TextButton")
+ doneButton.Name = "DoneButton"
+ doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ doneButton.Text = "Done"
+ doneButton.TextColor3 = Color3.new(1,1,1)
+ doneButton.Font = Enum.Font.ArialBold
+ doneButton.FontSize = Enum.FontSize.Size18
+ doneButton.Size = UDim2.new(0,100,0,50)
+ doneButton.Position = UDim2.new(0.5,-50,1,-50)
+
+ if skipTutorial then
+ doneButton.MouseButton1Click:connect(function() skipTutorial() end)
+ end
+
+ doneButton.Parent = frame
+ end
+
+ local innerFrame = Instance.new("Frame")
+ innerFrame.Name = "ContentFrame"
+ innerFrame.BackgroundTransparency = 1
+ innerFrame.Position = UDim2.new(0,0,0,25)
+ innerFrame.Parent = frame
+
+ local nextButton = Instance.new("TextButton")
+ nextButton.Name = "NextButton"
+ nextButton.Text = "Next"
+ nextButton.TextColor3 = Color3.new(1,1,1)
+ nextButton.Font = Enum.Font.Arial
+ nextButton.FontSize = Enum.FontSize.Size18
+ nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ nextButton.Size = UDim2.new(0,80, 0, 32)
+ nextButton.Position = UDim2.new(0.5, 5, 1, -32)
+ nextButton.Active = false
+ nextButton.Visible = false
+ nextButton.Parent = frame
+
+ local prevButton = Instance.new("TextButton")
+ prevButton.Name = "PrevButton"
+ prevButton.Text = "Previous"
+ prevButton.TextColor3 = Color3.new(1,1,1)
+ prevButton.Font = Enum.Font.Arial
+ prevButton.FontSize = Enum.FontSize.Size18
+ prevButton.Style = Enum.ButtonStyle.RobloxButton
+ prevButton.Size = UDim2.new(0,80, 0, 32)
+ prevButton.Position = UDim2.new(0.5, -85, 1, -32)
+ prevButton.Active = false
+ prevButton.Visible = false
+ prevButton.Parent = frame
+
+ if giveDoneButton then
+ innerFrame.Size = UDim2.new(1,0,1,-75)
+ else
+ innerFrame.Size = UDim2.new(1,0,1,-22)
+ end
+
+ local parentConnection = nil
+
+ local function basicHandleResize()
+ if frame.Visible and frame.Parent then
+ local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
+ handleResize(200,maxSize)
+ end
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "Parent" then
+ if parentConnection ~= nil then
+ parentConnection:disconnect()
+ parentConnection = nil
+ end
+ if frame.Parent and frame.Parent:IsA("GuiObject") then
+ parentConnection = frame.Parent.Changed:connect(
+ function(parentProp)
+ if parentProp == "AbsoluteSize" then
+ wait()
+ basicHandleResize()
+ end
+ end)
+ basicHandleResize()
+ end
+ end
+
+ if prop == "Visible" then
+ basicHandleResize()
+ end
+ end)
+
+ return frame, innerFrame
+end
+
+t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
+ local frame = nil
+ local contentFrame = nil
+
+ local textLabel = Instance.new("TextLabel")
+ textLabel.BackgroundTransparency = 1
+ textLabel.TextColor3 = Color3.new(1,1,1)
+ textLabel.Text = text
+ textLabel.TextWrap = true
+ textLabel.TextXAlignment = Enum.TextXAlignment.Left
+ textLabel.TextYAlignment = Enum.TextYAlignment.Center
+ textLabel.Font = Enum.Font.Arial
+ textLabel.FontSize = Enum.FontSize.Size14
+ textLabel.Size = UDim2.new(1,0,1,0)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ frame.Size = UDim2.new(0, size, 0, size)
+ return textLabel.TextFits
+ end)
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
+ textLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
+ local frame = nil
+ local contentFrame = nil
+
+ local imageLabel = Instance.new("ImageLabel")
+ imageLabel.BackgroundTransparency = 1
+ imageLabel.Image = imageAsset
+ imageLabel.Size = UDim2.new(0,x,0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ return size >= x and size >= y
+ end)
+ if size >= x and size >= y then
+ imageLabel.Size = UDim2.new(0,x, 0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
+ else
+ if x > y then
+ --X is limiter, so
+ imageLabel.Size = UDim2.new(1,0,y/x,0)
+ imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
+ else
+ --Y is limiter
+ imageLabel.Size = UDim2.new(x/y,0,1, 0)
+ imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
+ end
+ end
+ size = size + 50
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
+ imageLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.AddTutorialPage = function(tutorial, tutorialPage)
+ local transitionFrame = tutorial.TransitionFrame
+ local currentPageValue = tutorial.CurrentTutorialPage
+
+ if not tutorial.Buttons.Value then
+ tutorialPage.NextButton.Parent = nil
+ tutorialPage.PrevButton.Parent = nil
+ end
+
+ local children = tutorial.Pages:GetChildren()
+ if children and #children > 0 then
+ tutorialPage.Name = "TutorialPage" .. (#children+1)
+ local previousPage = children[#children]
+ if not previousPage:IsA("GuiObject") then
+ error("All elements under Pages must be GuiObjects")
+ end
+
+ if tutorial.Buttons.Value then
+ if previousPage.NextButton.Active then
+ error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
+ end
+ previousPage.NextButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
+ end)
+ previousPage.NextButton.Active = true
+ previousPage.NextButton.Visible = true
+
+ if tutorialPage.PrevButton.Active then
+ error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
+ end
+ tutorialPage.PrevButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
+ end)
+ tutorialPage.PrevButton.Active = true
+ tutorialPage.PrevButton.Visible = true
+ end
+
+ tutorialPage.Parent = tutorial.Pages
+ else
+ --First child
+ tutorialPage.Name = "TutorialPage1"
+ tutorialPage.Parent = tutorial.Pages
+ end
+end
+
+t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
+
+ if not userIdsForSets then
+ error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
+ end
+ if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
+ error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
+ end
+ if not objectSelected then
+ error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
+ end
+ if type(objectSelected) ~= "function" then
+ error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
+ end
+ if dialogClosed and type(dialogClosed) ~= "function" then
+ error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
+ end
+
+ if showAdminCategories == nil then -- by default, don't show beta sets
+ showAdminCategories = false
+ end
+
+ local arrayPosition = 1
+ local insertButtons = {}
+ local insertButtonCons = {}
+ local contents = nil
+ local setGui = nil
+
+ -- used for water selections
+ local waterForceDirection = "NegX"
+ local waterForce = "None"
+ local waterGui, waterTypeChangedEvent = nil
+
+ local Data = {}
+ Data.CurrentCategory = nil
+ Data.Category = {}
+ local SetCache = {}
+
+ local userCategoryButtons = nil
+
+ local buttonWidth = 64
+ local buttonHeight = buttonWidth
+
+ local SmallThumbnailUrl = nil
+ local LargeThumbnailUrl = nil
+ local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
+
+ if useAssetVersionId then
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
+ else
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
+ end
+
+ local function drillDownSetZIndex(parent, index)
+ local children = parent:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("GuiObject") then
+ children[i].ZIndex = index
+ end
+ drillDownSetZIndex(children[i], index)
+ end
+ end
+
+ -- for terrain stamping
+ local currTerrainDropDownFrame = nil
+ local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
+ local terrainShapeMap = {}
+ for i = 1, #terrainShapes do
+ terrainShapeMap[terrainShapes[i]] = i - 1
+ end
+ terrainShapeMap[terrainShapes[#terrainShapes]] = 6
+
+ local function createWaterGui()
+ local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
+ local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
+
+ local waterFrame = Instance.new("Frame")
+ waterFrame.Name = "WaterFrame"
+ waterFrame.Style = Enum.FrameStyle.RobloxSquare
+ waterFrame.Size = UDim2.new(0,150,0,110)
+ waterFrame.Visible = false
+
+ local waterForceLabel = Instance.new("TextLabel")
+ waterForceLabel.Name = "WaterForceLabel"
+ waterForceLabel.BackgroundTransparency = 1
+ waterForceLabel.Size = UDim2.new(1,0,0,12)
+ waterForceLabel.Font = Enum.Font.ArialBold
+ waterForceLabel.FontSize = Enum.FontSize.Size12
+ waterForceLabel.TextColor3 = Color3.new(1,1,1)
+ waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
+ waterForceLabel.Text = "Water Force"
+ waterForceLabel.Parent = waterFrame
+
+ local waterForceDirLabel = waterForceLabel:Clone()
+ waterForceDirLabel.Name = "WaterForceDirectionLabel"
+ waterForceDirLabel.Text = "Water Force Direction"
+ waterForceDirLabel.Position = UDim2.new(0,0,0,50)
+ waterForceDirLabel.Parent = waterFrame
+
+ local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
+ waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
+
+ local waterForceDirectionSelectedFunc = function(newForceDirection)
+ waterForceDirection = newForceDirection
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+ local waterForceSelectedFunc = function(newForce)
+ waterForce = newForce
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+
+ local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
+ waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
+ forceWaterDirectionSelection("NegX")
+ waterForceDirectionDropDown.Parent = waterForceDirLabel
+
+ local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
+ forceWaterForceSelection("None")
+ waterForceDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDropDown.Position = UDim2.new(0,0,1,3)
+ waterForceDropDown.Parent = waterForceLabel
+
+ return waterFrame, waterTypeChangedEvent
+ end
+
+ -- Helper Function that contructs gui elements
+ local function createSetGui()
+
+ local setGui = Instance.new("ScreenGui")
+ setGui.Name = "SetGui"
+
+ local setPanel = Instance.new("Frame")
+ setPanel.Name = "SetPanel"
+ setPanel.Active = true
+ setPanel.BackgroundTransparency = 1
+ if position then
+ setPanel.Position = position
+ else
+ setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
+ end
+ if size then
+ setPanel.Size = size
+ else
+ setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
+ end
+ setPanel.Style = Enum.FrameStyle.RobloxRound
+ setPanel.ZIndex = 6
+ setPanel.Parent = setGui
+
+ -- Children of SetPanel
+ local itemPreview = Instance.new("Frame")
+ itemPreview.Name = "ItemPreview"
+ itemPreview.BackgroundTransparency = 1
+ itemPreview.Position = UDim2.new(0.8,5,0.085,0)
+ itemPreview.Size = UDim2.new(0.21,0,0.9,0)
+ itemPreview.ZIndex = 6
+ itemPreview.Parent = setPanel
+
+ -- Children of ItemPreview
+ local textPanel = Instance.new("Frame")
+ textPanel.Name = "TextPanel"
+ textPanel.BackgroundTransparency = 1
+ textPanel.Position = UDim2.new(0,0,0.45,0)
+ textPanel.Size = UDim2.new(1,0,0.55,0)
+ textPanel.ZIndex = 6
+ textPanel.Parent = itemPreview
+
+ -- Children of TextPanel
+ local rolloverText = Instance.new("TextLabel")
+ rolloverText.Name = "RolloverText"
+ rolloverText.BackgroundTransparency = 1
+ rolloverText.Size = UDim2.new(1,0,0,48)
+ rolloverText.ZIndex = 6
+ rolloverText.Font = Enum.Font.ArialBold
+ rolloverText.FontSize = Enum.FontSize.Size24
+ rolloverText.Text = ""
+ rolloverText.TextColor3 = Color3.new(1,1,1)
+ rolloverText.TextWrap = true
+ rolloverText.TextXAlignment = Enum.TextXAlignment.Left
+ rolloverText.TextYAlignment = Enum.TextYAlignment.Top
+ rolloverText.Parent = textPanel
+
+ local largePreview = Instance.new("ImageLabel")
+ largePreview.Name = "LargePreview"
+ largePreview.BackgroundTransparency = 1
+ largePreview.Image = ""
+ largePreview.Size = UDim2.new(1,0,0,170)
+ largePreview.ZIndex = 6
+ largePreview.Parent = itemPreview
+
+ local sets = Instance.new("Frame")
+ sets.Name = "Sets"
+ sets.BackgroundTransparency = 1
+ sets.Position = UDim2.new(0,0,0,5)
+ sets.Size = UDim2.new(0.23,0,1,-5)
+ sets.ZIndex = 6
+ sets.Parent = setPanel
+
+ -- Children of Sets
+ local line = Instance.new("Frame")
+ line.Name = "Line"
+ line.BackgroundColor3 = Color3.new(1,1,1)
+ line.BackgroundTransparency = 0.7
+ line.BorderSizePixel = 0
+ line.Position = UDim2.new(1,-3,0.06,0)
+ line.Size = UDim2.new(0,3,0.9,0)
+ line.ZIndex = 6
+ line.Parent = sets
+
+ local setsLists, controlFrame = t.CreateTrueScrollingFrame()
+ setsLists.Size = UDim2.new(1,-6,0.94,0)
+ setsLists.Position = UDim2.new(0,0,0.06,0)
+ setsLists.BackgroundTransparency = 1
+ setsLists.Name = "SetsLists"
+ setsLists.ZIndex = 6
+ setsLists.Parent = sets
+ drillDownSetZIndex(controlFrame, 7)
+
+ local setsHeader = Instance.new("TextLabel")
+ setsHeader.Name = "SetsHeader"
+ setsHeader.BackgroundTransparency = 1
+ setsHeader.Size = UDim2.new(0,47,0,24)
+ setsHeader.ZIndex = 6
+ setsHeader.Font = Enum.Font.ArialBold
+ setsHeader.FontSize = Enum.FontSize.Size24
+ setsHeader.Text = "Sets"
+ setsHeader.TextColor3 = Color3.new(1,1,1)
+ setsHeader.TextXAlignment = Enum.TextXAlignment.Left
+ setsHeader.TextYAlignment = Enum.TextYAlignment.Top
+ setsHeader.Parent = sets
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(1,-32,0,-2)
+ cancelButton.Size = UDim2.new(0,34,0,34)
+ cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ cancelButton.ZIndex = 6
+ cancelButton.Text = ""
+ cancelButton.Modal = true
+ cancelButton.Parent = setPanel
+
+ -- Children of Cancel Button
+ local cancelImage = Instance.new("ImageLabel")
+ cancelImage.Name = "CancelImage"
+ cancelImage.BackgroundTransparency = 1
+ cancelImage.Image = "rbxasset://ui/cancel.png"
+ cancelImage.Position = UDim2.new(0,-2,0,-2)
+ cancelImage.Size = UDim2.new(0,16,0,16)
+ cancelImage.ZIndex = 6
+ cancelImage.Parent = cancelButton
+
+ return setGui
+ end
+
+ local function createSetButton(text)
+ local setButton = Instance.new("TextButton")
+
+ if text then setButton.Text = text
+ else setButton.Text = "" end
+
+ setButton.AutoButtonColor = false
+ setButton.BackgroundTransparency = 1
+ setButton.BackgroundColor3 = Color3.new(1,1,1)
+ setButton.BorderSizePixel = 0
+ setButton.Size = UDim2.new(1,-5,0,18)
+ setButton.ZIndex = 6
+ setButton.Visible = false
+ setButton.Font = Enum.Font.Arial
+ setButton.FontSize = Enum.FontSize.Size18
+ setButton.TextColor3 = Color3.new(1,1,1)
+ setButton.TextXAlignment = Enum.TextXAlignment.Left
+
+ return setButton
+ end
+
+ local function buildSetButton(name, setId, setImageId, i, count)
+ local button = createSetButton(name)
+ button.Text = name
+ button.Name = "SetButton"
+ button.Visible = true
+
+ local setValue = Instance.new("IntValue")
+ setValue.Name = "SetId"
+ setValue.Value = setId
+ setValue.Parent = button
+
+ local setName = Instance.new("StringValue")
+ setName.Name = "SetName"
+ setName.Value = name
+ setName.Parent = button
+
+ return button
+ end
+
+ local function processCategory(sets)
+ local setButtons = {}
+ local numSkipped = 0
+ for i = 1, #sets do
+ if not showAdminCategories and sets[i].Name == "Beta" then
+ numSkipped = numSkipped + 1
+ else
+ setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
+ end
+ end
+ return setButtons
+ end
+
+ local function handleResize()
+ wait() -- neccessary to insure heartbeat happened
+
+ local itemPreview = setGui.SetPanel.ItemPreview
+
+ itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
+ itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
+ itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
+ itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
+ end
+
+ local function makeInsertAssetButton()
+ local insertAssetButtonExample = Instance.new("Frame")
+ insertAssetButtonExample.Name = "InsertAssetButtonExample"
+ insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
+ insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
+ insertAssetButtonExample.BackgroundTransparency = 1
+ insertAssetButtonExample.ZIndex = 6
+ insertAssetButtonExample.Visible = false
+
+ local assetId = Instance.new("IntValue")
+ assetId.Name = "AssetId"
+ assetId.Value = 0
+ assetId.Parent = insertAssetButtonExample
+
+ local assetName = Instance.new("StringValue")
+ assetName.Name = "AssetName"
+ assetName.Value = ""
+ assetName.Parent = insertAssetButtonExample
+
+ local button = Instance.new("TextButton")
+ button.Name = "Button"
+ button.Text = ""
+ button.Style = Enum.ButtonStyle.RobloxButton
+ button.Position = UDim2.new(0.025,0,0.025,0)
+ button.Size = UDim2.new(0.95,0,0.95,0)
+ button.ZIndex = 6
+ button.Parent = insertAssetButtonExample
+
+ local buttonImage = Instance.new("ImageLabel")
+ buttonImage.Name = "ButtonImage"
+ buttonImage.Image = ""
+ buttonImage.Position = UDim2.new(0,-7,0,-7)
+ buttonImage.Size = UDim2.new(1,14,1,14)
+ buttonImage.BackgroundTransparency = 1
+ buttonImage.ZIndex = 7
+ buttonImage.Parent = button
+
+ local configIcon = buttonImage:clone()
+ configIcon.Name = "ConfigIcon"
+ configIcon.Visible = false
+ configIcon.Position = UDim2.new(1,-23,1,-24)
+ configIcon.Size = UDim2.new(0,16,0,16)
+ configIcon.Image = ""
+ configIcon.ZIndex = 6
+ configIcon.Parent = insertAssetButtonExample
+
+ return insertAssetButtonExample
+ end
+
+ local function showLargePreview(insertButton)
+ if insertButton:FindFirstChild("AssetId") then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
+ setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
+ end)
+ end
+ if insertButton:FindFirstChild("AssetName") then
+ setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
+ end
+ end
+
+ local function selectTerrainShape(shape)
+ if currTerrainDropDownFrame then
+ objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
+ end
+ end
+
+ local function createTerrainTypeButton(name, parent)
+ local dropDownTextButton = Instance.new("TextButton")
+ dropDownTextButton.Name = name .. "Button"
+ dropDownTextButton.Font = Enum.Font.ArialBold
+ dropDownTextButton.FontSize = Enum.FontSize.Size14
+ dropDownTextButton.BorderSizePixel = 0
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ dropDownTextButton.Text = name
+ dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.ZIndex = parent.ZIndex + 1
+ dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
+ dropDownTextButton.Position = UDim2.new(0,1,0,0)
+
+ dropDownTextButton.MouseEnter:connect(function()
+ dropDownTextButton.BackgroundTransparency = 0
+ dropDownTextButton.TextColor3 = Color3.new(0,0,0)
+ end)
+
+ dropDownTextButton.MouseLeave:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ end)
+
+ dropDownTextButton.MouseButton1Click:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
+ dropDownTextButton.Parent.Visible = false
+ end
+ selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
+ end)
+
+ return dropDownTextButton
+ end
+
+ local function createTerrainDropDownMenu(zIndex)
+ local dropDown = Instance.new("Frame")
+ dropDown.Name = "TerrainDropDown"
+ dropDown.BackgroundColor3 = Color3.new(0,0,0)
+ dropDown.BorderColor3 = Color3.new(1,0,0)
+ dropDown.Size = UDim2.new(0,200,0,0)
+ dropDown.Visible = false
+ dropDown.ZIndex = zIndex
+ dropDown.Parent = setGui
+
+ for i = 1, #terrainShapes do
+ local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
+ shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
+ shapeButton.Parent = dropDown
+ dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
+ end
+
+ dropDown.MouseLeave:connect(function()
+ dropDown.Visible = false
+ end)
+ end
+
+
+ local function createDropDownMenuButton(parent)
+ local dropDownButton = Instance.new("ImageButton")
+ dropDownButton.Name = "DropDownButton"
+ dropDownButton.Image = "rbxasset://ui/dropdownbutton.png"
+ dropDownButton.BackgroundTransparency = 1
+ dropDownButton.Size = UDim2.new(0,16,0,16)
+ dropDownButton.Position = UDim2.new(1,-24,0,6)
+ dropDownButton.ZIndex = parent.ZIndex + 2
+ dropDownButton.Parent = parent
+
+ if not setGui:FindFirstChild("TerrainDropDown") then
+ createTerrainDropDownMenu(8)
+ end
+
+ dropDownButton.MouseButton1Click:connect(function()
+ setGui.TerrainDropDown.Visible = true
+ setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
+ currTerrainDropDownFrame = parent
+ end)
+ end
+
+ local function buildInsertButton()
+ local insertButton = makeInsertAssetButton()
+ insertButton.Name = "InsertAssetButton"
+ insertButton.Visible = true
+
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ createDropDownMenuButton(insertButton)
+ end
+
+ local lastEnter = nil
+ local mouseEnterCon = insertButton.MouseEnter:connect(function()
+ lastEnter = insertButton
+ delay(0.1,function()
+ if lastEnter == insertButton then
+ showLargePreview(insertButton)
+ end
+ end)
+ end)
+ return insertButton, mouseEnterCon
+ end
+
+ local function realignButtonGrid(columns)
+ local x = 0
+ local y = 0
+ for i = 1, #insertButtons do
+ insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
+ x = x + 1
+ if x >= columns then
+ x = 0
+ y = y + 1
+ end
+ end
+ end
+
+ local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
+ if visible then
+ insertFrame.AssetName.Value = name
+ insertFrame.AssetId.Value = assetId
+ local newImageUrl = SmallThumbnailUrl .. assetId
+ if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
+ insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
+ end)
+ end
+ table.insert(insertButtonCons,
+ insertFrame.Button.MouseButton1Click:connect(function()
+ -- special case for water, show water selection gui
+ local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
+ waterGui.Visible = isWaterSelected
+ if isWaterSelected then
+ objectSelected(name, tonumber(assetId), nil)
+ else
+ objectSelected(name, tonumber(assetId))
+ end
+ end)
+ )
+ insertFrame.Visible = true
+ else
+ insertFrame.Visible = false
+ end
+ end
+
+ local function loadSectionOfItems(setGui, rows, columns)
+ local pageSize = rows * columns
+
+ if arrayPosition > #contents then return end
+
+ local origArrayPos = arrayPosition
+
+ local yCopy = 0
+ for i = 1, pageSize + 1 do
+ if arrayPosition >= #contents + 1 then
+ break
+ end
+
+ local buttonCon
+ insertButtons[arrayPosition], buttonCon = buildInsertButton()
+ table.insert(insertButtonCons,buttonCon)
+ insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
+ arrayPosition = arrayPosition + 1
+ end
+ realignButtonGrid(columns)
+
+ local indexCopy = origArrayPos
+ for index = origArrayPos, arrayPosition do
+ if insertButtons[index] then
+ if contents[index] then
+
+ -- we don't want water to have a drop down button
+ if contents[index].Name == "Water" then
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
+ end
+ end
+
+ local assetId
+ if useAssetVersionId then
+ assetId = contents[index].AssetVersionId
+ else
+ assetId = contents[index].AssetId
+ end
+ setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
+ else
+ break
+ end
+ else
+ break
+ end
+ indexCopy = index
+ end
+ end
+
+ local function setSetIndex()
+ Data.Category[Data.CurrentCategory].Index = 0
+
+ rows = 7
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ contents = Data.Category[Data.CurrentCategory].Contents
+ if contents then
+ -- remove our buttons and their connections
+ for i = 1, #insertButtons do
+ insertButtons[i]:remove()
+ end
+ for i = 1, #insertButtonCons do
+ if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
+ end
+ insertButtonCons = {}
+ insertButtons = {}
+
+ arrayPosition = 1
+ loadSectionOfItems(setGui, rows, columns)
+ end
+ end
+
+ local function selectSet(button, setName, setId, setIndex)
+ if button and Data.Category[Data.CurrentCategory] ~= nil then
+ if button ~= Data.Category[Data.CurrentCategory].Button then
+ Data.Category[Data.CurrentCategory].Button = button
+
+ if SetCache[setId] == nil then
+ SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
+ end
+ Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
+
+ Data.Category[Data.CurrentCategory].SetName = setName
+ Data.Category[Data.CurrentCategory].SetId = setId
+ end
+ setSetIndex()
+ end
+ end
+
+ local function selectCategoryPage(buttons, page)
+ if buttons ~= Data.CurrentCategory then
+ if Data.CurrentCategory then
+ for key, button in pairs(Data.CurrentCategory) do
+ button.Visible = false
+ end
+ end
+
+ Data.CurrentCategory = buttons
+ if Data.Category[Data.CurrentCategory] == nil then
+ Data.Category[Data.CurrentCategory] = {}
+ if #buttons > 0 then
+ selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
+ end
+ else
+ Data.Category[Data.CurrentCategory].Button = nil
+ selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
+ end
+ end
+ end
+
+ local function selectCategory(category)
+ selectCategoryPage(category, 0)
+ end
+
+ local function resetAllSetButtonSelection()
+ local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+ for i = 1, #setButtons do
+ if setButtons[i]:IsA("TextButton") then
+ setButtons[i].Selected = false
+ setButtons[i].BackgroundTransparency = 1
+ setButtons[i].TextColor3 = Color3.new(1,1,1)
+ setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
+ end
+ end
+ end
+
+ local function populateSetsFrame()
+ local currRow = 0
+ for i = 1, #userCategoryButtons do
+ local button = userCategoryButtons[i]
+ button.Visible = true
+ button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
+ button.Parent = setGui.SetPanel.Sets.SetsLists
+
+ if i == 1 then -- we will have this selected by default, so show it
+ button.Selected = true
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ end
+
+ button.MouseEnter:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 0
+ button.TextColor3 = Color3.new(0,0,0)
+ end
+ end)
+ button.MouseLeave:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 1
+ button.TextColor3 = Color3.new(1,1,1)
+ end
+ end)
+ button.MouseButton1Click:connect(function()
+ resetAllSetButtonSelection()
+ button.Selected = not button.Selected
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
+ end)
+
+ currRow = currRow + 1
+ end
+
+ local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+
+ -- set first category as loaded for default
+ if buttons then
+ for i = 1, #buttons do
+ if buttons[i]:IsA("TextButton") then
+ selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
+ selectCategory(userCategoryButtons)
+ break
+ end
+ end
+ end
+ end
+
+ setGui = createSetGui()
+ waterGui, waterTypeChangedEvent = createWaterGui()
+ waterGui.Position = UDim2.new(0,55,0,0)
+ waterGui.Parent = setGui
+ setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
+ if prop == "AbsoluteSize" then
+ handleResize()
+ setSetIndex()
+ end
+ end)
+
+ local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
+ scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
+ scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
+ scrollFrame.Name = "ItemsFrame"
+ scrollFrame.ZIndex = 6
+ scrollFrame.Parent = setGui.SetPanel
+ scrollFrame.BackgroundTransparency = 1
+
+ drillDownSetZIndex(controlFrame,7)
+
+ controlFrame.Parent = setGui.SetPanel
+ controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
+
+ local debounce = false
+ controlFrame.ScrollBottom.Changed:connect(function(prop)
+ if controlFrame.ScrollBottom.Value == true then
+ if debounce then return end
+ debounce = true
+ loadSectionOfItems(setGui, rows, columns)
+ debounce = false
+ end
+ end)
+
+ local userData = {}
+ for id = 1, #userIdsForSets do
+ local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
+ if newUserData and #newUserData > 2 then
+ -- start at #3 to skip over My Decals and My Models for each account
+ for category = 3, #newUserData do
+ if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
+ table.insert(userData,1,newUserData[category])
+ else
+ table.insert(userData, newUserData[category])
+ end
+ end
+ end
+
+ end
+ if userData then
+ userCategoryButtons = processCategory(userData)
+ end
+
+ rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ populateSetsFrame()
+
+ insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
+ setGui.SetPanel.Visible = false
+ if dialogClosed then dialogClosed() end
+ end)
+
+ local setVisibilityFunction = function(visible)
+ if visible then
+ setGui.SetPanel.Visible = true
+ else
+ setGui.SetPanel.Visible = false
+ end
+ end
+
+ local getVisibilityFunction = function()
+ if setGui then
+ if setGui:FindFirstChild("SetPanel") then
+ return setGui.SetPanel.Visible
+ end
+ end
+
+ return false
+ end
+
+ return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
+end
+
+t.CreateTerrainMaterialSelector = function(size,position)
+ local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
+ terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
+
+ local selectedButton = nil
+
+ local frame = Instance.new("Frame")
+ frame.Name = "TerrainMaterialSelector"
+ if size then
+ frame.Size = size
+ else
+ frame.Size = UDim2.new(0, 245, 0, 230)
+ end
+ if position then
+ frame.Position = position
+ end
+ frame.BorderSizePixel = 0
+ frame.BackgroundColor3 = Color3.new(0,0,0)
+ frame.Active = true
+
+ terrainMaterialSelectionChanged.Parent = frame
+
+ local waterEnabled = true -- todo: turn this on when water is ready
+
+ local materialToImageMap = {}
+ local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
+ if waterEnabled then
+ table.insert(materialNames,"Water")
+ end
+ local currentMaterial = 1
+
+ function getEnumFromName(choice)
+ if choice == "Grass" then return 1 end
+ if choice == "Sand" then return 2 end
+ if choice == "Erase" then return 0 end
+ if choice == "Brick" then return 3 end
+ if choice == "Granite" then return 4 end
+ if choice == "Asphalt" then return 5 end
+ if choice == "Iron" then return 6 end
+ if choice == "Aluminum" then return 7 end
+ if choice == "Gold" then return 8 end
+ if choice == "Plank" then return 9 end
+ if choice == "Log" then return 10 end
+ if choice == "Gravel" then return 11 end
+ if choice == "Cinder Block" then return 12 end
+ if choice == "Stone Wall" then return 13 end
+ if choice == "Concrete" then return 14 end
+ if choice == "Plastic (red)" then return 15 end
+ if choice == "Plastic (blue)" then return 16 end
+ if choice == "Water" then return 17 end
+ end
+
+ function getNameFromEnum(choice)
+ if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
+ if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
+ if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
+ if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
+ if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
+ if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
+ if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
+ if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
+ if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
+ if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
+ if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
+ if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
+ if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
+ if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
+ if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
+ if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
+ if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
+
+ if waterEnabled then
+ if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
+ end
+ end
+
+
+ local function updateMaterialChoice(choice)
+ currentMaterial = getEnumFromName(choice)
+ terrainMaterialSelectionChanged:Fire(currentMaterial)
+ end
+
+ -- we so need a better way to do this
+ for i,v in pairs(materialNames) do
+ materialToImageMap[v] = {}
+ if v == "Grass" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Grass.png"
+ elseif v == "Sand" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Sand.png"
+ elseif v == "Brick" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Brick.png"
+ elseif v == "Granite" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Granite.png"
+ elseif v == "Asphalt" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Asphalt.png"
+ elseif v == "Iron" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Iron.png"
+ elseif v == "Aluminum" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Aluminum.png"
+ elseif v == "Gold" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Gold.png"
+ elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/PlasticRed.png"
+ elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/PlasticBlue.png"
+ elseif v == "Plank" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Plank.png"
+ elseif v == "Log" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Log.png"
+ elseif v == "Gravel" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Gravel.png"
+ elseif v == "Cinder Block" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/CinderBlock.png"
+ elseif v == "Stone Wall" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/StoneWall.png"
+ elseif v == "Concrete" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Concrete.png"
+ elseif v == "Water" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Water.png"
+ else materialToImageMap[v].Regular = "rbxasset://textures/terrain/unknown.png" -- fill in the rest here!!
+ end
+ end
+
+ local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
+ scrollFrame.Size = UDim2.new(0.85,0,1,0)
+ scrollFrame.Position = UDim2.new(0,0,0,0)
+ scrollFrame.Parent = frame
+
+ scrollUp.Parent = frame
+ scrollUp.Visible = true
+ scrollUp.Position = UDim2.new(1,-19,0,0)
+
+ scrollDown.Parent = frame
+ scrollDown.Visible = true
+ scrollDown.Position = UDim2.new(1,-19,1,-17)
+
+ local function goToNewMaterial(buttonWrap, materialName)
+ updateMaterialChoice(materialName)
+ buttonWrap.BackgroundTransparency = 0
+ selectedButton.BackgroundTransparency = 1
+ selectedButton = buttonWrap
+ end
+
+ local function createMaterialButton(name)
+ local buttonWrap = Instance.new("TextButton")
+ buttonWrap.Text = ""
+ buttonWrap.Size = UDim2.new(0,32,0,32)
+ buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
+ buttonWrap.BorderSizePixel = 0
+ buttonWrap.BackgroundTransparency = 1
+ buttonWrap.AutoButtonColor = false
+ buttonWrap.Name = tostring(name)
+
+ local imageButton = Instance.new("ImageButton")
+ imageButton.AutoButtonColor = false
+ imageButton.BackgroundTransparency = 1
+ imageButton.Size = UDim2.new(0,30,0,30)
+ imageButton.Position = UDim2.new(0,1,0,1)
+ imageButton.Name = tostring(name)
+ imageButton.Parent = buttonWrap
+ imageButton.Image = materialToImageMap[name].Regular
+
+ local enumType = Instance.new("NumberValue")
+ enumType.Name = "EnumType"
+ enumType.Parent = buttonWrap
+ enumType.Value = 0
+
+ imageButton.MouseEnter:connect(function()
+ buttonWrap.BackgroundTransparency = 0
+ end)
+ imageButton.MouseLeave:connect(function()
+ if selectedButton ~= buttonWrap then
+ buttonWrap.BackgroundTransparency = 1
+ end
+ end)
+ imageButton.MouseButton1Click:connect(function()
+ if selectedButton ~= buttonWrap then
+ goToNewMaterial(buttonWrap, tostring(name))
+ end
+ end)
+
+ return buttonWrap
+ end
+
+ for i = 1, #materialNames do
+ local imageButton = createMaterialButton(materialNames[i])
+
+ if materialNames[i] == "Grass" then -- always start with grass as the default
+ selectedButton = imageButton
+ imageButton.BackgroundTransparency = 0
+ end
+
+ imageButton.Parent = scrollFrame
+ end
+
+ local forceTerrainMaterialSelection = function(newMaterialType)
+ if not newMaterialType then return end
+ if currentMaterial == newMaterialType then return end
+
+ local matName = getNameFromEnum(newMaterialType)
+ local buttons = scrollFrame:GetChildren()
+ for i = 1, #buttons do
+ if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
+ if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
+ if string.find(buttons[i].Name, matName) then
+ goToNewMaterial(buttons[i],matName)
+ return
+ end
+ end
+ end
+
+ frame.Changed:connect(function ( prop )
+ if prop == "AbsoluteSize" then
+ recalculateScroll()
+ end
+ end)
+
+ recalculateScroll()
+ return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
+end
+
+t.CreateLoadingFrame = function(name,size,position)
+ game:GetService("ContentProvider"):Preload("rbxasset://ui/loadingbar.png")
+
+ local loadingFrame = Instance.new("Frame")
+ loadingFrame.Name = "LoadingFrame"
+ loadingFrame.Style = Enum.FrameStyle.RobloxRound
+
+ if size then loadingFrame.Size = size
+ else loadingFrame.Size = UDim2.new(0,300,0,160) end
+ if position then loadingFrame.Position = position
+ else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
+
+ local loadingBar = Instance.new("Frame")
+ loadingBar.Name = "LoadingBar"
+ loadingBar.BackgroundColor3 = Color3.new(0,0,0)
+ loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
+ loadingBar.Position = UDim2.new(0,0,0,41)
+ loadingBar.Size = UDim2.new(1,0,0,30)
+ loadingBar.Parent = loadingFrame
+
+ local loadingGreenBar = Instance.new("ImageLabel")
+ loadingGreenBar.Name = "LoadingGreenBar"
+ loadingGreenBar.Image = "rbxasset://ui/loadingbar.png"
+ loadingGreenBar.Position = UDim2.new(0,0,0,0)
+ loadingGreenBar.Size = UDim2.new(0,0,1,0)
+ loadingGreenBar.Visible = false
+ loadingGreenBar.Parent = loadingBar
+
+ local loadingPercent = Instance.new("TextLabel")
+ loadingPercent.Name = "LoadingPercent"
+ loadingPercent.BackgroundTransparency = 1
+ loadingPercent.Position = UDim2.new(0,0,1,0)
+ loadingPercent.Size = UDim2.new(1,0,0,14)
+ loadingPercent.Font = Enum.Font.Arial
+ loadingPercent.Text = "0%"
+ loadingPercent.FontSize = Enum.FontSize.Size14
+ loadingPercent.TextColor3 = Color3.new(1,1,1)
+ loadingPercent.Parent = loadingBar
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(0.5,-60,1,-40)
+ cancelButton.Size = UDim2.new(0,120,0,40)
+ cancelButton.Font = Enum.Font.Arial
+ cancelButton.FontSize = Enum.FontSize.Size18
+ cancelButton.TextColor3 = Color3.new(1,1,1)
+ cancelButton.Text = "Cancel"
+ cancelButton.Style = Enum.ButtonStyle.RobloxButton
+ cancelButton.Parent = loadingFrame
+
+ local loadingName = Instance.new("TextLabel")
+ loadingName.Name = "loadingName"
+ loadingName.BackgroundTransparency = 1
+ loadingName.Size = UDim2.new(1,0,0,18)
+ loadingName.Position = UDim2.new(0,0,0,2)
+ loadingName.Font = Enum.Font.Arial
+ loadingName.Text = name
+ loadingName.TextColor3 = Color3.new(1,1,1)
+ loadingName.TextStrokeTransparency = 1
+ loadingName.FontSize = Enum.FontSize.Size18
+ loadingName.Parent = loadingFrame
+
+ local cancelButtonClicked = Instance.new("BindableEvent")
+ cancelButtonClicked.Name = "CancelButtonClicked"
+ cancelButtonClicked.Parent = cancelButton
+ cancelButton.MouseButton1Click:connect(function()
+ cancelButtonClicked:Fire()
+ end)
+
+ local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
+ if percent and type(percent) ~= "number" then
+ error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
+ end
+
+ local newSize = nil
+ if percent < 0 then
+ newSize = UDim2.new(0,0,1,0)
+ elseif percent > 1 then
+ newSize = UDim2.new(1,0,1,0)
+ else
+ newSize = UDim2.new(percent,0,1,0)
+ end
+
+ if tweenAction then
+ if not tweenLength then
+ error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
+ end
+
+ if (newSize.X.Scale > 0) then
+ loadingGreenBar.Visible = true
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true)
+ else
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true,
+ function()
+ if (newSize.X.Scale < 0) then
+ loadingGreenBar.Visible = false
+ end
+ end)
+ end
+
+ else
+ loadingGreenBar.Size = newSize
+ loadingGreenBar.Visible = (newSize.X.Scale > 0)
+ end
+ end
+
+ loadingGreenBar.Changed:connect(function(prop)
+ if prop == "Size" then
+ loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
+ end
+ end)
+
+ return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
+end
+
+t.CreatePluginFrame = function (name,size,position,scrollable,parent)
+ function createMenuButton(size,position,text,fontsize,name,parent)
+ local button = Instance.new("TextButton",parent)
+ button.AutoButtonColor = false
+ button.Name = name
+ button.BackgroundTransparency = 1
+ button.Position = position
+ button.Size = size
+ button.Font = Enum.Font.ArialBold
+ button.FontSize = fontsize
+ button.Text = text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BorderSizePixel = 0
+ button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
+
+ button.MouseEnter:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 0
+ end)
+ button.MouseLeave:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 1
+ end)
+
+ return button
+
+ end
+
+ local dragBar = Instance.new("Frame",parent)
+ dragBar.Name = tostring(name) .. "DragBar"
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ dragBar.BorderColor3 = Color3.new(0,0,0)
+ if size then
+ dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
+ else
+ dragBar.Size = UDim2.new(0,183,0,20)
+ end
+ if position then
+ dragBar.Position = position
+ end
+ dragBar.Active = true
+ dragBar.Draggable = true
+ --dragBar.Visible = false
+ dragBar.MouseEnter:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
+ end)
+ dragBar.MouseLeave:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ end)
+
+ -- plugin name label
+ local pluginNameLabel = Instance.new("TextLabel",dragBar)
+ pluginNameLabel.Name = "BarNameLabel"
+ pluginNameLabel.Text = " " .. tostring(name)
+ pluginNameLabel.TextColor3 = Color3.new(1,1,1)
+ pluginNameLabel.TextStrokeTransparency = 0
+ pluginNameLabel.Size = UDim2.new(1,0,1,0)
+ pluginNameLabel.Font = Enum.Font.ArialBold
+ pluginNameLabel.FontSize = Enum.FontSize.Size18
+ pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
+ pluginNameLabel.BackgroundTransparency = 1
+
+ -- close button
+ local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
+ local closeEvent = Instance.new("BindableEvent")
+ closeEvent.Name = "CloseEvent"
+ closeEvent.Parent = closeButton
+ closeButton.MouseButton1Click:connect(function ()
+ closeEvent:Fire()
+ closeButton.BackgroundTransparency = 1
+ end)
+
+ -- help button
+ local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
+ local helpFrame = Instance.new("Frame",dragBar)
+ helpFrame.Name = "HelpFrame"
+ helpFrame.BackgroundColor3 = Color3.new(0,0,0)
+ helpFrame.Size = UDim2.new(0,300,0,552)
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ helpFrame.Active = true
+ helpFrame.BorderSizePixel = 0
+ helpFrame.Visible = false
+
+ helpButton.MouseButton1Click:connect(function( )
+ helpFrame.Visible = not helpFrame.Visible
+ if helpFrame.Visible then
+ helpButton.Selected = true
+ helpButton.BackgroundTransparency = 0
+ local screenGui = getScreenGuiAncestor(helpFrame)
+ if screenGui then
+ if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
+ helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
+ else -- position on right hand side
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpButton.Selected = false
+ helpButton.BackgroundTransparency = 1
+ end
+ end)
+
+ local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
+ minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
+
+ local minimizeFrame = Instance.new("Frame",dragBar)
+ minimizeFrame.Name = "MinimizeFrame"
+ minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
+ minimizeFrame.BorderColor3 = Color3.new(0,0,0)
+ minimizeFrame.Position = UDim2.new(0,0,1,0)
+ if size then
+ minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
+ else
+ minimizeFrame.Size = UDim2.new(0,183,0,50)
+ end
+ minimizeFrame.Visible = false
+
+ local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
+ minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
+ minimizeBigButton.Name = "MinimizeButton"
+ minimizeBigButton.Size = UDim2.new(0,100,0,40)
+ minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
+ minimizeBigButton.Font = Enum.Font.ArialBold
+ minimizeBigButton.FontSize = Enum.FontSize.Size18
+ minimizeBigButton.TextColor3 = Color3.new(1,1,1)
+ minimizeBigButton.Text = "Show"
+
+ local separatingLine = Instance.new("Frame",dragBar)
+ separatingLine.Name = "SeparatingLine"
+ separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
+ separatingLine.BorderSizePixel = 0
+ separatingLine.Position = UDim2.new(1,-18,0.5,-7)
+ separatingLine.Size = UDim2.new(0,1,0,14)
+
+ local otherSeparatingLine = separatingLine:clone()
+ otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
+ otherSeparatingLine.Parent = dragBar
+
+ local widgetContainer = Instance.new("Frame",dragBar)
+ widgetContainer.Name = "WidgetContainer"
+ widgetContainer.BackgroundTransparency = 1
+ widgetContainer.Position = UDim2.new(0,0,1,0)
+ widgetContainer.BorderColor3 = Color3.new(0,0,0)
+ if not scrollable then
+ widgetContainer.BackgroundTransparency = 0
+ widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ end
+
+ if size then
+ if scrollable then
+ widgetContainer.Size = size
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
+ end
+ else
+ if scrollable then
+ widgetContainer.Size = UDim2.new(0,163,0,400)
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
+ end
+ end
+ if position then
+ widgetContainer.Position = position + UDim2.new(0,0,0,20)
+ end
+
+ local frame,control,verticalDragger = nil
+ if scrollable then
+ --frame for widgets
+ frame,control = t.CreateTrueScrollingFrame()
+ frame.Size = UDim2.new(1, 0, 1, 0)
+ frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ frame.BorderColor3 = Color3.new(0,0,0)
+ frame.Active = true
+ frame.Parent = widgetContainer
+ control.Parent = dragBar
+ control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ control.BorderSizePixel = 0
+ control.BackgroundTransparency = 0
+ control.Position = UDim2.new(1,-21,1,1)
+ if size then
+ control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
+ else
+ control.Size = UDim2.new(0,21,0,400)
+ end
+ control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
+
+ local fakeLine = Instance.new("Frame",control)
+ fakeLine.Name = "FakeLine"
+ fakeLine.BorderSizePixel = 0
+ fakeLine.BackgroundColor3 = Color3.new(0,0,0)
+ fakeLine.Size = UDim2.new(0,1,1,1)
+ fakeLine.Position = UDim2.new(1,0,0,0)
+
+ verticalDragger = Instance.new("TextButton",widgetContainer)
+ verticalDragger.ZIndex = 2
+ verticalDragger.AutoButtonColor = false
+ verticalDragger.Name = "VerticalDragger"
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ verticalDragger.BorderColor3 = Color3.new(0,0,0)
+ verticalDragger.Size = UDim2.new(1,20,0,20)
+ verticalDragger.Position = UDim2.new(0,0,1,0)
+ verticalDragger.Active = true
+ verticalDragger.Text = ""
+
+ local scrubFrame = Instance.new("Frame",verticalDragger)
+ scrubFrame.Name = "ScrubFrame"
+ scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
+ scrubFrame.BorderSizePixel = 0
+ scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
+ scrubFrame.Size = UDim2.new(0,10,0,1)
+ scrubFrame.ZIndex = 5
+ local scrubTwo = scrubFrame:clone()
+ scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
+ scrubTwo.Parent = verticalDragger
+ local scrubThree = scrubFrame:clone()
+ scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
+ scrubThree.Parent = verticalDragger
+
+ local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.BorderSizePixel = 0
+ areaSoak.Text = ""
+ areaSoak.ZIndex = 10
+ areaSoak.Visible = false
+ areaSoak.Active = true
+
+ local draggingVertical = false
+ local startYPos = nil
+ verticalDragger.MouseEnter:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
+ end)
+ verticalDragger.MouseLeave:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ end)
+ verticalDragger.MouseButton1Down:connect(function(x,y)
+ draggingVertical = true
+ areaSoak.Visible = true
+ startYPos = y
+ end)
+ areaSoak.MouseButton1Up:connect(function ( )
+ draggingVertical = false
+ areaSoak.Visible = false
+ end)
+ areaSoak.MouseMoved:connect(function(x,y)
+ if not draggingVertical then return end
+
+ local yDelta = y - startYPos
+ if not control.ScrollDownButton.Visible and yDelta > 0 then
+ return
+ end
+
+ if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
+ control.Size = UDim2.new (0,21,0,150)
+ return
+ end
+
+ startYPos = y
+
+ if widgetContainer.Size.Y.Offset + yDelta >= 0 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
+ control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
+ end
+ end)
+ end
+
+ local function switchMinimize()
+ minimizeFrame.Visible = not minimizeFrame.Visible
+ if scrollable then
+ frame.Visible = not frame.Visible
+ verticalDragger.Visible = not verticalDragger.Visible
+ control.Visible = not control.Visible
+ else
+ widgetContainer.Visible = not widgetContainer.Visible
+ end
+
+ if minimizeFrame.Visible then
+ minimizeButton.Text = "+"
+ else
+ minimizeButton.Text = "-"
+ end
+ end
+
+ minimizeBigButton.MouseButton1Click:connect(function ( )
+ switchMinimize()
+ end)
+
+ minimizeButton.MouseButton1Click:connect(function( )
+ switchMinimize()
+ end)
+
+ if scrollable then
+ return dragBar, frame, helpFrame, closeEvent
+ else
+ return dragBar, widgetContainer, helpFrame, closeEvent
+ end
+end
+
+t.Help =
+ function(funcNameOrFunc)
+ --input argument can be a string or a function. Should return a description (of arguments and expected side effects)
+ if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
+ return "Function CreatePropertyDropDownMenu. " ..
+ "Arguments: (instance, propertyName, enumType). " ..
+ "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
+ end
+ if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
+ return "Function CreateDropDownMenu. " ..
+ "Arguments: (items, onItemSelected). " ..
+ "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
+ end
+ if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
+ return "Function CreateMessageDialog. " ..
+ "Arguments: (title, message, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
+ end
+ if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
+ return "Function CreateStyledMessageDialog. " ..
+ "Arguments: (title, message, style, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
+ end
+ if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
+ return "Function GetFontHeight. " ..
+ "Arguments: (font, fontSize). " ..
+ "Side effect: returns the size in pixels of the given font + fontSize"
+ end
+ if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
+
+ end
+ if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
+ return "Function CreateScrollingFrame. " ..
+ "Arguments: (orderList, style) " ..
+ "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
+ end
+ if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
+ return "Function CreateTrueScrollingFrame. " ..
+ "Arguments: (nil) " ..
+ "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
+ end
+ if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
+ return "Function AutoTruncateTextObject. " ..
+ "Arguments: (textLabel) " ..
+ "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
+ end
+ if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
+ return "Function CreateSlider. " ..
+ "Arguments: (steps, width, position) " ..
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
+ end
+ if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
+ return "Function CreateLoadingFrame. " ..
+ "Arguments: (name, size, position) " ..
+ "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
+ end
+ if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
+ return "Function CreateTerrainMaterialSelector. " ..
+ "Arguments: (size, position) " ..
+ "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
+ end
+ end
+
+--RBXGUI END
+
+-- A couple of necessary functions
+local function waitForChild(instance, name)
+ assert(instance)
+ assert(name)
+ while not instance:FindFirstChild(name) do
+ instance.ChildAdded:wait()
+ end
+ return instance:FindFirstChild(name)
+end
+local function waitForProperty(instance, property)
+ assert(instance)
+ assert(property)
+ while not instance[property] do
+ instance.Changed:wait()
+ end
+end
+
+waitForChild(game,"Players")
+waitForProperty(game.Players,"LocalPlayer")
+local player = game.Players.LocalPlayer
+
+local RbxGui, msg = t
+if not RbxGui then print("could not find RbxGui!") return end
+
+--- Begin Locals
+local StaticTabName = "gear"
+
+local backpack = script.Parent.Backpack
+local screen = script.Parent
+
+local backpackItems = {}
+local buttons = {}
+
+local debounce = false
+local browsingMenu = false
+
+local mouseEnterCons = {}
+local mouseClickCons = {}
+
+local characterChildAddedCon = nil
+local characterChildRemovedCon = nil
+local backpackAddCon = nil
+
+local playerBackpack = waitForChild(player,"Backpack")
+
+waitForChild(backpack,"Tabs")
+
+waitForChild(backpack,"Gear")
+local gearPreview = waitForChild(backpack.Gear,"GearPreview")
+
+local scroller = waitForChild(backpack.Gear,"GearGridScrollingArea")
+
+local currentLoadout = waitForChild(backpack.Parent,"CurrentLoadout")
+
+local grid = waitForChild(backpack.Gear,"GearGrid")
+local gearButton = waitForChild(grid,"GearButton")
+
+local swapSlot = waitForChild(script.Parent,"SwapSlot")
+
+local backpackManager = waitForChild(script.Parent,"CoreScripts/BackpackScripts/BackpackManager")
+local backpackOpenEvent = waitForChild(backpackManager,"BackpackOpenEvent")
+local backpackCloseEvent = waitForChild(backpackManager,"BackpackCloseEvent")
+local tabClickedEvent = waitForChild(backpackManager,"TabClickedEvent")
+local resizeEvent = waitForChild(backpackManager,"ResizeEvent")
+local searchRequestedEvent = waitForChild(backpackManager,"SearchRequestedEvent")
+local tellBackpackReadyFunc = waitForChild(backpackManager,"BackpackReady")
+
+-- creating scroll bar early as to make sure items get placed correctly
+local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid")
+
+scrollFrame.Position = UDim2.new(0,0,0,30)
+scrollFrame.Size = UDim2.new(1,0,1,-30)
+scrollFrame.Parent = backpack.Gear.GearGrid
+
+local scrollBar = Instance.new("Frame")
+scrollBar.Name = "ScrollBar"
+scrollBar.BackgroundTransparency = 0.9
+scrollBar.BackgroundColor3 = Color3.new(1,1,1)
+scrollBar.BorderSizePixel = 0
+scrollBar.Size = UDim2.new(0, 17, 1, -36)
+scrollBar.Position = UDim2.new(0,0,0,18)
+scrollBar.Parent = scroller
+
+scrollDown.Position = UDim2.new(0,0,1,-17)
+
+scrollUp.Parent = scroller
+scrollDown.Parent = scroller
+
+local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
+
+scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
+scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
+scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
+
+local LoadoutButton = Instance.new("TextButton")
+
+LoadoutButton.Name = "LoadoutButton"
+LoadoutButton.Font = Enum.Font.ArialBold
+LoadoutButton.FontSize = Enum.FontSize.Size14
+LoadoutButton.Position = UDim2.new(0,0,0,0)
+LoadoutButton.Size = UDim2.new(1,0,0,32)
+LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
+LoadoutButton.Text = "Loadout #1"
+LoadoutButton.TextColor3 = Color3.new(1,1,1)
+LoadoutButton.Parent = scrollFrameLoadout
+
+local LoadoutButtonTwo = LoadoutButton:clone()
+LoadoutButtonTwo.Text = "Loadout #2"
+LoadoutButtonTwo.Parent = scrollFrameLoadout
+
+local LoadoutButtonThree = LoadoutButton:clone()
+LoadoutButtonThree.Text = "Loadout #3"
+LoadoutButtonThree.Parent = scrollFrameLoadout
+
+local LoadoutButtonFour = LoadoutButton:clone()
+LoadoutButtonFour.Text = "Loadout #4"
+LoadoutButtonFour.Parent = scrollFrameLoadout
+
+local scrollBarLoadout = Instance.new("Frame")
+scrollBarLoadout.Name = "ScrollBarLoadout"
+scrollBarLoadout.BackgroundTransparency = 0.9
+scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
+scrollBarLoadout.BorderSizePixel = 0
+scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
+scrollBarLoadout.Position = UDim2.new(0,0,0,18)
+scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
+
+scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
+
+scrollUpLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
+scrollDownLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
+
+
+-- Begin Functions
+function removeFromMap(map,object)
+ for i = 1, #map do
+ if map[i] == object then
+ table.remove(map,i)
+ break
+ end
+ end
+end
+
+function robloxLock(instance)
+end
+
+function resize()
+ local size = 0
+ if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
+ size = gearPreview.AbsoluteSize.X * 0.75
+ else
+ size = gearPreview.AbsoluteSize.Y * 0.75
+ end
+
+ waitForChild(gearPreview,"GearImage")
+ gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
+ gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
+
+ resizeGrid()
+end
+
+function addToGrid(child)
+ if not child:IsA("Tool") then
+ if not child:IsA("HopperBin") then
+ return
+ end
+ end
+ if child:FindFirstChild("RobloxBuildTool") then return end
+
+ for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
+ if v == child then return end
+ end
+
+ table.insert(backpackItems,child)
+
+ local changeCon = child.Changed:connect(function(prop)
+ if prop == "Name" then
+ if buttons[child] then
+ if buttons[child].Image == "" then
+ buttons[child].GearText.Text = child.Name
+ end
+ end
+ end
+ end)
+ local ancestryCon = nil
+ ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
+ local thisObject = nil
+ for k,v in pairs(backpackItems) do
+ if v == child then
+ thisObject = v
+ break
+ end
+ end
+
+ waitForProperty(player,"Character")
+ waitForChild(player,"Backpack")
+ if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
+ if ancestryCon then ancestryCon:disconnect() end
+ if changeCon then changeCon:disconnect() end
+
+ for k,v in pairs(backpackItems) do
+ if v == thisObject then
+ if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
+ if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
+ buttons[v].Parent = nil
+ buttons[v] = nil
+ break
+ end
+ end
+
+ removeFromMap(backpackItems,thisObject)
+
+ resizeGrid()
+ else
+ resizeGrid()
+ end
+ updateGridActive()
+ end)
+ resizeGrid()
+end
+
+function buttonClick(button)
+ if button:FindFirstChild("UnequipContextMenu") and not button.Active then
+ button.UnequipContextMenu.Visible = true
+ browsingMenu = true
+ end
+end
+
+function previewGear(button)
+ if not browsingMenu then
+ gearPreview.GearImage.Image = button.Image
+ gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
+ end
+end
+
+function findEmptySlot()
+ local smallestNum = nil
+ local loadout = currentLoadout:GetChildren()
+ for i = 1, #loadout do
+ if loadout[i]:IsA("Frame") and #loadout[i]:GetChildren() <= 0 then
+ local frameNum = tonumber(string.sub(loadout[i].Name,5))
+ if frameNum == 0 then frameNum = 10 end
+ if not smallestNum or (smallestNum > frameNum) then
+ smallestNum = frameNum
+ end
+ end
+ end
+ if smallestNum == 10 then smallestNum = 0 end
+ return smallestNum
+end
+
+function checkForSwap(button,x,y)
+ local loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
+ if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
+ if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
+ local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
+ swapGearSlot(slot,button)
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+function resizeGrid()
+ for k,v in pairs(backpackItems) do
+ if not v:FindFirstChild("RobloxBuildTool") then
+ if not buttons[v] then
+ local buttonClone = gearButton:clone()
+ buttonClone.Parent = grid.ScrollingFrame
+ buttonClone.Visible = true
+ buttonClone.Image = v.TextureId
+ if buttonClone.Image == "" then
+ buttonClone.GearText.Text = v.Name
+ end
+
+ buttonClone.GearReference.Value = v
+ buttonClone.Draggable = true
+ buttons[v] = buttonClone
+
+ local unequipMenu = getGearContextMenu()
+
+ unequipMenu.Visible = false
+ unequipMenu.Parent = buttonClone
+
+ local beginPos = nil
+ buttonClone.DragBegin:connect(function(value)
+ buttonClone.ZIndex = 9
+ beginPos = value
+ end)
+ buttonClone.DragStopped:connect(function(x,y)
+ buttonClone.ZIndex = 1
+ if beginPos ~= buttonClone.Position then
+ if not checkForSwap(buttonClone,x,y) then
+ buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
+ buttonClone.Draggable = false
+ delay(0.5,function()
+ buttonClone.Draggable = true
+ end)
+ else
+ buttonClone.Position = beginPos
+ end
+ end
+ end)
+ local clickTime = tick()
+ mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
+ mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function()
+ local newClickTime = tick()
+ if buttonClone.Active and (newClickTime - clickTime) < 0.5 then
+ local slot = findEmptySlot()
+ if slot then
+ buttonClone.ZIndex = 1
+ swapGearSlot(slot,buttonClone)
+ end
+ else
+ buttonClick(buttonClone)
+ end
+ clickTime = newClickTime
+ end)
+ end
+ end
+ end
+ recalculateScroll()
+end
+
+function showPartialGrid(subset)
+ for k,v in pairs(buttons) do
+ v.Parent = nil
+ end
+ if subset then
+ for k,v in pairs(subset) do
+ v.Parent = grid.ScrollingFrame
+ end
+ end
+ recalculateScroll()
+end
+
+function showEntireGrid()
+ for k,v in pairs(buttons) do
+ v.Parent = grid.ScrollingFrame
+ end
+ recalculateScroll()
+end
+
+function inLoadout(gear)
+ local children = currentLoadout:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ local button = children[i]:GetChildren()
+ if #button > 0 then
+ if button[1].GearReference.Value and button[1].GearReference.Value == gear then
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+function updateGridActive()
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ local gear = nil
+ local gearRef = buttons[v]:FindFirstChild("GearReference")
+
+ if gearRef then gear = gearRef.Value end
+
+ if not gear then
+ buttons[v].Active = false
+ elseif inLoadout(gear) then
+ buttons[v].Active = false
+ else
+ buttons[v].Active = true
+ end
+ end
+ end
+end
+
+function centerGear(loadoutChildren)
+ local gearButtons = {}
+ local lastSlotAdd = nil
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
+ if loadoutChildren[i].Name == "Slot0" then
+ lastSlotAdd = loadoutChildren[i]
+ else
+ table.insert(gearButtons, loadoutChildren[i])
+ end
+ end
+ end
+ if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
+
+ local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
+ for i = 1, #gearButtons do
+ gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
+ end
+end
+
+function tabClickHandler(tabName)
+ if tabName == StaticTabName then
+ backpackOpenHandler(tabName)
+ else
+ backpackCloseHandler(tabName)
+ end
+end
+
+function backpackOpenHandler(currentTab)
+ if currentTab and currentTab ~= StaticTabName then
+ backpack.Gear.Visible = false
+ return
+ end
+
+ backpack.Gear.Visible = true
+ updateGridActive()
+
+ resizeGrid()
+ resize()
+ tellBackpackReadyFunc:Invoke()
+end
+
+function backpackCloseHandler(currentTab)
+ if currentTab and currentTab ~= StaticTabName then
+ backpack.Gear.Visible = false
+ return
+ end
+
+ backpack.Gear.Visible = false
+
+ resizeGrid()
+ resize()
+ tellBackpackReadyFunc:Invoke()
+end
+
+function loadoutCheck(child, selectState)
+ if not child:IsA("ImageButton") then return end
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ if child:FindFirstChild("GearReference") and buttons[v]:FindFirstChild("GearReference") then
+ if buttons[v].GearReference.Value == child.GearReference.Value then
+ buttons[v].Active = selectState
+ break
+ end
+ end
+ end
+ end
+end
+
+function clearPreview()
+ gearPreview.GearImage.Image = ""
+ gearPreview.GearStats.GearName.Text = ""
+end
+
+function removeAllEquippedGear(physGear)
+ local stuff = player.Character:GetChildren()
+ for i = 1, #stuff do
+ if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
+ stuff[i].Parent = playerBackpack
+ end
+ end
+end
+
+function equipGear(physGear)
+ removeAllEquippedGear(physGear)
+ physGear.Parent = player.Character
+ updateGridActive()
+end
+
+function unequipGear(physGear)
+ physGear.Parent = playerBackpack
+ updateGridActive()
+end
+
+function highlight(button)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
+end
+function clearHighlight(button)
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundColor3 = Color3.new(0,0,0)
+end
+
+function swapGearSlot(slot,gearButton)
+ if not swapSlot.Value then -- signal loadout to swap a gear out
+ swapSlot.Slot.Value = slot
+ swapSlot.GearButton.Value = gearButton
+ swapSlot.Value = true
+ updateGridActive()
+ end
+end
+
+
+local UnequipGearMenuClick = function(element, menu)
+ if type(element.Action) ~= "number" then return end
+ local num = element.Action
+ if num == 1 then -- remove from loadout
+ unequipGear(menu.Parent.GearReference.Value)
+ local inventoryButton = menu.Parent
+ local gearToUnequip = inventoryButton.GearReference.Value
+ local loadoutChildren = currentLoadout:GetChildren()
+ local slot = -1
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ local button = loadoutChildren[i]:GetChildren()
+ if button[1] and button[1].GearReference.Value == gearToUnequip then
+ slot = button[1].SlotNumber.Text
+ break
+ end
+ end
+ end
+ swapGearSlot(slot,nil)
+ end
+end
+
+function setupCharacterConnections()
+
+ if backpackAddCon then backpackAddCon:disconnect() end
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+
+ -- make sure we get all the children
+ local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
+ for i = 1, #backpackChildren do
+ addToGrid(backpackChildren[i])
+ end
+
+ if characterChildAddedCon then characterChildAddedCon:disconnect() end
+ characterChildAddedCon =
+ game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
+ addToGrid(child)
+ updateGridActive()
+ end)
+
+ if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
+ characterChildRemovedCon =
+ game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
+ updateGridActive()
+ end)
+
+ wait()
+ centerGear(currentLoadout:GetChildren())
+end
+
+function removeCharacterConnections()
+ if characterChildAddedCon then characterChildAddedCon:disconnect() end
+ if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
+ if backpackAddCon then backpackAddCon:disconnect() end
+end
+
+function trim(s)
+ return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+function filterGear(terms)
+ local filteredGear = {}
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ local gearString = string.lower(buttons[v].GearReference.Value.Name)
+ gearString = trim(gearString)
+ for i = 1, #terms do
+ if string.match(gearString,terms[i]) then
+ table.insert(filteredGear,buttons[v])
+ break
+ end
+ end
+ end
+ end
+
+ return filteredGear
+end
+function splitByWhitespace(text)
+ if type(text) ~= "string" then return nil end
+
+ local terms = {}
+ for token in string.gmatch(text, "[^%s]+") do
+ if string.len(token) > 0 then
+ table.insert(terms,token)
+ end
+ end
+ return terms
+end
+function showSearchGear(searchTerms)
+ if not backpack.Gear.Visible then return end -- currently not active tab
+
+ local searchTermTable = splitByWhitespace(searchTerms)
+ if searchTermTable and (#searchTermTable > 0) then
+ currSearchTerms = searchTermTable
+ else
+ currSearchTerms = nil
+ end
+
+ if searchTermTable == nil then
+ showEntireGrid()
+ return
+ end
+
+ local filteredButtons = filterGear(currSearchTerms)
+ showPartialGrid(filteredButtons)
+end
+
+function nukeBackpack()
+ while #buttons > 0 do
+ table.remove(buttons)
+ end
+ buttons = {}
+ while #backpackItems > 0 do
+ table.remove(backpackItems)
+ end
+ backpackItems = {}
+ local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
+ for i = 1, #scrollingFrameChildren do
+ scrollingFrameChildren[i]:remove()
+ end
+end
+
+function getGearContextMenu()
+ local gearContextMenu = Instance.new("Frame")
+ gearContextMenu.Active = true
+ gearContextMenu.Name = "UnequipContextMenu"
+ gearContextMenu.Size = UDim2.new(0,115,0,70)
+ gearContextMenu.Position = UDim2.new(0,-16,0,-16)
+ gearContextMenu.BackgroundTransparency = 1
+ gearContextMenu.Visible = false
+
+ local gearContextMenuButton = Instance.new("TextButton")
+ gearContextMenuButton.Name = "UnequipContextMenuButton"
+ gearContextMenuButton.Text = ""
+ gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ gearContextMenuButton.ZIndex = 8
+ gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
+ gearContextMenuButton.Visible = true
+ gearContextMenuButton.Parent = gearContextMenu
+
+ local elementHeight = 12
+
+ local contextMenuElements = {}
+ local contextMenuElementsName = {"Remove Hotkey"}
+
+ for i = 1, #contextMenuElementsName do
+ local element = {}
+ element.Type = "Button"
+ element.Text = contextMenuElementsName[i]
+ element.Action = i
+ element.DoIt = UnequipGearMenuClick
+ table.insert(contextMenuElements,element)
+ end
+
+ for i, contextElement in ipairs(contextMenuElements) do
+ local element = contextElement
+ if element.Type == "Button" then
+ local button = Instance.new("TextButton")
+ button.Name = "UnequipContextButton" .. i
+ button.BackgroundColor3 = Color3.new(0,0,0)
+ button.BorderSizePixel = 0
+ button.TextXAlignment = Enum.TextXAlignment.Left
+ button.Text = " " .. contextElement.Text
+ button.Font = Enum.Font.Arial
+ button.FontSize = Enum.FontSize.Size14
+ button.Size = UDim2.new(1, 8, 0, elementHeight)
+ button.Position = UDim2.new(0,0,0,elementHeight * i)
+ button.TextColor3 = Color3.new(1,1,1)
+ button.ZIndex = 9
+ button.Parent = gearContextMenuButton
+
+ button.MouseButton1Click:connect(function()
+ if button.Active and not gearContextMenu.Parent.Active then
+ local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
+ browsingMenu = false
+ gearContextMenu.Visible = false
+ clearHighlight(button)
+ clearPreview()
+ end
+ end)
+
+ button.MouseEnter:connect(function()
+ if button.Active and gearContextMenu.Parent.Active then
+ highlight(button)
+ end
+ end)
+ button.MouseLeave:connect(function()
+ if button.Active and gearContextMenu.Parent.Active then
+ clearHighlight(button)
+ end
+ end)
+
+ contextElement.Button = button
+ contextElement.Element = button
+ elseif element.Type == "Label" then
+ local frame = Instance.new("Frame")
+ frame.Name = "ContextLabel" .. i
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(1, 8, 0, elementHeight)
+
+ local label = Instance.new("TextLabel")
+ label.Name = "Text1"
+ label.BackgroundTransparency = 1
+ label.BackgroundColor3 = Color3.new(1,1,1)
+ label.BorderSizePixel = 0
+ label.TextXAlignment = Enum.TextXAlignment.Left
+ label.Font = Enum.Font.ArialBold
+ label.FontSize = Enum.FontSize.Size14
+ label.Position = UDim2.new(0.0, 0, 0, 0)
+ label.Size = UDim2.new(0.5, 0, 1, 0)
+ label.TextColor3 = Color3.new(1,1,1)
+ label.ZIndex = 9
+ label.Parent = frame
+ element.Label1 = label
+
+ if element.GetText2 then
+ label = Instance.new("TextLabel")
+ label.Name = "Text2"
+ label.BackgroundTransparency = 1
+ label.BackgroundColor3 = Color3.new(1,1,1)
+ label.BorderSizePixel = 0
+ label.TextXAlignment = Enum.TextXAlignment.Right
+ label.Font = Enum.Font.Arial
+ label.FontSize = Enum.FontSize.Size14
+ label.Position = UDim2.new(0.5, 0, 0, 0)
+ label.Size = UDim2.new(0.5, 0, 1, 0)
+ label.TextColor3 = Color3.new(1,1,1)
+ label.ZIndex = 9
+ label.Parent = frame
+ element.Label2 = label
+ end
+ frame.Parent = gearContextMenuButton
+ element.Label = frame
+ element.Element = frame
+ end
+ end
+
+ gearContextMenu.ZIndex = 4
+ gearContextMenu.MouseLeave:connect(function()
+ browsingMenu = false
+ gearContextMenu.Visible = false
+ clearPreview()
+ end)
+
+
+ return gearContextMenu
+end
+
+local backpackChildren = player.Backpack:GetChildren()
+for i = 1, #backpackChildren do
+ addToGrid(backpackChildren[i])
+end
+
+------------------------- Start Lifelong Connections -----------------------
+
+
+resizeEvent.Event:connect(function(absSize)
+ if debounce then return end
+
+ debounce = true
+ wait()
+ resize()
+ resizeGrid()
+ debounce = false
+end)
+
+currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
+currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
+
+currentLoadout.DescendantAdded:connect(function(descendant)
+ if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
+ centerGear(currentLoadout:GetChildren())
+ end
+end)
+currentLoadout.DescendantRemoving:connect(function(descendant)
+ if not backpack.Visible and ( descendant:IsA("ImageButton") or descendant:IsA("TextButton") ) then
+ wait()
+ centerGear(currentLoadout:GetChildren())
+ end
+end)
+
+grid.MouseEnter:connect(function() clearPreview() end)
+grid.MouseLeave:connect(function() clearPreview() end)
+
+player.CharacterRemoving:connect(function()
+ removeCharacterConnections()
+ nukeBackpack()
+end)
+player.CharacterAdded:connect(function() setupCharacterConnections() end)
+
+player.ChildAdded:connect(function(child)
+ if child:IsA("Backpack") then
+ playerBackpack = child
+ if backpackAddCon then backpackAddCon:disconnect() end
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+ end
+end)
+
+swapSlot.Changed:connect(function()
+ if not swapSlot.Value then
+ updateGridActive()
+ end
+end)
+
+local loadoutChildren = currentLoadout:GetChildren()
+for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
+ loadoutChildren[i].ChildRemoved:connect(function()
+ updateGridActive()
+ end)
+ loadoutChildren[i].ChildAdded:connect(function()
+ updateGridActive()
+ end)
+ end
+end
+------------------------- End Lifelong Connections -----------------------
+
+resize()
+resizeGrid()
+
+-- make sure any items in the loadout are accounted for in inventory
+local loadoutChildren = currentLoadout:GetChildren()
+for i = 1, #loadoutChildren do
+ loadoutCheck(loadoutChildren[i], false)
+end
+if not backpack.Visible then centerGear(currentLoadout:GetChildren()) end
+
+-- make sure that inventory is listening to gear reparenting
+if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
+ setupCharacterConnections()
+end
+if not backpackAddCon then
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+end
+
+backpackOpenEvent.Event:connect(backpackOpenHandler)
+backpackCloseEvent.Event:connect(backpackCloseHandler)
+tabClickedEvent.Event:connect(tabClickHandler)
+searchRequestedEvent.Event:connect(showSearchGear)
+
+recalculateScrollLoadout()
+
+
+ -
+
+ false
+
+ BackpackResizer
+ print("Making sure BackpackResizer script is doing it's work...")
+print("Backpack has been built. Time for the resizer script.")
+script.Parent.BackpackResizer.Parent = script.Parent.Backpack
+local t = {}
+
+local function ScopedConnect(parentInstance, instance, event, signalFunc, syncFunc, removeFunc)
+ local eventConnection = nil
+
+ --Connection on parentInstance is scoped by parentInstance (when destroyed, it goes away)
+ local tryConnect = function()
+ if game:IsAncestorOf(parentInstance) then
+ --Entering the world, make sure we are connected/synced
+ if not eventConnection then
+ eventConnection = instance[event]:connect(signalFunc)
+ if syncFunc then syncFunc() end
+ end
+ else
+ --Probably leaving the world, so disconnect for now
+ if eventConnection then
+ eventConnection:disconnect()
+ if removeFunc then removeFunc() end
+ end
+ end
+ end
+
+ --Hook it up to ancestryChanged signal
+ local connection = parentInstance.AncestryChanged:connect(tryConnect)
+
+ --Now connect us if we're already in the world
+ tryConnect()
+
+ return connection
+end
+
+local function getScreenGuiAncestor(instance)
+ local localInstance = instance
+ while localInstance and not localInstance:IsA("ScreenGui") do
+ localInstance = localInstance.Parent
+ end
+ return localInstance
+end
+
+local function CreateButtons(frame, buttons, yPos, ySize)
+ local buttonNum = 1
+ local buttonObjs = {}
+ for i, obj in ipairs(buttons) do
+ local button = Instance.new("TextButton")
+ button.Name = "Button" .. buttonNum
+ button.Font = Enum.Font.Arial
+ button.FontSize = Enum.FontSize.Size18
+ button.AutoButtonColor = true
+ button.Modal = true
+ if obj["Style"] then
+ button.Style = obj.Style
+ else
+ button.Style = Enum.ButtonStyle.RobloxButton
+ end
+ button.Text = obj.Text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.MouseButton1Click:connect(obj.Function)
+ button.Parent = frame
+ buttonObjs[buttonNum] = button
+
+ buttonNum = buttonNum + 1
+ end
+ local numButtons = buttonNum-1
+
+ if numButtons == 1 then
+ frame.Button1.Position = UDim2.new(0.35, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.4,0,ySize.Scale, ySize.Offset)
+ elseif numButtons == 2 then
+ frame.Button1.Position = UDim2.new(0.1, 0, yPos.Scale, yPos.Offset)
+ frame.Button1.Size = UDim2.new(.8/3,0, ySize.Scale, ySize.Offset)
+
+ frame.Button2.Position = UDim2.new(0.55, 0, yPos.Scale, yPos.Offset)
+ frame.Button2.Size = UDim2.new(.35,0, ySize.Scale, ySize.Offset)
+ elseif numButtons >= 3 then
+ local spacing = .1 / numButtons
+ local buttonSize = .9 / numButtons
+
+ buttonNum = 1
+ while buttonNum <= numButtons do
+ buttonObjs[buttonNum].Position = UDim2.new(spacing*buttonNum + (buttonNum-1) * buttonSize, 0, yPos.Scale, yPos.Offset)
+ buttonObjs[buttonNum].Size = UDim2.new(buttonSize, 0, ySize.Scale, ySize.Offset)
+ buttonNum = buttonNum + 1
+ end
+ end
+end
+
+local function setSliderPos(newAbsPosX,slider,sliderPosition,bar,steps)
+
+ local newStep = steps - 1 --otherwise we really get one more step than we want
+ local relativePosX = math.min(1, math.max(0, (newAbsPosX - bar.AbsolutePosition.X) / bar.AbsoluteSize.X ))
+ local wholeNum, remainder = math.modf(relativePosX * newStep)
+ if remainder > 0.5 then
+ wholeNum = wholeNum + 1
+ end
+ relativePosX = wholeNum/newStep
+
+ local result = math.ceil(relativePosX * newStep)
+ if sliderPosition.Value ~= (result + 1) then --only update if we moved a step
+ sliderPosition.Value = result + 1
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end
+
+end
+
+local function cancelSlide(areaSoak)
+ areaSoak.Visible = false
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+end
+
+t.CreateStyledMessageDialog = function(title, message, style, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0, 165)
+ frame.Position = UDim2.new(0.25, 0, 0.5, -72.5)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local styleImage = Instance.new("ImageLabel")
+ styleImage.Name = "StyleImage"
+ styleImage.BackgroundTransparency = 1
+ styleImage.Position = UDim2.new(0,5,0,15)
+ if style == "error" or style == "Error" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "rbxasset://ui/error.png"
+ elseif style == "notify" or style == "Notify" then
+ styleImage.Size = UDim2.new(0, 71, 0, 71)
+ styleImage.Image = "rbxasset://ui/notify.png"
+ elseif style == "confirm" or style == "Confirm" then
+ styleImage.Size = UDim2.new(0, 74, 0, 76)
+ styleImage.Image = "rbxasset://ui/confirm.png"
+ else
+ return t.CreateMessageDialog(title,message,buttons)
+ end
+ styleImage.Parent = frame
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.TextStrokeTransparency = 0
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 80, 0, 0)
+ titleLabel.Size = UDim2.new(1, -80, 0, 40)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextStrokeTransparency = 0
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 80, 0, 45)
+ messageLabel.Size = UDim2.new(0.95, -80, 0, 55)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0, 105), UDim.new(0, 40) )
+
+ return frame
+end
+
+t.CreateMessageDialog = function(title, message, buttons)
+ local frame = Instance.new("Frame")
+ frame.Size = UDim2.new(0.5, 0, 0.5, 0)
+ frame.Position = UDim2.new(0.25, 0, 0.25, 0)
+ frame.Name = "MessageDialog"
+ frame.Active = true
+ frame.Style = Enum.FrameStyle.RobloxRound
+
+ local titleLabel = Instance.new("TextLabel")
+ titleLabel.Name = "Title"
+ titleLabel.Text = title
+ titleLabel.BackgroundTransparency = 1
+ titleLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ titleLabel.Position = UDim2.new(0, 0, 0, 0)
+ titleLabel.Size = UDim2.new(1, 0, 0.15, 0)
+ titleLabel.Font = Enum.Font.ArialBold
+ titleLabel.FontSize = Enum.FontSize.Size36
+ titleLabel.TextXAlignment = Enum.TextXAlignment.Center
+ titleLabel.TextYAlignment = Enum.TextYAlignment.Center
+ titleLabel.Parent = frame
+
+ local messageLabel = Instance.new("TextLabel")
+ messageLabel.Name = "Message"
+ messageLabel.Text = message
+ messageLabel.TextColor3 = Color3.new(221/255,221/255,221/255)
+ messageLabel.Position = UDim2.new(0.025, 0, 0.175, 0)
+ messageLabel.Size = UDim2.new(0.95, 0, .55, 0)
+ messageLabel.BackgroundTransparency = 1
+ messageLabel.Font = Enum.Font.Arial
+ messageLabel.FontSize = Enum.FontSize.Size18
+ messageLabel.TextWrap = true
+ messageLabel.TextXAlignment = Enum.TextXAlignment.Left
+ messageLabel.TextYAlignment = Enum.TextYAlignment.Top
+ messageLabel.Parent = frame
+
+ CreateButtons(frame, buttons, UDim.new(0.8,0), UDim.new(0.15, 0))
+
+ return frame
+end
+
+t.CreateDropDownMenu = function(items, onSelect, forRoblox)
+ local width = UDim.new(0, 100)
+ local height = UDim.new(0, 32)
+
+ local xPos = 0.055
+ local frame = Instance.new("Frame")
+ frame.Name = "DropDownMenu"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(width, height)
+
+ local dropDownMenu = Instance.new("TextButton")
+ dropDownMenu.Name = "DropDownMenuButton"
+ dropDownMenu.TextWrap = true
+ dropDownMenu.TextColor3 = Color3.new(1,1,1)
+ dropDownMenu.Text = "Choose One"
+ dropDownMenu.Font = Enum.Font.ArialBold
+ dropDownMenu.FontSize = Enum.FontSize.Size18
+ dropDownMenu.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownMenu.TextYAlignment = Enum.TextYAlignment.Center
+ dropDownMenu.BackgroundTransparency = 1
+ dropDownMenu.AutoButtonColor = true
+ dropDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ dropDownMenu.Size = UDim2.new(1,0,1,0)
+ dropDownMenu.Parent = frame
+ dropDownMenu.ZIndex = 2
+
+ local dropDownIcon = Instance.new("ImageLabel")
+ dropDownIcon.Name = "Icon"
+ dropDownIcon.Active = false
+ dropDownIcon.Image = "rbxasset://ui/dropdownicon.png"
+ dropDownIcon.BackgroundTransparency = 1
+ dropDownIcon.Size = UDim2.new(0,11,0,6)
+ dropDownIcon.Position = UDim2.new(1,-11,0.5, -2)
+ dropDownIcon.Parent = dropDownMenu
+ dropDownIcon.ZIndex = 2
+
+ local itemCount = #items
+ local dropDownItemCount = #items
+ local useScrollButtons = false
+ if dropDownItemCount > 6 then
+ useScrollButtons = true
+ dropDownItemCount = 6
+ end
+
+ local droppedDownMenu = Instance.new("TextButton")
+ droppedDownMenu.Name = "List"
+ droppedDownMenu.Text = ""
+ droppedDownMenu.BackgroundTransparency = 1
+ --droppedDownMenu.AutoButtonColor = true
+ droppedDownMenu.Style = Enum.ButtonStyle.RobloxButton
+ droppedDownMenu.Visible = false
+ droppedDownMenu.Active = true --Blocks clicks
+ droppedDownMenu.Position = UDim2.new(0,0,0,0)
+ droppedDownMenu.Size = UDim2.new(1,0, (1 + dropDownItemCount)*.8, 0)
+ droppedDownMenu.Parent = frame
+ droppedDownMenu.ZIndex = 2
+
+ local choiceButton = Instance.new("TextButton")
+ choiceButton.Name = "ChoiceButton"
+ choiceButton.BackgroundTransparency = 1
+ choiceButton.BorderSizePixel = 0
+ choiceButton.Text = "ReplaceMe"
+ choiceButton.TextColor3 = Color3.new(1,1,1)
+ choiceButton.TextXAlignment = Enum.TextXAlignment.Left
+ choiceButton.TextYAlignment = Enum.TextYAlignment.Center
+ choiceButton.BackgroundColor3 = Color3.new(1, 1, 1)
+ choiceButton.Font = Enum.Font.Arial
+ choiceButton.FontSize = Enum.FontSize.Size18
+ if useScrollButtons then
+ choiceButton.Size = UDim2.new(1,-13, .8/((dropDownItemCount + 1)*.8),0)
+ else
+ choiceButton.Size = UDim2.new(1, 0, .8/((dropDownItemCount + 1)*.8),0)
+ end
+ choiceButton.TextWrap = true
+ choiceButton.ZIndex = 2
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = true
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 3
+
+ local dropDownSelected = false
+
+ local scrollUpButton
+ local scrollDownButton
+ local scrollMouseCount = 0
+
+ local setZIndex = function(baseZIndex)
+ droppedDownMenu.ZIndex = baseZIndex +1
+ if scrollUpButton then
+ scrollUpButton.ZIndex = baseZIndex + 3
+ end
+ if scrollDownButton then
+ scrollDownButton.ZIndex = baseZIndex + 3
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child.Name == "ChoiceButton" then
+ child.ZIndex = baseZIndex + 2
+ elseif child.Name == "ClickCaptureButton" then
+ child.ZIndex = baseZIndex
+ end
+ end
+ end
+ end
+
+ local scrollBarPosition = 1
+ local updateScroll = function()
+ if scrollUpButton then
+ scrollUpButton.Active = scrollBarPosition > 1
+ end
+ if scrollDownButton then
+ scrollDownButton.Active = scrollBarPosition + dropDownItemCount <= itemCount
+ end
+
+ local children = droppedDownMenu:GetChildren()
+ if not children then return end
+
+ local childNum = 1
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if childNum < scrollBarPosition or childNum >= scrollBarPosition + dropDownItemCount then
+ obj.Visible = false
+ else
+ obj.Position = UDim2.new(0,0,((childNum-scrollBarPosition+1)*.8)/((dropDownItemCount+1)*.8),0)
+ obj.Visible = true
+ end
+ obj.TextColor3 = Color3.new(1,1,1)
+ obj.BackgroundTransparency = 1
+
+ childNum = childNum + 1
+ end
+ end
+ end
+ local toggleVisibility = function()
+ dropDownSelected = not dropDownSelected
+
+ areaSoak.Visible = not areaSoak.Visible
+ dropDownMenu.Visible = not dropDownSelected
+ droppedDownMenu.Visible = dropDownSelected
+ if dropDownSelected then
+ setZIndex(4)
+ else
+ setZIndex(2)
+ end
+ if useScrollButtons then
+ updateScroll()
+ end
+ end
+ droppedDownMenu.MouseButton1Click:connect(toggleVisibility)
+
+ local updateSelection = function(text)
+ local foundItem = false
+ local children = droppedDownMenu:GetChildren()
+ local childNum = 1
+ if children then
+ for i, obj in ipairs(children) do
+ if obj.Name == "ChoiceButton" then
+ if obj.Text == text then
+ obj.Font = Enum.Font.ArialBold
+ foundItem = true
+ scrollBarPosition = childNum
+ else
+ obj.Font = Enum.Font.Arial
+ end
+ childNum = childNum + 1
+ end
+ end
+ end
+ if not text then
+ dropDownMenu.Text = "Choose One"
+ scrollBarPosition = 1
+ else
+ if not foundItem then
+ error("Invalid Selection Update -- " .. text)
+ end
+
+ if scrollBarPosition + dropDownItemCount > itemCount + 1 then
+ scrollBarPosition = itemCount - dropDownItemCount + 1
+ end
+
+ dropDownMenu.Text = text
+ end
+ end
+
+ local function scrollDown()
+ if scrollBarPosition + dropDownItemCount <= itemCount then
+ scrollBarPosition = scrollBarPosition + 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+ local function scrollUp()
+ if scrollBarPosition > 1 then
+ scrollBarPosition = scrollBarPosition - 1
+ updateScroll()
+ return true
+ end
+ return false
+ end
+
+ if useScrollButtons then
+ --Make some scroll buttons
+ scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+ scrollUpButton.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),0)
+ scrollUpButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollUp()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollUp() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ scrollUpButton.Parent = droppedDownMenu
+
+ scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+ scrollDownButton.Position = UDim2.new(1,-11,1,-11)
+ scrollDownButton.Parent = droppedDownMenu
+ scrollDownButton.MouseButton1Click:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseLeave:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollMouseCount = scrollMouseCount + 1
+
+ scrollDown()
+ local val = scrollMouseCount
+ wait(0.5)
+ while val == scrollMouseCount do
+ if scrollDown() == false then
+ break
+ end
+ wait(0.1)
+ end
+ end)
+
+ local scrollbar = Instance.new("ImageLabel")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, (dropDownItemCount*.8)/((dropDownItemCount+1)*.8), -(17) - 11 - 4)
+ scrollbar.Position = UDim2.new(1,-11,(1*.8)/((dropDownItemCount+1)*.8),17+2)
+ scrollbar.Parent = droppedDownMenu
+ end
+
+ for i,item in ipairs(items) do
+ -- needed to maintain local scope for items in event listeners below
+ local button = choiceButton:clone()
+ if forRoblox then
+ button.RobloxLocked = true
+ end
+ button.Text = item
+ button.Parent = droppedDownMenu
+ button.MouseButton1Click:connect(function()
+ --Remove Highlight
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundTransparency = 1
+
+ updateSelection(item)
+ onSelect(item)
+
+ toggleVisibility()
+ end)
+ button.MouseEnter:connect(function()
+ --Add Highlight
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ end)
+
+ button.MouseLeave:connect(function()
+ --Remove Highlight
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundTransparency = 1
+ end)
+ end
+
+ --This does the initial layout of the buttons
+ updateScroll()
+
+ frame.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(frame)
+ end
+ end)
+
+ dropDownMenu.MouseButton1Click:connect(toggleVisibility)
+ areaSoak.MouseButton1Click:connect(toggleVisibility)
+ return frame, updateSelection
+end
+
+t.CreatePropertyDropDownMenu = function(instance, property, enum)
+
+ local items = enum:GetEnumItems()
+ local names = {}
+ local nameToItem = {}
+ for i,obj in ipairs(items) do
+ names[i] = obj.Name
+ nameToItem[obj.Name] = obj
+ end
+
+ local frame
+ local updateSelection
+ frame, updateSelection = t.CreateDropDownMenu(names, function(text) instance[property] = nameToItem[text] end)
+
+ ScopedConnect(frame, instance, "Changed",
+ function(prop)
+ if prop == property then
+ updateSelection(instance[property].Name)
+ end
+ end,
+ function()
+ updateSelection(instance[property].Name)
+ end)
+
+ return frame
+end
+
+t.GetFontHeight = function(font, fontSize)
+ if font == nil or fontSize == nil then
+ error("Font and FontSize must be non-nil")
+ end
+
+ if font == Enum.Font.Legacy then
+ if fontSize == Enum.FontSize.Size8 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 15
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 17
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 21
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 27
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 54
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 72
+ else
+ error("Unknown FontSize")
+ end
+ elseif font == Enum.Font.Arial or font == Enum.Font.ArialBold then
+ if fontSize == Enum.FontSize.Size8 then
+ return 8
+ elseif fontSize == Enum.FontSize.Size9 then
+ return 9
+ elseif fontSize == Enum.FontSize.Size10 then
+ return 10
+ elseif fontSize == Enum.FontSize.Size11 then
+ return 11
+ elseif fontSize == Enum.FontSize.Size12 then
+ return 12
+ elseif fontSize == Enum.FontSize.Size14 then
+ return 14
+ elseif fontSize == Enum.FontSize.Size18 then
+ return 18
+ elseif fontSize == Enum.FontSize.Size24 then
+ return 24
+ elseif fontSize == Enum.FontSize.Size36 then
+ return 36
+ elseif fontSize == Enum.FontSize.Size48 then
+ return 48
+ else
+ error("Unknown FontSize")
+ end
+ else
+ error("Unknown Font " .. font)
+ end
+end
+
+local function layoutGuiObjectsHelper(frame, guiObjects, settingsTable)
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+ for i, child in ipairs(guiObjects) do
+ if child:IsA("TextLabel") or child:IsA("TextButton") then
+ local isLabel = child:IsA("TextLabel")
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, pixelsRemaining)
+
+ if child.TextFits and child.TextBounds.Y < pixelsRemaining then
+ child.Visible = true
+ if isLabel then
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextLabelSizePadY"])
+ else
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.TextBounds.Y + settingsTable["TextButtonSizePadY"])
+ end
+
+ while not child.TextFits do
+ child.Size = UDim2.new(child.Size.X.Scale, child.Size.X.Offset, 0, child.AbsoluteSize.Y + 1)
+ end
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+
+ if isLabel then
+ pixelsRemaining = pixelsRemaining - settingsTable["TextLabelPositionPadY"]
+ else
+ pixelsRemaining = pixelsRemaining - settingsTable["TextButtonPositionPadY"]
+ end
+ else
+ child.Visible = false
+ pixelsRemaining = -1
+ end
+
+ else
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ child.Visible = (pixelsRemaining >= 0)
+ end
+ end
+end
+
+t.LayoutGuiObjects = function(frame, guiObjects, settingsTable)
+ if not frame:IsA("GuiObject") then
+ error("Frame must be a GuiObject")
+ end
+ for i, child in ipairs(guiObjects) do
+ if not child:IsA("GuiObject") then
+ error("All elements that are layed out must be of type GuiObject")
+ end
+ end
+
+ if not settingsTable then
+ settingsTable = {}
+ end
+
+ if not settingsTable["TextLabelSizePadY"] then
+ settingsTable["TextLabelSizePadY"] = 0
+ end
+ if not settingsTable["TextLabelPositionPadY"] then
+ settingsTable["TextLabelPositionPadY"] = 0
+ end
+ if not settingsTable["TextButtonSizePadY"] then
+ settingsTable["TextButtonSizePadY"] = 12
+ end
+ if not settingsTable["TextButtonPositionPadY"] then
+ settingsTable["TextButtonPositionPadY"] = 2
+ end
+
+ --Wrapper frame takes care of styled objects
+ local wrapperFrame = Instance.new("Frame")
+ wrapperFrame.Name = "WrapperFrame"
+ wrapperFrame.BackgroundTransparency = 1
+ wrapperFrame.Size = UDim2.new(1,0,1,0)
+ wrapperFrame.Parent = frame
+
+ for i, child in ipairs(guiObjects) do
+ child.Parent = wrapperFrame
+ end
+
+ local recalculate = function()
+ wait()
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(recalculate)
+
+ layoutGuiObjectsHelper(wrapperFrame, guiObjects, settingsTable)
+end
+
+
+t.CreateSlider = function(steps,width,position)
+ local sliderGui = Instance.new("Frame")
+ sliderGui.Size = UDim2.new(1,0,1,0)
+ sliderGui.BackgroundTransparency = 1
+ sliderGui.Name = "SliderGui"
+
+ local sliderSteps = Instance.new("IntValue")
+ sliderSteps.Name = "SliderSteps"
+ sliderSteps.Value = steps
+ sliderSteps.Parent = sliderGui
+
+ local areaSoak = Instance.new("TextButton")
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Text = ""
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.Active = false
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.Visible = false
+ areaSoak.ZIndex = 4
+
+ sliderGui.AncestryChanged:connect(function(child,parent)
+ if parent == nil then
+ areaSoak.Parent = nil
+ else
+ areaSoak.Parent = getScreenGuiAncestor(sliderGui)
+ end
+ end)
+
+ local sliderPosition = Instance.new("IntValue")
+ sliderPosition.Name = "SliderPosition"
+ sliderPosition.Value = 0
+ sliderPosition.Parent = sliderGui
+
+ local id = math.random(1,100)
+
+ local bar = Instance.new("TextButton")
+ bar.Text = ""
+ bar.AutoButtonColor = false
+ bar.Name = "Bar"
+ bar.BackgroundColor3 = Color3.new(0,0,0)
+ if type(width) == "number" then
+ bar.Size = UDim2.new(0,width,0,5)
+ else
+ bar.Size = UDim2.new(0,200,0,5)
+ end
+ bar.BorderColor3 = Color3.new(95/255,95/255,95/255)
+ bar.ZIndex = 2
+ bar.Parent = sliderGui
+
+ if position["X"] and position["X"]["Scale"] and position["X"]["Offset"] and position["Y"] and position["Y"]["Scale"] and position["Y"]["Offset"] then
+ bar.Position = position
+ end
+
+ local slider = Instance.new("ImageButton")
+ slider.Name = "Slider"
+ slider.BackgroundTransparency = 1
+ slider.Image = "rbxasset://textures/ui/Slider.png"
+ slider.Position = UDim2.new(0,0,0.5,-10)
+ slider.Size = UDim2.new(0,20,0,20)
+ slider.ZIndex = 3
+ slider.Parent = bar
+
+ local areaSoakMouseMoveCon = nil
+
+ areaSoak.MouseLeave:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+ areaSoak.MouseButton1Up:connect(function()
+ if areaSoak.Visible then
+ cancelSlide(areaSoak)
+ end
+ end)
+
+ slider.MouseButton1Down:connect(function()
+ areaSoak.Visible = true
+ if areaSoakMouseMoveCon then areaSoakMouseMoveCon:disconnect() end
+ areaSoakMouseMoveCon = areaSoak.MouseMoved:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+ end)
+
+ slider.MouseButton1Up:connect(function() cancelSlide(areaSoak) end)
+
+ sliderPosition.Changed:connect(function(prop)
+ sliderPosition.Value = math.min(steps, math.max(1,sliderPosition.Value))
+ local relativePosX = (sliderPosition.Value - 1) / (steps - 1)
+ slider.Position = UDim2.new(relativePosX,-slider.AbsoluteSize.X/2,slider.Position.Y.Scale,slider.Position.Y.Offset)
+ end)
+
+ bar.MouseButton1Down:connect(function(x,y)
+ setSliderPos(x,slider,sliderPosition,bar,steps)
+ end)
+
+ return sliderGui, sliderPosition, sliderSteps
+
+end
+
+t.CreateTrueScrollingFrame = function()
+ local lowY = nil
+ local highY = nil
+
+ local dragCon = nil
+ local upCon = nil
+
+ local internalChange = false
+
+ local descendantsChangeConMap = {}
+
+ local scrollingFrame = Instance.new("Frame")
+ scrollingFrame.Name = "ScrollingFrame"
+ scrollingFrame.Active = true
+ scrollingFrame.Size = UDim2.new(1,0,1,0)
+ scrollingFrame.ClipsDescendants = true
+
+ local controlFrame = Instance.new("Frame")
+ controlFrame.Name = "ControlFrame"
+ controlFrame.BackgroundTransparency = 1
+ controlFrame.Size = UDim2.new(0,18,1,0)
+ controlFrame.Position = UDim2.new(1,-20,0,0)
+ controlFrame.Parent = scrollingFrame
+
+ local scrollBottom = Instance.new("BoolValue")
+ scrollBottom.Value = false
+ scrollBottom.Name = "ScrollBottom"
+ scrollBottom.Parent = controlFrame
+
+ local scrollUp = Instance.new("BoolValue")
+ scrollUp.Value = false
+ scrollUp.Name = "scrollUp"
+ scrollUp.Parent = controlFrame
+
+ local scrollUpButton = Instance.new("TextButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.Text = ""
+ scrollUpButton.AutoButtonColor = false
+ scrollUpButton.BackgroundColor3 = Color3.new(0,0,0)
+ scrollUpButton.BorderColor3 = Color3.new(1,1,1)
+ scrollUpButton.BackgroundTransparency = 0.5
+ scrollUpButton.Size = UDim2.new(0,18,0,18)
+ scrollUpButton.ZIndex = 2
+ scrollUpButton.Parent = controlFrame
+ for i = 1, 6 do
+ local triFrame = Instance.new("Frame")
+ triFrame.BorderColor3 = Color3.new(1,1,1)
+ triFrame.Name = "tri" .. tostring(i)
+ triFrame.ZIndex = 3
+ triFrame.BackgroundTransparency = 0.5
+ triFrame.Size = UDim2.new(0,12 - ((i -1) * 2),0,0)
+ triFrame.Position = UDim2.new(0,3 + (i -1),0.5,2 - (i -1))
+ triFrame.Parent = scrollUpButton
+ end
+ scrollUpButton.MouseEnter:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.1
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollUpButton.MouseLeave:connect(function()
+ scrollUpButton.BackgroundTransparency = 0.5
+ local upChildren = scrollUpButton:GetChildren()
+ for i = 1, #upChildren do
+ upChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+
+ local scrollDownButton = scrollUpButton:clone()
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.Position = UDim2.new(0,0,1,-18)
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].Position = UDim2.new(0,3 + (i -1),0.5,-2 + (i - 1))
+ end
+ scrollDownButton.MouseEnter:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.1
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.1
+ end
+ end)
+ scrollDownButton.MouseLeave:connect(function()
+ scrollDownButton.BackgroundTransparency = 0.5
+ local downChildren = scrollDownButton:GetChildren()
+ for i = 1, #downChildren do
+ downChildren[i].BackgroundTransparency = 0.5
+ end
+ end)
+ scrollDownButton.Parent = controlFrame
+
+ local scrollTrack = Instance.new("Frame")
+ scrollTrack.Name = "ScrollTrack"
+ scrollTrack.BackgroundTransparency = 1
+ scrollTrack.Size = UDim2.new(0,18,1,-38)
+ scrollTrack.Position = UDim2.new(0,0,0,19)
+ scrollTrack.Parent = controlFrame
+
+ local scrollbar = Instance.new("TextButton")
+ scrollbar.BackgroundColor3 = Color3.new(0,0,0)
+ scrollbar.BorderColor3 = Color3.new(1,1,1)
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.AutoButtonColor = false
+ scrollbar.Text = ""
+ scrollbar.Active = true
+ scrollbar.Name = "ScrollBar"
+ scrollbar.ZIndex = 2
+ scrollbar.BackgroundTransparency = 0.5
+ scrollbar.Size = UDim2.new(0, 18, 0.1, 0)
+ scrollbar.Position = UDim2.new(0,0,0,0)
+ scrollbar.Parent = scrollTrack
+
+ local scrollNub = Instance.new("Frame")
+ scrollNub.Name = "ScrollNub"
+ scrollNub.BorderColor3 = Color3.new(1,1,1)
+ scrollNub.Size = UDim2.new(0,10,0,0)
+ scrollNub.Position = UDim2.new(0.5,-5,0.5,0)
+ scrollNub.ZIndex = 2
+ scrollNub.BackgroundTransparency = 0.5
+ scrollNub.Parent = scrollbar
+
+ local newNub = scrollNub:clone()
+ newNub.Position = UDim2.new(0.5,-5,0.5,-2)
+ newNub.Parent = scrollbar
+
+ local lastNub = scrollNub:clone()
+ lastNub.Position = UDim2.new(0.5,-5,0.5,2)
+ lastNub.Parent = scrollbar
+
+ scrollbar.MouseEnter:connect(function()
+ scrollbar.BackgroundTransparency = 0.1
+ scrollNub.BackgroundTransparency = 0.1
+ newNub.BackgroundTransparency = 0.1
+ lastNub.BackgroundTransparency = 0.1
+ end)
+ scrollbar.MouseLeave:connect(function()
+ scrollbar.BackgroundTransparency = 0.5
+ scrollNub.BackgroundTransparency = 0.5
+ newNub.BackgroundTransparency = 0.5
+ lastNub.BackgroundTransparency = 0.5
+ end)
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local function positionScrollBar(x,y,offset)
+ local oldPos = scrollbar.Position
+
+ if y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+
+ if y > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ return (oldPos ~= scrollbar.Position)
+ end
+ local newScaleYPos = (y - scrollTrack.AbsolutePosition.y - offset)/scrollTrack.AbsoluteSize.y
+ if newScaleYPos + relativeSize > 1 then
+ newScaleYPos = 1 - relativeSize
+ scrollBottom.Value = true
+ scrollUp.Value = false
+ elseif newScaleYPos <= 0 then
+ newScaleYPos = 0
+ scrollUp.Value = true
+ scrollBottom.Value = false
+ else
+ scrollUp.Value = false
+ scrollBottom.Value = false
+ end
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,newScaleYPos,0)
+
+ return (oldPos ~= scrollbar.Position)
+ end
+
+ local function drillDownSetHighLow(instance)
+ if not instance or not instance:IsA("GuiObject") then return end
+ if instance == controlFrame then return end
+ if instance:IsDescendantOf(controlFrame) then return end
+ if not instance.Visible then return end
+
+ if lowY and lowY > instance.AbsolutePosition.Y then
+ lowY = instance.AbsolutePosition.Y
+ elseif not lowY then
+ lowY = instance.AbsolutePosition.Y
+ end
+ if highY and highY < (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ local children = instance:GetChildren()
+ for i = 1, #children do
+ drillDownSetHighLow(children[i])
+ end
+ end
+
+ local function resetHighLow()
+ local firstChildren = scrollingFrame:GetChildren()
+
+ for i = 1, #firstChildren do
+ drillDownSetHighLow(firstChildren[i])
+ end
+ end
+
+ local function recalculate()
+ internalChange = true
+
+ local percentFrame = 0
+ if scrollbar.Position.Y.Scale > 0 then
+ if scrollbar.Visible then
+ percentFrame = scrollbar.Position.Y.Scale/((scrollTrack.AbsoluteSize.Y - scrollbar.AbsoluteSize.Y)/scrollTrack.AbsoluteSize.Y)
+ else
+ percentFrame = 0
+ end
+ end
+ if percentFrame > 0.99 then percentFrame = 1 end
+
+ local hiddenYAmount = (scrollingFrame.AbsoluteSize.Y - (highY - lowY)) * percentFrame
+
+ local guiChildren = scrollingFrame:GetChildren()
+ for i = 1, #guiChildren do
+ if guiChildren[i] ~= controlFrame then
+ guiChildren[i].Position = UDim2.new(guiChildren[i].Position.X.Scale,guiChildren[i].Position.X.Offset,
+ 0, math.ceil(guiChildren[i].AbsolutePosition.Y) - math.ceil(lowY) + hiddenYAmount)
+ end
+ end
+
+ lowY = nil
+ highY = nil
+ resetHighLow()
+ internalChange = false
+ end
+
+ local function setSliderSizeAndPosition()
+ if not highY or not lowY then return end
+
+ local totalYSpan = math.abs(highY - lowY)
+ if totalYSpan == 0 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ return
+ end
+
+ local percentShown = scrollingFrame.AbsoluteSize.Y/totalYSpan
+ if percentShown >= 1 then
+ scrollbar.Visible = false
+ scrollDownButton.Visible = false
+ scrollUpButton.Visible = false
+ recalculate()
+ else
+ scrollbar.Visible = true
+ scrollDownButton.Visible = true
+ scrollUpButton.Visible = true
+
+ scrollbar.Size = UDim2.new(scrollbar.Size.X.Scale,scrollbar.Size.X.Offset,percentShown,0)
+ end
+
+ local percentPosition = (scrollingFrame.AbsolutePosition.Y - lowY)/totalYSpan
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,percentPosition,-scrollbar.AbsoluteSize.X/2)
+
+ if scrollbar.AbsolutePosition.y < scrollTrack.AbsolutePosition.y then
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,0,0)
+ end
+
+ if (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.Y) > (scrollTrack.AbsolutePosition.y + scrollTrack.AbsoluteSize.y) then
+ local relativeSize = scrollbar.AbsoluteSize.Y/scrollTrack.AbsoluteSize.Y
+ scrollbar.Position = UDim2.new(scrollbar.Position.X.Scale,scrollbar.Position.X.Offset,1 - relativeSize,0)
+ end
+ end
+
+ local buttonScrollAmountPixels = 7
+ local reentrancyGuardScrollUp = false
+ local function doScrollUp()
+ if reentrancyGuardScrollUp then return end
+
+ reentrancyGuardScrollUp = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y - buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollUp = false
+ end
+
+ local reentrancyGuardScrollDown = false
+ local function doScrollDown()
+ if reentrancyGuardScrollDown then return end
+
+ reentrancyGuardScrollDown = true
+ if positionScrollBar(0,scrollbar.AbsolutePosition.Y + buttonScrollAmountPixels,0) then
+ recalculate()
+ end
+ reentrancyGuardScrollDown = false
+ end
+
+ local function scrollUp(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollbar.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local function scrollDown(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollbar.AbsolutePosition.y + scrollbar.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ scrollbar.MouseButton1Down:connect(function(x,y)
+ if scrollbar.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollbar.AbsolutePosition.y
+ if dragCon then dragCon:disconnect() dragCon = nil end
+ if upCon then upCon:disconnect() upCon = nil end
+ local prevY = y
+ local reentrancyGuardMouseScroll = false
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ if reentrancyGuardMouseScroll then return end
+
+ reentrancyGuardMouseScroll = true
+ if positionScrollBar(x,y,mouseOffset) then
+ recalculate()
+ end
+ reentrancyGuardMouseScroll = false
+
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+ local function heightCheck(instance)
+ if highY and (instance.AbsolutePosition.Y + instance.AbsoluteSize.Y) > highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ elseif not highY then
+ highY = instance.AbsolutePosition.Y + instance.AbsoluteSize.Y
+ end
+ setSliderSizeAndPosition()
+ end
+
+ local function highLowRecheck()
+ local oldLowY = lowY
+ local oldHighY = highY
+ lowY = nil
+ highY = nil
+ resetHighLow()
+
+ if (lowY ~= oldLowY) or (highY ~= oldHighY) then
+ setSliderSizeAndPosition()
+ end
+ end
+
+ local function descendantChanged(this, prop)
+ if internalChange then return end
+ if not this.Visible then return end
+
+ if prop == "Size" or prop == "Position" then
+ wait()
+ highLowRecheck()
+ end
+ end
+
+ scrollingFrame.DescendantAdded:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+
+ if instance.Visible then
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end
+
+ descendantsChangeConMap[instance] = instance.Changed:connect(function(prop) descendantChanged(instance, prop) end)
+ end)
+
+ scrollingFrame.DescendantRemoving:connect(function(instance)
+ if not instance:IsA("GuiObject") then return end
+ if descendantsChangeConMap[instance] then
+ descendantsChangeConMap[instance]:disconnect()
+ descendantsChangeConMap[instance] = nil
+ end
+ wait() -- wait a heartbeat for sizes to reconfig
+ highLowRecheck()
+ end)
+
+ scrollingFrame.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ if not highY or not lowY then return end
+
+ highLowRecheck()
+ setSliderSizeAndPosition()
+ end
+ end)
+
+ return scrollingFrame, controlFrame
+end
+
+t.CreateScrollingFrame = function(orderList,scrollStyle)
+ local frame = Instance.new("Frame")
+ frame.Name = "ScrollingFrame"
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(1,0,1,0)
+
+ local scrollUpButton = Instance.new("ImageButton")
+ scrollUpButton.Name = "ScrollUpButton"
+ scrollUpButton.BackgroundTransparency = 1
+ scrollUpButton.Image = "rbxasset://textures/ui/scrollbuttonUp.png"
+ scrollUpButton.Size = UDim2.new(0,17,0,17)
+
+
+ local scrollDownButton = Instance.new("ImageButton")
+ scrollDownButton.Name = "ScrollDownButton"
+ scrollDownButton.BackgroundTransparency = 1
+ scrollDownButton.Image = "rbxasset://textures/ui/scrollbuttonDown.png"
+ scrollDownButton.Size = UDim2.new(0,17,0,17)
+
+ local scrollbar = Instance.new("ImageButton")
+ scrollbar.Name = "ScrollBar"
+ scrollbar.Image = "rbxasset://textures/ui/scrollbar.png"
+ scrollbar.BackgroundTransparency = 1
+ scrollbar.Size = UDim2.new(0, 18, 0, 150)
+
+ local scrollStamp = 0
+
+ local scrollDrag = Instance.new("ImageButton")
+ scrollDrag.Image = "rbxasset://ui/scrolldrag.png"
+ scrollDrag.Size = UDim2.new(1, 0, 0, 16)
+ scrollDrag.BackgroundTransparency = 1
+ scrollDrag.Name = "ScrollDrag"
+ scrollDrag.Active = true
+ scrollDrag.Parent = scrollbar
+
+ local mouseDrag = Instance.new("ImageButton")
+ mouseDrag.Active = false
+ mouseDrag.Size = UDim2.new(1.5, 0, 1.5, 0)
+ mouseDrag.AutoButtonColor = false
+ mouseDrag.BackgroundTransparency = 1
+ mouseDrag.Name = "mouseDrag"
+ mouseDrag.Position = UDim2.new(-0.25, 0, -0.25, 0)
+ mouseDrag.ZIndex = 10
+
+ local style = "simple"
+ if scrollStyle and tostring(scrollStyle) then
+ style = scrollStyle
+ end
+
+ local scrollPosition = 1
+ local rowSize = 0
+ local howManyDisplayed = 0
+
+ local layoutGridScrollBar = function()
+ howManyDisplayed = 0
+ local guiObjects = {}
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ if scrollPosition < 1 then scrollPosition = 1 end
+
+ local totalPixelsY = frame.AbsoluteSize.Y
+ local pixelsRemainingY = frame.AbsoluteSize.Y
+
+ local totalPixelsX = frame.AbsoluteSize.X
+
+ local xCounter = 0
+ local rowSizeCounter = 0
+ local setRowSize = true
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+
+ local currentRowY = 0
+
+ pos = scrollPosition
+ --count up from current scroll position to fill out grid
+ while pos <= #guiObjects and pixelsBelowScrollbar < totalPixelsY do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ --previous pos was the end of a row
+ if xCounter >= totalPixelsX then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ end
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+ pos = pos + 1
+ end
+ --Count wherever current row left off
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ currentRowY = 0
+
+ pos = scrollPosition - 1
+ xCounter = 0
+
+ --objects with varying X,Y dimensions can rarely cause minor errors
+ --rechecking every new scrollPosition is necessary to avoid 100% of errors
+
+ --count backwards from current scrollPosition to see if we can add more rows
+ while pixelsBelowScrollbar + currentRowY < totalPixelsY and pos >= 1 do
+ xCounter = xCounter + guiObjects[pos].AbsoluteSize.X
+ rowSizeCounter = rowSizeCounter + 1
+ if xCounter >= totalPixelsX then
+ rowSize = rowSizeCounter - 1
+ rowSizeCounter = 0
+ xCounter = guiObjects[pos].AbsoluteSize.X
+ if pixelsBelowScrollbar + currentRowY <= totalPixelsY then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + currentRowY
+ if scrollPosition <= rowSize then
+ scrollPosition = 1
+ break
+ else
+ scrollPosition = scrollPosition - rowSize
+ end
+ currentRowY = 0
+ else
+ break
+ end
+ end
+
+ if guiObjects[pos].AbsoluteSize.Y > currentRowY then
+ currentRowY = guiObjects[pos].AbsoluteSize.Y
+ end
+
+ pos = pos - 1
+ end
+
+ --Do check last time if pos = 0
+ if (pos == 0) and (pixelsBelowScrollbar + currentRowY <= totalPixelsY) then
+ scrollPosition = 1
+ end
+
+ xCounter = 0
+ --pos = scrollPosition
+ rowSizeCounter = 0
+ setRowSize = true
+ local lastChildSize = 0
+
+ local xOffset,yOffset = 0
+ if guiObjects[1] then
+ yOffset = math.ceil(math.floor(math.fmod(totalPixelsY,guiObjects[1].AbsoluteSize.X))/2)
+ xOffset = math.ceil(math.floor(math.fmod(totalPixelsX,guiObjects[1].AbsoluteSize.Y))/2)
+ end
+
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemainingY < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ if setRowSize then rowSizeCounter = rowSizeCounter + 1 end
+ if xCounter + child.AbsoluteSize.X >= totalPixelsX then
+ if setRowSize then
+ rowSize = rowSizeCounter - 1
+ setRowSize = false
+ end
+ xCounter = 0
+ pixelsRemainingY = pixelsRemainingY - child.AbsoluteSize.Y
+ end
+ child.Position = UDim2.new(child.Position.X.Scale,xCounter + xOffset, 0, totalPixelsY - pixelsRemainingY + yOffset)
+ xCounter = xCounter + child.AbsoluteSize.X
+ child.Visible = ((pixelsRemainingY - child.AbsoluteSize.Y) >= 0)
+ if child.Visible then
+ howManyDisplayed = howManyDisplayed + 1
+ end
+ lastChildSize = child.AbsoluteSize
+ end
+ end
+ end
+
+ scrollUpButton.Active = (scrollPosition > 1)
+ if lastChildSize == 0 then
+ scrollDownButton.Active = false
+ else
+ scrollDownButton.Active = ((pixelsRemainingY - lastChildSize.Y) < 0)
+ end
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+
+ local layoutSimpleScrollBar = function()
+ local guiObjects = {}
+ howManyDisplayed = 0
+
+ if orderList then
+ for i, child in ipairs(orderList) do
+ if child.Parent == frame then
+ table.insert(guiObjects, child)
+ end
+ end
+ else
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ table.insert(guiObjects, child)
+ end
+ end
+ end
+ end
+ if #guiObjects == 0 then
+ scrollUpButton.Active = false
+ scrollDownButton.Active = false
+ scrollDrag.Active = false
+ scrollPosition = 1
+ return
+ end
+
+ if scrollPosition > #guiObjects then
+ scrollPosition = #guiObjects
+ end
+
+ local totalPixels = frame.AbsoluteSize.Y
+ local pixelsRemaining = frame.AbsoluteSize.Y
+
+ local pixelsBelowScrollbar = 0
+ local pos = #guiObjects
+ while pixelsBelowScrollbar < totalPixels and pos >= 1 do
+ if pos >= scrollPosition then
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ else
+ if pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y <= totalPixels then
+ --It fits, so back up our scroll position
+ pixelsBelowScrollbar = pixelsBelowScrollbar + guiObjects[pos].AbsoluteSize.Y
+ if scrollPosition <= 1 then
+ scrollPosition = 1
+ break
+ else
+ --local ("Backing up ScrollPosition from -- " ..scrollPosition)
+ scrollPosition = scrollPosition - 1
+ end
+ else
+ break
+ end
+ end
+ pos = pos - 1
+ end
+
+ pos = scrollPosition
+ for i, child in ipairs(guiObjects) do
+ if i < scrollPosition then
+ --print("Hiding " .. child.Name)
+ child.Visible = false
+ else
+ if pixelsRemaining < 0 then
+ --print("Out of Space " .. child.Name)
+ child.Visible = false
+ else
+ --print("Laying out " .. child.Name)
+ --GuiObject
+ child.Position = UDim2.new(child.Position.X.Scale, child.Position.X.Offset, 0, totalPixels - pixelsRemaining)
+ pixelsRemaining = pixelsRemaining - child.AbsoluteSize.Y
+ if (pixelsRemaining >= 0) then
+ child.Visible = true
+ howManyDisplayed = howManyDisplayed + 1
+ else
+ child.Visible = false
+ end
+ end
+ end
+ end
+ scrollUpButton.Active = (scrollPosition > 1)
+ scrollDownButton.Active = (pixelsRemaining < 0)
+ scrollDrag.Active = #guiObjects > howManyDisplayed
+ scrollDrag.Visible = scrollDrag.Active
+ end
+
+
+ local moveDragger = function()
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ if not scrollDrag.Parent then return end
+
+ local dragSizeY = scrollDrag.Parent.AbsoluteSize.y * (1/(guiObjects - howManyDisplayed + 1))
+ if dragSizeY < 16 then dragSizeY = 16 end
+ scrollDrag.Size = UDim2.new(scrollDrag.Size.X.Scale,scrollDrag.Size.X.Offset,scrollDrag.Size.Y.Scale,dragSizeY)
+
+ local relativeYPos = (scrollPosition - 1)/(guiObjects - (howManyDisplayed))
+ if relativeYPos > 1 then relativeYPos = 1
+ elseif relativeYPos < 0 then relativeYPos = 0 end
+ local absYPos = 0
+
+ if relativeYPos ~= 0 then
+ absYPos = (relativeYPos * scrollbar.AbsoluteSize.y) - (relativeYPos * scrollDrag.AbsoluteSize.y)
+ end
+
+ scrollDrag.Position = UDim2.new(scrollDrag.Position.X.Scale,scrollDrag.Position.X.Offset,scrollDrag.Position.Y.Scale,absYPos)
+ end
+
+ local reentrancyGuard = false
+ local recalculate = function()
+ if reentrancyGuard then
+ return
+ end
+ reentrancyGuard = true
+ wait()
+ local success, err = nil
+ if style == "grid" then
+ success, err = pcall(function() layoutGridScrollBar() end)
+ elseif style == "simple" then
+ success, err = pcall(function() layoutSimpleScrollBar() end)
+ end
+ if not success then print(err) end
+ moveDragger()
+ reentrancyGuard = false
+ end
+
+ local doScrollUp = function()
+ scrollPosition = (scrollPosition) - rowSize
+ if scrollPosition < 1 then scrollPosition = 1 end
+ recalculate(nil)
+ end
+
+ local doScrollDown = function()
+ scrollPosition = (scrollPosition) + rowSize
+ recalculate(nil)
+ end
+
+ local scrollUp = function(mouseYPos)
+ if scrollUpButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local upCon
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ upCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollUp()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollUp()
+ if mouseYPos and mouseYPos > scrollDrag.AbsolutePosition.y then
+ break
+ end
+ if not scrollUpButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local scrollDown = function(mouseYPos)
+ if scrollDownButton.Active then
+ scrollStamp = tick()
+ local current = scrollStamp
+ local downCon
+ downCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ downCon:disconnect()
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ doScrollDown()
+ wait(0.2)
+ local t = tick()
+ local w = 0.1
+ while scrollStamp == current do
+ doScrollDown()
+ if mouseYPos and mouseYPos < (scrollDrag.AbsolutePosition.y + scrollDrag.AbsoluteSize.x) then
+ break
+ end
+ if not scrollDownButton.Active then break end
+ if tick()-t > 5 then
+ w = 0
+ elseif tick()-t > 2 then
+ w = 0.06
+ end
+ wait(w)
+ end
+ end
+ end
+
+ local y = 0
+ scrollDrag.MouseButton1Down:connect(function(x,y)
+ if scrollDrag.Active then
+ scrollStamp = tick()
+ local mouseOffset = y - scrollDrag.AbsolutePosition.y
+ local dragCon
+ local upCon
+ dragCon = mouseDrag.MouseMoved:connect(function(x,y)
+ local barAbsPos = scrollbar.AbsolutePosition.y
+ local barAbsSize = scrollbar.AbsoluteSize.y
+
+ local dragAbsSize = scrollDrag.AbsoluteSize.y
+ local barAbsOne = barAbsPos + barAbsSize - dragAbsSize
+ y = y - mouseOffset
+ y = y < barAbsPos and barAbsPos or y > barAbsOne and barAbsOne or y
+ y = y - barAbsPos
+
+ local guiObjects = 0
+ local children = frame:GetChildren()
+ if children then
+ for i, child in ipairs(children) do
+ if child:IsA("GuiObject") then
+ guiObjects = guiObjects + 1
+ end
+ end
+ end
+
+ local doublePercent = y/(barAbsSize-dragAbsSize)
+ local rowDiff = rowSize
+ local totalScrollCount = guiObjects - (howManyDisplayed - 1)
+ local newScrollPosition = math.floor((doublePercent * totalScrollCount) + 0.5) + rowDiff
+ if newScrollPosition < scrollPosition then
+ rowDiff = -rowDiff
+ end
+
+ if newScrollPosition < 1 then
+ newScrollPosition = 1
+ end
+
+ scrollPosition = newScrollPosition
+ recalculate(nil)
+ end)
+ upCon = mouseDrag.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ mouseDrag.Parent = nil
+ dragCon:disconnect(); dragCon = nil
+ upCon:disconnect(); drag = nil
+ end)
+ mouseDrag.Parent = getScreenGuiAncestor(scrollbar)
+ end
+ end)
+
+ local scrollMouseCount = 0
+
+ scrollUpButton.MouseButton1Down:connect(
+ function()
+ scrollUp()
+ end)
+ scrollUpButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+
+
+ scrollDownButton.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollDownButton.MouseButton1Down:connect(
+ function()
+ scrollDown()
+ end)
+
+ scrollbar.MouseButton1Up:connect(function()
+ scrollStamp = tick()
+ end)
+ scrollbar.MouseButton1Down:connect(
+ function(x,y)
+ if y > (scrollDrag.AbsoluteSize.y + scrollDrag.AbsolutePosition.y) then
+ scrollDown(y)
+ elseif y < (scrollDrag.AbsolutePosition.y) then
+ scrollUp(y)
+ end
+ end)
+
+
+ frame.ChildAdded:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.ChildRemoved:connect(function()
+ recalculate(nil)
+ end)
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ --Wait a heartbeat for it to sync in
+ recalculate(nil)
+ end
+ end)
+ frame.AncestryChanged:connect(function() recalculate(nil) end)
+
+ return frame, scrollUpButton, scrollDownButton, recalculate, scrollbar
+end
+local function binaryGrow(min, max, fits)
+ if min > max then
+ return min
+ end
+ local biggestLegal = min
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (biggestLegal == nil or biggestLegal < mid) then
+ biggestLegal = mid
+
+ --Try growing
+ min = mid + 1
+ else
+ --Doesn't fit, shrink
+ max = mid - 1
+ end
+ end
+ return biggestLegal
+end
+
+
+local function binaryShrink(min, max, fits)
+ if min > max then
+ return min
+ end
+ local smallestLegal = max
+
+ while min <= max do
+ local mid = min + math.floor((max - min) / 2)
+ if fits(mid) and (smallestLegal == nil or smallestLegal > mid) then
+ smallestLegal = mid
+
+ --It fits, shrink
+ max = mid - 1
+ else
+ --Doesn't fit, grow
+ min = mid + 1
+ end
+ end
+ return smallestLegal
+end
+
+
+local function getGuiOwner(instance)
+ while instance ~= nil do
+ if instance:IsA("ScreenGui") or instance:IsA("BillboardGui") then
+ return instance
+ end
+ instance = instance.Parent
+ end
+ return nil
+end
+
+t.AutoTruncateTextObject = function(textLabel)
+ local text = textLabel.Text
+
+ local fullLabel = textLabel:Clone()
+ fullLabel.Name = "Full" .. textLabel.Name
+ fullLabel.BorderSizePixel = 0
+ fullLabel.BackgroundTransparency = 0
+ fullLabel.Text = text
+ fullLabel.TextXAlignment = Enum.TextXAlignment.Center
+ fullLabel.Position = UDim2.new(0,-3,0,0)
+ fullLabel.Size = UDim2.new(0,100,1,0)
+ fullLabel.Visible = false
+ fullLabel.Parent = textLabel
+
+ local shortText = nil
+ local mouseEnterConnection = nil
+ local mouseLeaveConnection= nil
+
+ local checkForResize = function()
+ if getGuiOwner(textLabel) == nil then
+ return
+ end
+ textLabel.Text = text
+ if textLabel.TextFits then
+ --Tear down the rollover if it is active
+ if mouseEnterConnection then
+ mouseEnterConnection:disconnect()
+ mouseEnterConnection = nil
+ end
+ if mouseLeaveConnection then
+ mouseLeaveConnection:disconnect()
+ mouseLeaveConnection = nil
+ end
+ else
+ local len = string.len(text)
+ textLabel.Text = text .. "~"
+
+ --Shrink the text
+ local textSize = binaryGrow(0, len,
+ function(pos)
+ if pos == 0 then
+ textLabel.Text = "~"
+ else
+ textLabel.Text = string.sub(text, 1, pos) .. "~"
+ end
+ return textLabel.TextFits
+ end)
+ shortText = string.sub(text, 1, textSize) .. "~"
+ textLabel.Text = shortText
+
+ --Make sure the fullLabel fits
+ if not fullLabel.TextFits then
+ --Already too small, grow it really bit to start
+ fullLabel.Size = UDim2.new(0, 10000, 1, 0)
+ end
+
+ --Okay, now try to binary shrink it back down
+ local fullLabelSize = binaryShrink(textLabel.AbsoluteSize.X,fullLabel.AbsoluteSize.X,
+ function(size)
+ fullLabel.Size = UDim2.new(0, size, 1, 0)
+ return fullLabel.TextFits
+ end)
+ fullLabel.Size = UDim2.new(0,fullLabelSize+6,1,0)
+
+ --Now setup the rollover effects, if they are currently off
+ if mouseEnterConnection == nil then
+ mouseEnterConnection = textLabel.MouseEnter:connect(
+ function()
+ fullLabel.ZIndex = textLabel.ZIndex + 1
+ fullLabel.Visible = true
+ --textLabel.Text = ""
+ end)
+ end
+ if mouseLeaveConnection == nil then
+ mouseLeaveConnection = textLabel.MouseLeave:connect(
+ function()
+ fullLabel.Visible = false
+ --textLabel.Text = shortText
+ end)
+ end
+ end
+ end
+ textLabel.AncestryChanged:connect(checkForResize)
+ textLabel.Changed:connect(
+ function(prop)
+ if prop == "AbsoluteSize" then
+ checkForResize()
+ end
+ end)
+
+ checkForResize()
+
+ local function changeText(newText)
+ text = newText
+ fullLabel.Text = text
+ checkForResize()
+ end
+
+ return textLabel, changeText
+end
+
+local function TransitionTutorialPages(fromPage, toPage, transitionFrame, currentPageValue)
+ if fromPage then
+ fromPage.Visible = false
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = fromPage.Size
+ transitionFrame.Position = fromPage.Position
+ end
+ else
+ if transitionFrame.Visible == false then
+ transitionFrame.Size = UDim2.new(0.0,50,0.0,50)
+ transitionFrame.Position = UDim2.new(0.5,-25,0.5,-25)
+ end
+ end
+ transitionFrame.Visible = true
+ currentPageValue.Value = nil
+
+ local newsize, newPosition
+ if toPage then
+ --Make it visible so it resizes
+ toPage.Visible = true
+
+ newSize = toPage.Size
+ newPosition = toPage.Position
+
+ toPage.Visible = false
+ else
+ newSize = UDim2.new(0.0,50,0.0,50)
+ newPosition = UDim2.new(0.5,-25,0.5,-25)
+ end
+ transitionFrame:TweenSizeAndPosition(newSize, newPosition, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, 0.3, true,
+ function(state)
+ if state == Enum.TweenStatus.Completed then
+ transitionFrame.Visible = false
+ if toPage then
+ toPage.Visible = true
+ currentPageValue.Value = toPage
+ end
+ end
+ end)
+end
+
+t.CreateTutorial = function(name, tutorialKey, createButtons)
+ local frame = Instance.new("Frame")
+ frame.Name = "Tutorial-" .. name
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+
+ local transitionFrame = Instance.new("Frame")
+ transitionFrame.Name = "TransitionFrame"
+ transitionFrame.Style = Enum.FrameStyle.RobloxRound
+ transitionFrame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ transitionFrame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ transitionFrame.Visible = false
+ transitionFrame.Parent = frame
+
+ local currentPageValue = Instance.new("ObjectValue")
+ currentPageValue.Name = "CurrentTutorialPage"
+ currentPageValue.Value = nil
+ currentPageValue.Parent = frame
+
+ local boolValue = Instance.new("BoolValue")
+ boolValue.Name = "Buttons"
+ boolValue.Value = createButtons
+ boolValue.Parent = frame
+
+ local pages = Instance.new("Frame")
+ pages.Name = "Pages"
+ pages.BackgroundTransparency = 1
+ pages.Size = UDim2.new(1,0,1,0)
+ pages.Parent = frame
+
+ local function getVisiblePageAndHideOthers()
+ local visiblePage = nil
+ local children = pages:GetChildren()
+ if children then
+ for i,child in ipairs(children) do
+ if child.Visible then
+ if visiblePage then
+ child.Visible = false
+ else
+ visiblePage = child
+ end
+ end
+ end
+ end
+ return visiblePage
+ end
+
+ local showTutorial = function(alwaysShow)
+ if alwaysShow or UserSettings().GameSettings:GetTutorialState(tutorialKey) == false then
+ print("Showing tutorial-",tutorialKey)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ local firstPage = pages:FindFirstChild("TutorialPage1")
+ if firstPage then
+ TransitionTutorialPages(currentTutorialPage, firstPage, transitionFrame, currentPageValue)
+ else
+ error("Could not find TutorialPage1")
+ end
+ end
+ end
+
+ local dismissTutorial = function()
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+
+ if currentTutorialPage then
+ TransitionTutorialPages(currentTutorialPage, nil, transitionFrame, currentPageValue)
+ end
+
+ UserSettings().GameSettings:SetTutorialState(tutorialKey, true)
+ end
+
+ local gotoPage = function(pageNum)
+ local page = pages:FindFirstChild("TutorialPage" .. pageNum)
+ local currentTutorialPage = getVisiblePageAndHideOthers()
+ TransitionTutorialPages(currentTutorialPage, page, transitionFrame, currentPageValue)
+ end
+
+ return frame, showTutorial, dismissTutorial, gotoPage
+end
+
+local function CreateBasicTutorialPage(name, handleResize, skipTutorial, giveDoneButton)
+ local frame = Instance.new("Frame")
+ frame.Name = "TutorialPage"
+ frame.Style = Enum.FrameStyle.RobloxRound
+ frame.Size = UDim2.new(0.6, 0, 0.6, 0)
+ frame.Position = UDim2.new(0.2, 0, 0.2, 0)
+ frame.Visible = false
+
+ local frameHeader = Instance.new("TextLabel")
+ frameHeader.Name = "Header"
+ frameHeader.Text = name
+ frameHeader.BackgroundTransparency = 1
+ frameHeader.FontSize = Enum.FontSize.Size24
+ frameHeader.Font = Enum.Font.ArialBold
+ frameHeader.TextColor3 = Color3.new(1,1,1)
+ frameHeader.TextXAlignment = Enum.TextXAlignment.Center
+ frameHeader.TextWrap = true
+ frameHeader.Size = UDim2.new(1,-55, 0, 22)
+ frameHeader.Position = UDim2.new(0,0,0,0)
+ frameHeader.Parent = frame
+
+ local skipButton = Instance.new("ImageButton")
+ skipButton.Name = "SkipButton"
+ skipButton.AutoButtonColor = false
+ skipButton.BackgroundTransparency = 1
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ skipButton.MouseButton1Click:connect(function()
+ skipTutorial()
+ end)
+ skipButton.MouseEnter:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton_dn.png"
+ end)
+ skipButton.MouseLeave:connect(function()
+ skipButton.Image = "rbxasset://textures/ui/closeButton.png"
+ end)
+ skipButton.Size = UDim2.new(0, 25, 0, 25)
+ skipButton.Position = UDim2.new(1, -25, 0, 0)
+ skipButton.Parent = frame
+
+
+ if giveDoneButton then
+ local doneButton = Instance.new("TextButton")
+ doneButton.Name = "DoneButton"
+ doneButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ doneButton.Text = "Done"
+ doneButton.TextColor3 = Color3.new(1,1,1)
+ doneButton.Font = Enum.Font.ArialBold
+ doneButton.FontSize = Enum.FontSize.Size18
+ doneButton.Size = UDim2.new(0,100,0,50)
+ doneButton.Position = UDim2.new(0.5,-50,1,-50)
+
+ if skipTutorial then
+ doneButton.MouseButton1Click:connect(function() skipTutorial() end)
+ end
+
+ doneButton.Parent = frame
+ end
+
+ local innerFrame = Instance.new("Frame")
+ innerFrame.Name = "ContentFrame"
+ innerFrame.BackgroundTransparency = 1
+ innerFrame.Position = UDim2.new(0,0,0,25)
+ innerFrame.Parent = frame
+
+ local nextButton = Instance.new("TextButton")
+ nextButton.Name = "NextButton"
+ nextButton.Text = "Next"
+ nextButton.TextColor3 = Color3.new(1,1,1)
+ nextButton.Font = Enum.Font.Arial
+ nextButton.FontSize = Enum.FontSize.Size18
+ nextButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ nextButton.Size = UDim2.new(0,80, 0, 32)
+ nextButton.Position = UDim2.new(0.5, 5, 1, -32)
+ nextButton.Active = false
+ nextButton.Visible = false
+ nextButton.Parent = frame
+
+ local prevButton = Instance.new("TextButton")
+ prevButton.Name = "PrevButton"
+ prevButton.Text = "Previous"
+ prevButton.TextColor3 = Color3.new(1,1,1)
+ prevButton.Font = Enum.Font.Arial
+ prevButton.FontSize = Enum.FontSize.Size18
+ prevButton.Style = Enum.ButtonStyle.RobloxButton
+ prevButton.Size = UDim2.new(0,80, 0, 32)
+ prevButton.Position = UDim2.new(0.5, -85, 1, -32)
+ prevButton.Active = false
+ prevButton.Visible = false
+ prevButton.Parent = frame
+
+ if giveDoneButton then
+ innerFrame.Size = UDim2.new(1,0,1,-75)
+ else
+ innerFrame.Size = UDim2.new(1,0,1,-22)
+ end
+
+ local parentConnection = nil
+
+ local function basicHandleResize()
+ if frame.Visible and frame.Parent then
+ local maxSize = math.min(frame.Parent.AbsoluteSize.X, frame.Parent.AbsoluteSize.Y)
+ handleResize(200,maxSize)
+ end
+ end
+
+ frame.Changed:connect(
+ function(prop)
+ if prop == "Parent" then
+ if parentConnection ~= nil then
+ parentConnection:disconnect()
+ parentConnection = nil
+ end
+ if frame.Parent and frame.Parent:IsA("GuiObject") then
+ parentConnection = frame.Parent.Changed:connect(
+ function(parentProp)
+ if parentProp == "AbsoluteSize" then
+ wait()
+ basicHandleResize()
+ end
+ end)
+ basicHandleResize()
+ end
+ end
+
+ if prop == "Visible" then
+ basicHandleResize()
+ end
+ end)
+
+ return frame, innerFrame
+end
+
+t.CreateTextTutorialPage = function(name, text, skipTutorialFunc)
+ local frame = nil
+ local contentFrame = nil
+
+ local textLabel = Instance.new("TextLabel")
+ textLabel.BackgroundTransparency = 1
+ textLabel.TextColor3 = Color3.new(1,1,1)
+ textLabel.Text = text
+ textLabel.TextWrap = true
+ textLabel.TextXAlignment = Enum.TextXAlignment.Left
+ textLabel.TextYAlignment = Enum.TextYAlignment.Center
+ textLabel.Font = Enum.Font.Arial
+ textLabel.FontSize = Enum.FontSize.Size14
+ textLabel.Size = UDim2.new(1,0,1,0)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ frame.Size = UDim2.new(0, size, 0, size)
+ return textLabel.TextFits
+ end)
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc)
+ textLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.CreateImageTutorialPage = function(name, imageAsset, x, y, skipTutorialFunc, giveDoneButton)
+ local frame = nil
+ local contentFrame = nil
+
+ local imageLabel = Instance.new("ImageLabel")
+ imageLabel.BackgroundTransparency = 1
+ imageLabel.Image = imageAsset
+ imageLabel.Size = UDim2.new(0,x,0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2,0.5,-y/2)
+
+ local function handleResize(minSize, maxSize)
+ size = binaryShrink(minSize, maxSize,
+ function(size)
+ return size >= x and size >= y
+ end)
+ if size >= x and size >= y then
+ imageLabel.Size = UDim2.new(0,x, 0,y)
+ imageLabel.Position = UDim2.new(0.5,-x/2, 0.5, -y/2)
+ else
+ if x > y then
+ --X is limiter, so
+ imageLabel.Size = UDim2.new(1,0,y/x,0)
+ imageLabel.Position = UDim2.new(0,0, 0.5 - (y/x)/2, 0)
+ else
+ --Y is limiter
+ imageLabel.Size = UDim2.new(x/y,0,1, 0)
+ imageLabel.Position = UDim2.new(0.5-(x/y)/2, 0, 0, 0)
+ end
+ end
+ size = size + 50
+ frame.Size = UDim2.new(0, size, 0, size)
+ frame.Position = UDim2.new(0.5, -size/2, 0.5, -size/2)
+ end
+
+ frame, contentFrame = CreateBasicTutorialPage(name, handleResize, skipTutorialFunc, giveDoneButton)
+ imageLabel.Parent = contentFrame
+
+ return frame
+end
+
+t.AddTutorialPage = function(tutorial, tutorialPage)
+ local transitionFrame = tutorial.TransitionFrame
+ local currentPageValue = tutorial.CurrentTutorialPage
+
+ if not tutorial.Buttons.Value then
+ tutorialPage.NextButton.Parent = nil
+ tutorialPage.PrevButton.Parent = nil
+ end
+
+ local children = tutorial.Pages:GetChildren()
+ if children and #children > 0 then
+ tutorialPage.Name = "TutorialPage" .. (#children+1)
+ local previousPage = children[#children]
+ if not previousPage:IsA("GuiObject") then
+ error("All elements under Pages must be GuiObjects")
+ end
+
+ if tutorial.Buttons.Value then
+ if previousPage.NextButton.Active then
+ error("NextButton already Active on previousPage, please only add pages with RbxGui.AddTutorialPage function")
+ end
+ previousPage.NextButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(previousPage, tutorialPage, transitionFrame, currentPageValue)
+ end)
+ previousPage.NextButton.Active = true
+ previousPage.NextButton.Visible = true
+
+ if tutorialPage.PrevButton.Active then
+ error("PrevButton already Active on tutorialPage, please only add pages with RbxGui.AddTutorialPage function")
+ end
+ tutorialPage.PrevButton.MouseButton1Click:connect(
+ function()
+ TransitionTutorialPages(tutorialPage, previousPage, transitionFrame, currentPageValue)
+ end)
+ tutorialPage.PrevButton.Active = true
+ tutorialPage.PrevButton.Visible = true
+ end
+
+ tutorialPage.Parent = tutorial.Pages
+ else
+ --First child
+ tutorialPage.Name = "TutorialPage1"
+ tutorialPage.Parent = tutorial.Pages
+ end
+end
+
+t.CreateSetPanel = function(userIdsForSets, objectSelected, dialogClosed, size, position, showAdminCategories, useAssetVersionId)
+
+ if not userIdsForSets then
+ error("CreateSetPanel: userIdsForSets (first arg) is nil, should be a table of number ids")
+ end
+ if type(userIdsForSets) ~= "table" and type(userIdsForSets) ~= "userdata" then
+ error("CreateSetPanel: userIdsForSets (first arg) is of type " ..type(userIdsForSets) .. ", should be of type table or userdata")
+ end
+ if not objectSelected then
+ error("CreateSetPanel: objectSelected (second arg) is nil, should be a callback function!")
+ end
+ if type(objectSelected) ~= "function" then
+ error("CreateSetPanel: objectSelected (second arg) is of type " .. type(objectSelected) .. ", should be of type function!")
+ end
+ if dialogClosed and type(dialogClosed) ~= "function" then
+ error("CreateSetPanel: dialogClosed (third arg) is of type " .. type(dialogClosed) .. ", should be of type function!")
+ end
+
+ if showAdminCategories == nil then -- by default, don't show beta sets
+ showAdminCategories = false
+ end
+
+ local arrayPosition = 1
+ local insertButtons = {}
+ local insertButtonCons = {}
+ local contents = nil
+ local setGui = nil
+
+ -- used for water selections
+ local waterForceDirection = "NegX"
+ local waterForce = "None"
+ local waterGui, waterTypeChangedEvent = nil
+
+ local Data = {}
+ Data.CurrentCategory = nil
+ Data.Category = {}
+ local SetCache = {}
+
+ local userCategoryButtons = nil
+
+ local buttonWidth = 64
+ local buttonHeight = buttonWidth
+
+ local SmallThumbnailUrl = nil
+ local LargeThumbnailUrl = nil
+ local BaseUrl = game:GetService("ContentProvider").BaseUrl:lower()
+
+ if useAssetVersionId then
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&assetversionid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&assetversionid="
+ else
+ LargeThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=420&ht=420&aid="
+ SmallThumbnailUrl = BaseUrl .. "Game/Tools/ThumbnailAsset.ashx?fmt=png&wd=75&ht=75&aid="
+ end
+
+ local function drillDownSetZIndex(parent, index)
+ local children = parent:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("GuiObject") then
+ children[i].ZIndex = index
+ end
+ drillDownSetZIndex(children[i], index)
+ end
+ end
+
+ -- for terrain stamping
+ local currTerrainDropDownFrame = nil
+ local terrainShapes = {"Block","Vertical Ramp","Corner Wedge","Inverse Corner Wedge","Horizontal Ramp","Auto-Wedge"}
+ local terrainShapeMap = {}
+ for i = 1, #terrainShapes do
+ terrainShapeMap[terrainShapes[i]] = i - 1
+ end
+ terrainShapeMap[terrainShapes[#terrainShapes]] = 6
+
+ local function createWaterGui()
+ local waterForceDirections = {"NegX","X","NegY","Y","NegZ","Z"}
+ local waterForces = {"None", "Small", "Medium", "Strong", "Max"}
+
+ local waterFrame = Instance.new("Frame")
+ waterFrame.Name = "WaterFrame"
+ waterFrame.Style = Enum.FrameStyle.RobloxSquare
+ waterFrame.Size = UDim2.new(0,150,0,110)
+ waterFrame.Visible = false
+
+ local waterForceLabel = Instance.new("TextLabel")
+ waterForceLabel.Name = "WaterForceLabel"
+ waterForceLabel.BackgroundTransparency = 1
+ waterForceLabel.Size = UDim2.new(1,0,0,12)
+ waterForceLabel.Font = Enum.Font.ArialBold
+ waterForceLabel.FontSize = Enum.FontSize.Size12
+ waterForceLabel.TextColor3 = Color3.new(1,1,1)
+ waterForceLabel.TextXAlignment = Enum.TextXAlignment.Left
+ waterForceLabel.Text = "Water Force"
+ waterForceLabel.Parent = waterFrame
+
+ local waterForceDirLabel = waterForceLabel:Clone()
+ waterForceDirLabel.Name = "WaterForceDirectionLabel"
+ waterForceDirLabel.Text = "Water Force Direction"
+ waterForceDirLabel.Position = UDim2.new(0,0,0,50)
+ waterForceDirLabel.Parent = waterFrame
+
+ local waterTypeChangedEvent = Instance.new("BindableEvent",waterFrame)
+ waterTypeChangedEvent.Name = "WaterTypeChangedEvent"
+
+ local waterForceDirectionSelectedFunc = function(newForceDirection)
+ waterForceDirection = newForceDirection
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+ local waterForceSelectedFunc = function(newForce)
+ waterForce = newForce
+ waterTypeChangedEvent:Fire({waterForce, waterForceDirection})
+ end
+
+ local waterForceDirectionDropDown, forceWaterDirectionSelection = t.CreateDropDownMenu(waterForceDirections, waterForceDirectionSelectedFunc)
+ waterForceDirectionDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDirectionDropDown.Position = UDim2.new(0,0,1,3)
+ forceWaterDirectionSelection("NegX")
+ waterForceDirectionDropDown.Parent = waterForceDirLabel
+
+ local waterForceDropDown, forceWaterForceSelection = t.CreateDropDownMenu(waterForces, waterForceSelectedFunc)
+ forceWaterForceSelection("None")
+ waterForceDropDown.Size = UDim2.new(1,0,0,25)
+ waterForceDropDown.Position = UDim2.new(0,0,1,3)
+ waterForceDropDown.Parent = waterForceLabel
+
+ return waterFrame, waterTypeChangedEvent
+ end
+
+ -- Helper Function that contructs gui elements
+ local function createSetGui()
+
+ local setGui = Instance.new("ScreenGui")
+ setGui.Name = "SetGui"
+
+ local setPanel = Instance.new("Frame")
+ setPanel.Name = "SetPanel"
+ setPanel.Active = true
+ setPanel.BackgroundTransparency = 1
+ if position then
+ setPanel.Position = position
+ else
+ setPanel.Position = UDim2.new(0.2, 29, 0.1, 24)
+ end
+ if size then
+ setPanel.Size = size
+ else
+ setPanel.Size = UDim2.new(0.6, -58, 0.64, 0)
+ end
+ setPanel.Style = Enum.FrameStyle.RobloxRound
+ setPanel.ZIndex = 6
+ setPanel.Parent = setGui
+
+ -- Children of SetPanel
+ local itemPreview = Instance.new("Frame")
+ itemPreview.Name = "ItemPreview"
+ itemPreview.BackgroundTransparency = 1
+ itemPreview.Position = UDim2.new(0.8,5,0.085,0)
+ itemPreview.Size = UDim2.new(0.21,0,0.9,0)
+ itemPreview.ZIndex = 6
+ itemPreview.Parent = setPanel
+
+ -- Children of ItemPreview
+ local textPanel = Instance.new("Frame")
+ textPanel.Name = "TextPanel"
+ textPanel.BackgroundTransparency = 1
+ textPanel.Position = UDim2.new(0,0,0.45,0)
+ textPanel.Size = UDim2.new(1,0,0.55,0)
+ textPanel.ZIndex = 6
+ textPanel.Parent = itemPreview
+
+ -- Children of TextPanel
+ local rolloverText = Instance.new("TextLabel")
+ rolloverText.Name = "RolloverText"
+ rolloverText.BackgroundTransparency = 1
+ rolloverText.Size = UDim2.new(1,0,0,48)
+ rolloverText.ZIndex = 6
+ rolloverText.Font = Enum.Font.ArialBold
+ rolloverText.FontSize = Enum.FontSize.Size24
+ rolloverText.Text = ""
+ rolloverText.TextColor3 = Color3.new(1,1,1)
+ rolloverText.TextWrap = true
+ rolloverText.TextXAlignment = Enum.TextXAlignment.Left
+ rolloverText.TextYAlignment = Enum.TextYAlignment.Top
+ rolloverText.Parent = textPanel
+
+ local largePreview = Instance.new("ImageLabel")
+ largePreview.Name = "LargePreview"
+ largePreview.BackgroundTransparency = 1
+ largePreview.Image = ""
+ largePreview.Size = UDim2.new(1,0,0,170)
+ largePreview.ZIndex = 6
+ largePreview.Parent = itemPreview
+
+ local sets = Instance.new("Frame")
+ sets.Name = "Sets"
+ sets.BackgroundTransparency = 1
+ sets.Position = UDim2.new(0,0,0,5)
+ sets.Size = UDim2.new(0.23,0,1,-5)
+ sets.ZIndex = 6
+ sets.Parent = setPanel
+
+ -- Children of Sets
+ local line = Instance.new("Frame")
+ line.Name = "Line"
+ line.BackgroundColor3 = Color3.new(1,1,1)
+ line.BackgroundTransparency = 0.7
+ line.BorderSizePixel = 0
+ line.Position = UDim2.new(1,-3,0.06,0)
+ line.Size = UDim2.new(0,3,0.9,0)
+ line.ZIndex = 6
+ line.Parent = sets
+
+ local setsLists, controlFrame = t.CreateTrueScrollingFrame()
+ setsLists.Size = UDim2.new(1,-6,0.94,0)
+ setsLists.Position = UDim2.new(0,0,0.06,0)
+ setsLists.BackgroundTransparency = 1
+ setsLists.Name = "SetsLists"
+ setsLists.ZIndex = 6
+ setsLists.Parent = sets
+ drillDownSetZIndex(controlFrame, 7)
+
+ local setsHeader = Instance.new("TextLabel")
+ setsHeader.Name = "SetsHeader"
+ setsHeader.BackgroundTransparency = 1
+ setsHeader.Size = UDim2.new(0,47,0,24)
+ setsHeader.ZIndex = 6
+ setsHeader.Font = Enum.Font.ArialBold
+ setsHeader.FontSize = Enum.FontSize.Size24
+ setsHeader.Text = "Sets"
+ setsHeader.TextColor3 = Color3.new(1,1,1)
+ setsHeader.TextXAlignment = Enum.TextXAlignment.Left
+ setsHeader.TextYAlignment = Enum.TextYAlignment.Top
+ setsHeader.Parent = sets
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(1,-32,0,-2)
+ cancelButton.Size = UDim2.new(0,34,0,34)
+ cancelButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ cancelButton.ZIndex = 6
+ cancelButton.Text = ""
+ cancelButton.Modal = true
+ cancelButton.Parent = setPanel
+
+ -- Children of Cancel Button
+ local cancelImage = Instance.new("ImageLabel")
+ cancelImage.Name = "CancelImage"
+ cancelImage.BackgroundTransparency = 1
+ cancelImage.Image = "rbxasset://ui/cancel.png"
+ cancelImage.Position = UDim2.new(0,-2,0,-2)
+ cancelImage.Size = UDim2.new(0,16,0,16)
+ cancelImage.ZIndex = 6
+ cancelImage.Parent = cancelButton
+
+ return setGui
+ end
+
+ local function createSetButton(text)
+ local setButton = Instance.new("TextButton")
+
+ if text then setButton.Text = text
+ else setButton.Text = "" end
+
+ setButton.AutoButtonColor = false
+ setButton.BackgroundTransparency = 1
+ setButton.BackgroundColor3 = Color3.new(1,1,1)
+ setButton.BorderSizePixel = 0
+ setButton.Size = UDim2.new(1,-5,0,18)
+ setButton.ZIndex = 6
+ setButton.Visible = false
+ setButton.Font = Enum.Font.Arial
+ setButton.FontSize = Enum.FontSize.Size18
+ setButton.TextColor3 = Color3.new(1,1,1)
+ setButton.TextXAlignment = Enum.TextXAlignment.Left
+
+ return setButton
+ end
+
+ local function buildSetButton(name, setId, setImageId, i, count)
+ local button = createSetButton(name)
+ button.Text = name
+ button.Name = "SetButton"
+ button.Visible = true
+
+ local setValue = Instance.new("IntValue")
+ setValue.Name = "SetId"
+ setValue.Value = setId
+ setValue.Parent = button
+
+ local setName = Instance.new("StringValue")
+ setName.Name = "SetName"
+ setName.Value = name
+ setName.Parent = button
+
+ return button
+ end
+
+ local function processCategory(sets)
+ local setButtons = {}
+ local numSkipped = 0
+ for i = 1, #sets do
+ if not showAdminCategories and sets[i].Name == "Beta" then
+ numSkipped = numSkipped + 1
+ else
+ setButtons[i - numSkipped] = buildSetButton(sets[i].Name, sets[i].CategoryId, sets[i].ImageAssetId, i - numSkipped, #sets)
+ end
+ end
+ return setButtons
+ end
+
+ local function handleResize()
+ wait() -- neccessary to insure heartbeat happened
+
+ local itemPreview = setGui.SetPanel.ItemPreview
+
+ itemPreview.LargePreview.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.X)
+ itemPreview.LargePreview.Position = UDim2.new(0.5,-itemPreview.LargePreview.AbsoluteSize.X/2,0,0)
+ itemPreview.TextPanel.Position = UDim2.new(0,0,0,itemPreview.LargePreview.AbsoluteSize.Y)
+ itemPreview.TextPanel.Size = UDim2.new(1,0,0,itemPreview.AbsoluteSize.Y - itemPreview.LargePreview.AbsoluteSize.Y)
+ end
+
+ local function makeInsertAssetButton()
+ local insertAssetButtonExample = Instance.new("Frame")
+ insertAssetButtonExample.Name = "InsertAssetButtonExample"
+ insertAssetButtonExample.Position = UDim2.new(0,128,0,64)
+ insertAssetButtonExample.Size = UDim2.new(0,64,0,64)
+ insertAssetButtonExample.BackgroundTransparency = 1
+ insertAssetButtonExample.ZIndex = 6
+ insertAssetButtonExample.Visible = false
+
+ local assetId = Instance.new("IntValue")
+ assetId.Name = "AssetId"
+ assetId.Value = 0
+ assetId.Parent = insertAssetButtonExample
+
+ local assetName = Instance.new("StringValue")
+ assetName.Name = "AssetName"
+ assetName.Value = ""
+ assetName.Parent = insertAssetButtonExample
+
+ local button = Instance.new("TextButton")
+ button.Name = "Button"
+ button.Text = ""
+ button.Style = Enum.ButtonStyle.RobloxButton
+ button.Position = UDim2.new(0.025,0,0.025,0)
+ button.Size = UDim2.new(0.95,0,0.95,0)
+ button.ZIndex = 6
+ button.Parent = insertAssetButtonExample
+
+ local buttonImage = Instance.new("ImageLabel")
+ buttonImage.Name = "ButtonImage"
+ buttonImage.Image = ""
+ buttonImage.Position = UDim2.new(0,-7,0,-7)
+ buttonImage.Size = UDim2.new(1,14,1,14)
+ buttonImage.BackgroundTransparency = 1
+ buttonImage.ZIndex = 7
+ buttonImage.Parent = button
+
+ local configIcon = buttonImage:clone()
+ configIcon.Name = "ConfigIcon"
+ configIcon.Visible = false
+ configIcon.Position = UDim2.new(1,-23,1,-24)
+ configIcon.Size = UDim2.new(0,16,0,16)
+ configIcon.Image = ""
+ configIcon.ZIndex = 6
+ configIcon.Parent = insertAssetButtonExample
+
+ return insertAssetButtonExample
+ end
+
+ local function showLargePreview(insertButton)
+ if insertButton:FindFirstChild("AssetId") then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(LargeThumbnailUrl .. tostring(insertButton.AssetId.Value))
+ setGui.SetPanel.ItemPreview.LargePreview.Image = LargeThumbnailUrl .. tostring(insertButton.AssetId.Value)
+ end)
+ end
+ if insertButton:FindFirstChild("AssetName") then
+ setGui.SetPanel.ItemPreview.TextPanel.RolloverText.Text = insertButton.AssetName.Value
+ end
+ end
+
+ local function selectTerrainShape(shape)
+ if currTerrainDropDownFrame then
+ objectSelected(tostring(currTerrainDropDownFrame.AssetName.Value), tonumber(currTerrainDropDownFrame.AssetId.Value), shape)
+ end
+ end
+
+ local function createTerrainTypeButton(name, parent)
+ local dropDownTextButton = Instance.new("TextButton")
+ dropDownTextButton.Name = name .. "Button"
+ dropDownTextButton.Font = Enum.Font.ArialBold
+ dropDownTextButton.FontSize = Enum.FontSize.Size14
+ dropDownTextButton.BorderSizePixel = 0
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ dropDownTextButton.Text = name
+ dropDownTextButton.TextXAlignment = Enum.TextXAlignment.Left
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.ZIndex = parent.ZIndex + 1
+ dropDownTextButton.Size = UDim2.new(0,parent.Size.X.Offset - 2,0,16)
+ dropDownTextButton.Position = UDim2.new(0,1,0,0)
+
+ dropDownTextButton.MouseEnter:connect(function()
+ dropDownTextButton.BackgroundTransparency = 0
+ dropDownTextButton.TextColor3 = Color3.new(0,0,0)
+ end)
+
+ dropDownTextButton.MouseLeave:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ end)
+
+ dropDownTextButton.MouseButton1Click:connect(function()
+ dropDownTextButton.BackgroundTransparency = 1
+ dropDownTextButton.TextColor3 = Color3.new(1,1,1)
+ if dropDownTextButton.Parent and dropDownTextButton.Parent:IsA("GuiObject") then
+ dropDownTextButton.Parent.Visible = false
+ end
+ selectTerrainShape(terrainShapeMap[dropDownTextButton.Text])
+ end)
+
+ return dropDownTextButton
+ end
+
+ local function createTerrainDropDownMenu(zIndex)
+ local dropDown = Instance.new("Frame")
+ dropDown.Name = "TerrainDropDown"
+ dropDown.BackgroundColor3 = Color3.new(0,0,0)
+ dropDown.BorderColor3 = Color3.new(1,0,0)
+ dropDown.Size = UDim2.new(0,200,0,0)
+ dropDown.Visible = false
+ dropDown.ZIndex = zIndex
+ dropDown.Parent = setGui
+
+ for i = 1, #terrainShapes do
+ local shapeButton = createTerrainTypeButton(terrainShapes[i],dropDown)
+ shapeButton.Position = UDim2.new(0,1,0,(i - 1) * (shapeButton.Size.Y.Offset))
+ shapeButton.Parent = dropDown
+ dropDown.Size = UDim2.new(0,200,0,dropDown.Size.Y.Offset + (shapeButton.Size.Y.Offset))
+ end
+
+ dropDown.MouseLeave:connect(function()
+ dropDown.Visible = false
+ end)
+ end
+
+
+ local function createDropDownMenuButton(parent)
+ local dropDownButton = Instance.new("ImageButton")
+ dropDownButton.Name = "DropDownButton"
+ dropDownButton.Image = "rbxasset://ui/dropdownbutton.png"
+ dropDownButton.BackgroundTransparency = 1
+ dropDownButton.Size = UDim2.new(0,16,0,16)
+ dropDownButton.Position = UDim2.new(1,-24,0,6)
+ dropDownButton.ZIndex = parent.ZIndex + 2
+ dropDownButton.Parent = parent
+
+ if not setGui:FindFirstChild("TerrainDropDown") then
+ createTerrainDropDownMenu(8)
+ end
+
+ dropDownButton.MouseButton1Click:connect(function()
+ setGui.TerrainDropDown.Visible = true
+ setGui.TerrainDropDown.Position = UDim2.new(0,parent.AbsolutePosition.X,0,parent.AbsolutePosition.Y)
+ currTerrainDropDownFrame = parent
+ end)
+ end
+
+ local function buildInsertButton()
+ local insertButton = makeInsertAssetButton()
+ insertButton.Name = "InsertAssetButton"
+ insertButton.Visible = true
+
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ createDropDownMenuButton(insertButton)
+ end
+
+ local lastEnter = nil
+ local mouseEnterCon = insertButton.MouseEnter:connect(function()
+ lastEnter = insertButton
+ delay(0.1,function()
+ if lastEnter == insertButton then
+ showLargePreview(insertButton)
+ end
+ end)
+ end)
+ return insertButton, mouseEnterCon
+ end
+
+ local function realignButtonGrid(columns)
+ local x = 0
+ local y = 0
+ for i = 1, #insertButtons do
+ insertButtons[i].Position = UDim2.new(0, buttonWidth * x, 0, buttonHeight * y)
+ x = x + 1
+ if x >= columns then
+ x = 0
+ y = y + 1
+ end
+ end
+ end
+
+ local function setInsertButtonImageBehavior(insertFrame, visible, name, assetId)
+ if visible then
+ insertFrame.AssetName.Value = name
+ insertFrame.AssetId.Value = assetId
+ local newImageUrl = SmallThumbnailUrl .. assetId
+ if newImageUrl ~= insertFrame.Button.ButtonImage.Image then
+ delay(0,function()
+ game:GetService("ContentProvider"):Preload(SmallThumbnailUrl .. assetId)
+ insertFrame.Button.ButtonImage.Image = SmallThumbnailUrl .. assetId
+ end)
+ end
+ table.insert(insertButtonCons,
+ insertFrame.Button.MouseButton1Click:connect(function()
+ -- special case for water, show water selection gui
+ local isWaterSelected = (name == "Water") and (Data.Category[Data.CurrentCategory].SetName == "High Scalability")
+ waterGui.Visible = isWaterSelected
+ if isWaterSelected then
+ objectSelected(name, tonumber(assetId), nil)
+ else
+ objectSelected(name, tonumber(assetId))
+ end
+ end)
+ )
+ insertFrame.Visible = true
+ else
+ insertFrame.Visible = false
+ end
+ end
+
+ local function loadSectionOfItems(setGui, rows, columns)
+ local pageSize = rows * columns
+
+ if arrayPosition > #contents then return end
+
+ local origArrayPos = arrayPosition
+
+ local yCopy = 0
+ for i = 1, pageSize + 1 do
+ if arrayPosition >= #contents + 1 then
+ break
+ end
+
+ local buttonCon
+ insertButtons[arrayPosition], buttonCon = buildInsertButton()
+ table.insert(insertButtonCons,buttonCon)
+ insertButtons[arrayPosition].Parent = setGui.SetPanel.ItemsFrame
+ arrayPosition = arrayPosition + 1
+ end
+ realignButtonGrid(columns)
+
+ local indexCopy = origArrayPos
+ for index = origArrayPos, arrayPosition do
+ if insertButtons[index] then
+ if contents[index] then
+
+ -- we don't want water to have a drop down button
+ if contents[index].Name == "Water" then
+ if Data.Category[Data.CurrentCategory].SetName == "High Scalability" then
+ insertButtons[index]:FindFirstChild("DropDownButton",true):Destroy()
+ end
+ end
+
+ local assetId
+ if useAssetVersionId then
+ assetId = contents[index].AssetVersionId
+ else
+ assetId = contents[index].AssetId
+ end
+ setInsertButtonImageBehavior(insertButtons[index], true, contents[index].Name, assetId)
+ else
+ break
+ end
+ else
+ break
+ end
+ indexCopy = index
+ end
+ end
+
+ local function setSetIndex()
+ Data.Category[Data.CurrentCategory].Index = 0
+
+ rows = 7
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ contents = Data.Category[Data.CurrentCategory].Contents
+ if contents then
+ -- remove our buttons and their connections
+ for i = 1, #insertButtons do
+ insertButtons[i]:remove()
+ end
+ for i = 1, #insertButtonCons do
+ if insertButtonCons[i] then insertButtonCons[i]:disconnect() end
+ end
+ insertButtonCons = {}
+ insertButtons = {}
+
+ arrayPosition = 1
+ loadSectionOfItems(setGui, rows, columns)
+ end
+ end
+
+ local function selectSet(button, setName, setId, setIndex)
+ if button and Data.Category[Data.CurrentCategory] ~= nil then
+ if button ~= Data.Category[Data.CurrentCategory].Button then
+ Data.Category[Data.CurrentCategory].Button = button
+
+ if SetCache[setId] == nil then
+ SetCache[setId] = game:GetService("InsertService"):GetCollection(setId)
+ end
+ Data.Category[Data.CurrentCategory].Contents = SetCache[setId]
+
+ Data.Category[Data.CurrentCategory].SetName = setName
+ Data.Category[Data.CurrentCategory].SetId = setId
+ end
+ setSetIndex()
+ end
+ end
+
+ local function selectCategoryPage(buttons, page)
+ if buttons ~= Data.CurrentCategory then
+ if Data.CurrentCategory then
+ for key, button in pairs(Data.CurrentCategory) do
+ button.Visible = false
+ end
+ end
+
+ Data.CurrentCategory = buttons
+ if Data.Category[Data.CurrentCategory] == nil then
+ Data.Category[Data.CurrentCategory] = {}
+ if #buttons > 0 then
+ selectSet(buttons[1], buttons[1].SetName.Value, buttons[1].SetId.Value, 0)
+ end
+ else
+ Data.Category[Data.CurrentCategory].Button = nil
+ selectSet(Data.Category[Data.CurrentCategory].ButtonFrame, Data.Category[Data.CurrentCategory].SetName, Data.Category[Data.CurrentCategory].SetId, Data.Category[Data.CurrentCategory].Index)
+ end
+ end
+ end
+
+ local function selectCategory(category)
+ selectCategoryPage(category, 0)
+ end
+
+ local function resetAllSetButtonSelection()
+ local setButtons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+ for i = 1, #setButtons do
+ if setButtons[i]:IsA("TextButton") then
+ setButtons[i].Selected = false
+ setButtons[i].BackgroundTransparency = 1
+ setButtons[i].TextColor3 = Color3.new(1,1,1)
+ setButtons[i].BackgroundColor3 = Color3.new(1,1,1)
+ end
+ end
+ end
+
+ local function populateSetsFrame()
+ local currRow = 0
+ for i = 1, #userCategoryButtons do
+ local button = userCategoryButtons[i]
+ button.Visible = true
+ button.Position = UDim2.new(0,5,0,currRow * button.Size.Y.Offset)
+ button.Parent = setGui.SetPanel.Sets.SetsLists
+
+ if i == 1 then -- we will have this selected by default, so show it
+ button.Selected = true
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ end
+
+ button.MouseEnter:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 0
+ button.TextColor3 = Color3.new(0,0,0)
+ end
+ end)
+ button.MouseLeave:connect(function()
+ if not button.Selected then
+ button.BackgroundTransparency = 1
+ button.TextColor3 = Color3.new(1,1,1)
+ end
+ end)
+ button.MouseButton1Click:connect(function()
+ resetAllSetButtonSelection()
+ button.Selected = not button.Selected
+ button.BackgroundColor3 = Color3.new(0,204/255,0)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundTransparency = 0
+ selectSet(button, button.Text, userCategoryButtons[i].SetId.Value, 0)
+ end)
+
+ currRow = currRow + 1
+ end
+
+ local buttons = setGui.SetPanel.Sets.SetsLists:GetChildren()
+
+ -- set first category as loaded for default
+ if buttons then
+ for i = 1, #buttons do
+ if buttons[i]:IsA("TextButton") then
+ selectSet(buttons[i], buttons[i].Text, userCategoryButtons[i].SetId.Value, 0)
+ selectCategory(userCategoryButtons)
+ break
+ end
+ end
+ end
+ end
+
+ setGui = createSetGui()
+ waterGui, waterTypeChangedEvent = createWaterGui()
+ waterGui.Position = UDim2.new(0,55,0,0)
+ waterGui.Parent = setGui
+ setGui.Changed:connect(function(prop) -- this resizes the preview image to always be the right size
+ if prop == "AbsoluteSize" then
+ handleResize()
+ setSetIndex()
+ end
+ end)
+
+ local scrollFrame, controlFrame = t.CreateTrueScrollingFrame()
+ scrollFrame.Size = UDim2.new(0.54,0,0.85,0)
+ scrollFrame.Position = UDim2.new(0.24,0,0.085,0)
+ scrollFrame.Name = "ItemsFrame"
+ scrollFrame.ZIndex = 6
+ scrollFrame.Parent = setGui.SetPanel
+ scrollFrame.BackgroundTransparency = 1
+
+ drillDownSetZIndex(controlFrame,7)
+
+ controlFrame.Parent = setGui.SetPanel
+ controlFrame.Position = UDim2.new(0.76, 5, 0, 0)
+
+ local debounce = false
+ controlFrame.ScrollBottom.Changed:connect(function(prop)
+ if controlFrame.ScrollBottom.Value == true then
+ if debounce then return end
+ debounce = true
+ loadSectionOfItems(setGui, rows, columns)
+ debounce = false
+ end
+ end)
+
+ local userData = {}
+ for id = 1, #userIdsForSets do
+ local newUserData = game:GetService("InsertService"):GetUserSets(userIdsForSets[id])
+ if newUserData and #newUserData > 2 then
+ -- start at #3 to skip over My Decals and My Models for each account
+ for category = 3, #newUserData do
+ if newUserData[category].Name == "High Scalability" then -- we want high scalability parts to show first
+ table.insert(userData,1,newUserData[category])
+ else
+ table.insert(userData, newUserData[category])
+ end
+ end
+ end
+
+ end
+ if userData then
+ userCategoryButtons = processCategory(userData)
+ end
+
+ rows = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.Y/buttonHeight)
+ columns = math.floor(setGui.SetPanel.ItemsFrame.AbsoluteSize.X/buttonWidth)
+
+ populateSetsFrame()
+
+ insertPanelCloseCon = setGui.SetPanel.CancelButton.MouseButton1Click:connect(function()
+ setGui.SetPanel.Visible = false
+ if dialogClosed then dialogClosed() end
+ end)
+
+ local setVisibilityFunction = function(visible)
+ if visible then
+ setGui.SetPanel.Visible = true
+ else
+ setGui.SetPanel.Visible = false
+ end
+ end
+
+ local getVisibilityFunction = function()
+ if setGui then
+ if setGui:FindFirstChild("SetPanel") then
+ return setGui.SetPanel.Visible
+ end
+ end
+
+ return false
+ end
+
+ return setGui, setVisibilityFunction, getVisibilityFunction, waterTypeChangedEvent
+end
+
+t.CreateTerrainMaterialSelector = function(size,position)
+ local terrainMaterialSelectionChanged = Instance.new("BindableEvent")
+ terrainMaterialSelectionChanged.Name = "TerrainMaterialSelectionChanged"
+
+ local selectedButton = nil
+
+ local frame = Instance.new("Frame")
+ frame.Name = "TerrainMaterialSelector"
+ if size then
+ frame.Size = size
+ else
+ frame.Size = UDim2.new(0, 245, 0, 230)
+ end
+ if position then
+ frame.Position = position
+ end
+ frame.BorderSizePixel = 0
+ frame.BackgroundColor3 = Color3.new(0,0,0)
+ frame.Active = true
+
+ terrainMaterialSelectionChanged.Parent = frame
+
+ local waterEnabled = true -- todo: turn this on when water is ready
+
+ local materialToImageMap = {}
+ local materialNames = {"Grass", "Sand", "Brick", "Granite", "Asphalt", "Iron", "Aluminum", "Gold", "Plank", "Log", "Gravel", "Cinder Block", "Stone Wall", "Concrete", "Plastic (red)", "Plastic (blue)"}
+ if waterEnabled then
+ table.insert(materialNames,"Water")
+ end
+ local currentMaterial = 1
+
+ function getEnumFromName(choice)
+ if choice == "Grass" then return 1 end
+ if choice == "Sand" then return 2 end
+ if choice == "Erase" then return 0 end
+ if choice == "Brick" then return 3 end
+ if choice == "Granite" then return 4 end
+ if choice == "Asphalt" then return 5 end
+ if choice == "Iron" then return 6 end
+ if choice == "Aluminum" then return 7 end
+ if choice == "Gold" then return 8 end
+ if choice == "Plank" then return 9 end
+ if choice == "Log" then return 10 end
+ if choice == "Gravel" then return 11 end
+ if choice == "Cinder Block" then return 12 end
+ if choice == "Stone Wall" then return 13 end
+ if choice == "Concrete" then return 14 end
+ if choice == "Plastic (red)" then return 15 end
+ if choice == "Plastic (blue)" then return 16 end
+ if choice == "Water" then return 17 end
+ end
+
+ function getNameFromEnum(choice)
+ if choice == Enum.CellMaterial.Grass or choice == 1 then return "Grass"end
+ if choice == Enum.CellMaterial.Sand or choice == 2 then return "Sand" end
+ if choice == Enum.CellMaterial.Empty or choice == 0 then return "Erase" end
+ if choice == Enum.CellMaterial.Brick or choice == 3 then return "Brick" end
+ if choice == Enum.CellMaterial.Granite or choice == 4 then return "Granite" end
+ if choice == Enum.CellMaterial.Asphalt or choice == 5 then return "Asphalt" end
+ if choice == Enum.CellMaterial.Iron or choice == 6 then return "Iron" end
+ if choice == Enum.CellMaterial.Aluminum or choice == 7 then return "Aluminum" end
+ if choice == Enum.CellMaterial.Gold or choice == 8 then return "Gold" end
+ if choice == Enum.CellMaterial.WoodPlank or choice == 9 then return "Plank" end
+ if choice == Enum.CellMaterial.WoodLog or choice == 10 then return "Log" end
+ if choice == Enum.CellMaterial.Gravel or choice == 11 then return "Gravel" end
+ if choice == Enum.CellMaterial.CinderBlock or choice == 12 then return "Cinder Block" end
+ if choice == Enum.CellMaterial.MossyStone or choice == 13 then return "Stone Wall" end
+ if choice == Enum.CellMaterial.Cement or choice == 14 then return "Concrete" end
+ if choice == Enum.CellMaterial.RedPlastic or choice == 15 then return "Plastic (red)" end
+ if choice == Enum.CellMaterial.BluePlastic or choice == 16 then return "Plastic (blue)" end
+
+ if waterEnabled then
+ if choice == Enum.CellMaterial.Water or choice == 17 then return "Water" end
+ end
+ end
+
+
+ local function updateMaterialChoice(choice)
+ currentMaterial = getEnumFromName(choice)
+ terrainMaterialSelectionChanged:Fire(currentMaterial)
+ end
+
+ -- we so need a better way to do this
+ for i,v in pairs(materialNames) do
+ materialToImageMap[v] = {}
+ if v == "Grass" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Grass.png"
+ elseif v == "Sand" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Sand.png"
+ elseif v == "Brick" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Brick.png"
+ elseif v == "Granite" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Granite.png"
+ elseif v == "Asphalt" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Asphalt.png"
+ elseif v == "Iron" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Iron.png"
+ elseif v == "Aluminum" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Aluminum.png"
+ elseif v == "Gold" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Gold.png"
+ elseif v == "Plastic (red)" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/PlasticRed.png"
+ elseif v == "Plastic (blue)" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/PlasticBlue.png"
+ elseif v == "Plank" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Plank.png"
+ elseif v == "Log" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Log.png"
+ elseif v == "Gravel" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Gravel.png"
+ elseif v == "Cinder Block" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/CinderBlock.png"
+ elseif v == "Stone Wall" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/StoneWall.png"
+ elseif v == "Concrete" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Concrete.png"
+ elseif v == "Water" then materialToImageMap[v].Regular = "rbxasset://textures/terrain/Water.png"
+ else materialToImageMap[v].Regular = "rbxasset://textures/terrain/unknown.png" -- fill in the rest here!!
+ end
+ end
+
+ local scrollFrame, scrollUp, scrollDown, recalculateScroll = t.CreateScrollingFrame(nil,"grid")
+ scrollFrame.Size = UDim2.new(0.85,0,1,0)
+ scrollFrame.Position = UDim2.new(0,0,0,0)
+ scrollFrame.Parent = frame
+
+ scrollUp.Parent = frame
+ scrollUp.Visible = true
+ scrollUp.Position = UDim2.new(1,-19,0,0)
+
+ scrollDown.Parent = frame
+ scrollDown.Visible = true
+ scrollDown.Position = UDim2.new(1,-19,1,-17)
+
+ local function goToNewMaterial(buttonWrap, materialName)
+ updateMaterialChoice(materialName)
+ buttonWrap.BackgroundTransparency = 0
+ selectedButton.BackgroundTransparency = 1
+ selectedButton = buttonWrap
+ end
+
+ local function createMaterialButton(name)
+ local buttonWrap = Instance.new("TextButton")
+ buttonWrap.Text = ""
+ buttonWrap.Size = UDim2.new(0,32,0,32)
+ buttonWrap.BackgroundColor3 = Color3.new(1,1,1)
+ buttonWrap.BorderSizePixel = 0
+ buttonWrap.BackgroundTransparency = 1
+ buttonWrap.AutoButtonColor = false
+ buttonWrap.Name = tostring(name)
+
+ local imageButton = Instance.new("ImageButton")
+ imageButton.AutoButtonColor = false
+ imageButton.BackgroundTransparency = 1
+ imageButton.Size = UDim2.new(0,30,0,30)
+ imageButton.Position = UDim2.new(0,1,0,1)
+ imageButton.Name = tostring(name)
+ imageButton.Parent = buttonWrap
+ imageButton.Image = materialToImageMap[name].Regular
+
+ local enumType = Instance.new("NumberValue")
+ enumType.Name = "EnumType"
+ enumType.Parent = buttonWrap
+ enumType.Value = 0
+
+ imageButton.MouseEnter:connect(function()
+ buttonWrap.BackgroundTransparency = 0
+ end)
+ imageButton.MouseLeave:connect(function()
+ if selectedButton ~= buttonWrap then
+ buttonWrap.BackgroundTransparency = 1
+ end
+ end)
+ imageButton.MouseButton1Click:connect(function()
+ if selectedButton ~= buttonWrap then
+ goToNewMaterial(buttonWrap, tostring(name))
+ end
+ end)
+
+ return buttonWrap
+ end
+
+ for i = 1, #materialNames do
+ local imageButton = createMaterialButton(materialNames[i])
+
+ if materialNames[i] == "Grass" then -- always start with grass as the default
+ selectedButton = imageButton
+ imageButton.BackgroundTransparency = 0
+ end
+
+ imageButton.Parent = scrollFrame
+ end
+
+ local forceTerrainMaterialSelection = function(newMaterialType)
+ if not newMaterialType then return end
+ if currentMaterial == newMaterialType then return end
+
+ local matName = getNameFromEnum(newMaterialType)
+ local buttons = scrollFrame:GetChildren()
+ for i = 1, #buttons do
+ if buttons[i].Name == "Plastic (blue)" and matName == "Plastic (blue)" then goToNewMaterial(buttons[i],matName) return end
+ if buttons[i].Name == "Plastic (red)" and matName == "Plastic (red)" then goToNewMaterial(buttons[i],matName) return end
+ if string.find(buttons[i].Name, matName) then
+ goToNewMaterial(buttons[i],matName)
+ return
+ end
+ end
+ end
+
+ frame.Changed:connect(function ( prop )
+ if prop == "AbsoluteSize" then
+ recalculateScroll()
+ end
+ end)
+
+ recalculateScroll()
+ return frame, terrainMaterialSelectionChanged, forceTerrainMaterialSelection
+end
+
+t.CreateLoadingFrame = function(name,size,position)
+ game:GetService("ContentProvider"):Preload("rbxasset://ui/loadingbar.png")
+
+ local loadingFrame = Instance.new("Frame")
+ loadingFrame.Name = "LoadingFrame"
+ loadingFrame.Style = Enum.FrameStyle.RobloxRound
+
+ if size then loadingFrame.Size = size
+ else loadingFrame.Size = UDim2.new(0,300,0,160) end
+ if position then loadingFrame.Position = position
+ else loadingFrame.Position = UDim2.new(0.5, -150, 0.5,-80) end
+
+ local loadingBar = Instance.new("Frame")
+ loadingBar.Name = "LoadingBar"
+ loadingBar.BackgroundColor3 = Color3.new(0,0,0)
+ loadingBar.BorderColor3 = Color3.new(79/255,79/255,79/255)
+ loadingBar.Position = UDim2.new(0,0,0,41)
+ loadingBar.Size = UDim2.new(1,0,0,30)
+ loadingBar.Parent = loadingFrame
+
+ local loadingGreenBar = Instance.new("ImageLabel")
+ loadingGreenBar.Name = "LoadingGreenBar"
+ loadingGreenBar.Image = "rbxasset://ui/loadingbar.png"
+ loadingGreenBar.Position = UDim2.new(0,0,0,0)
+ loadingGreenBar.Size = UDim2.new(0,0,1,0)
+ loadingGreenBar.Visible = false
+ loadingGreenBar.Parent = loadingBar
+
+ local loadingPercent = Instance.new("TextLabel")
+ loadingPercent.Name = "LoadingPercent"
+ loadingPercent.BackgroundTransparency = 1
+ loadingPercent.Position = UDim2.new(0,0,1,0)
+ loadingPercent.Size = UDim2.new(1,0,0,14)
+ loadingPercent.Font = Enum.Font.Arial
+ loadingPercent.Text = "0%"
+ loadingPercent.FontSize = Enum.FontSize.Size14
+ loadingPercent.TextColor3 = Color3.new(1,1,1)
+ loadingPercent.Parent = loadingBar
+
+ local cancelButton = Instance.new("TextButton")
+ cancelButton.Name = "CancelButton"
+ cancelButton.Position = UDim2.new(0.5,-60,1,-40)
+ cancelButton.Size = UDim2.new(0,120,0,40)
+ cancelButton.Font = Enum.Font.Arial
+ cancelButton.FontSize = Enum.FontSize.Size18
+ cancelButton.TextColor3 = Color3.new(1,1,1)
+ cancelButton.Text = "Cancel"
+ cancelButton.Style = Enum.ButtonStyle.RobloxButton
+ cancelButton.Parent = loadingFrame
+
+ local loadingName = Instance.new("TextLabel")
+ loadingName.Name = "loadingName"
+ loadingName.BackgroundTransparency = 1
+ loadingName.Size = UDim2.new(1,0,0,18)
+ loadingName.Position = UDim2.new(0,0,0,2)
+ loadingName.Font = Enum.Font.Arial
+ loadingName.Text = name
+ loadingName.TextColor3 = Color3.new(1,1,1)
+ loadingName.TextStrokeTransparency = 1
+ loadingName.FontSize = Enum.FontSize.Size18
+ loadingName.Parent = loadingFrame
+
+ local cancelButtonClicked = Instance.new("BindableEvent")
+ cancelButtonClicked.Name = "CancelButtonClicked"
+ cancelButtonClicked.Parent = cancelButton
+ cancelButton.MouseButton1Click:connect(function()
+ cancelButtonClicked:Fire()
+ end)
+
+ local updateLoadingGuiPercent = function(percent, tweenAction, tweenLength)
+ if percent and type(percent) ~= "number" then
+ error("updateLoadingGuiPercent expects number as argument, got",type(percent),"instead")
+ end
+
+ local newSize = nil
+ if percent < 0 then
+ newSize = UDim2.new(0,0,1,0)
+ elseif percent > 1 then
+ newSize = UDim2.new(1,0,1,0)
+ else
+ newSize = UDim2.new(percent,0,1,0)
+ end
+
+ if tweenAction then
+ if not tweenLength then
+ error("updateLoadingGuiPercent is set to tween new percentage, but got no tween time length! Please pass this in as third argument")
+ end
+
+ if (newSize.X.Scale > 0) then
+ loadingGreenBar.Visible = true
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true)
+ else
+ loadingGreenBar:TweenSize( newSize,
+ Enum.EasingDirection.Out,
+ Enum.EasingStyle.Quad,
+ tweenLength,
+ true,
+ function()
+ if (newSize.X.Scale < 0) then
+ loadingGreenBar.Visible = false
+ end
+ end)
+ end
+
+ else
+ loadingGreenBar.Size = newSize
+ loadingGreenBar.Visible = (newSize.X.Scale > 0)
+ end
+ end
+
+ loadingGreenBar.Changed:connect(function(prop)
+ if prop == "Size" then
+ loadingPercent.Text = tostring( math.ceil(loadingGreenBar.Size.X.Scale * 100) ) .. "%"
+ end
+ end)
+
+ return loadingFrame, updateLoadingGuiPercent, cancelButtonClicked
+end
+
+t.CreatePluginFrame = function (name,size,position,scrollable,parent)
+ function createMenuButton(size,position,text,fontsize,name,parent)
+ local button = Instance.new("TextButton",parent)
+ button.AutoButtonColor = false
+ button.Name = name
+ button.BackgroundTransparency = 1
+ button.Position = position
+ button.Size = size
+ button.Font = Enum.Font.ArialBold
+ button.FontSize = fontsize
+ button.Text = text
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BorderSizePixel = 0
+ button.BackgroundColor3 = Color3.new(20/255,20/255,20/255)
+
+ button.MouseEnter:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 0
+ end)
+ button.MouseLeave:connect(function ( )
+ if button.Selected then return end
+ button.BackgroundTransparency = 1
+ end)
+
+ return button
+
+ end
+
+ local dragBar = Instance.new("Frame",parent)
+ dragBar.Name = tostring(name) .. "DragBar"
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ dragBar.BorderColor3 = Color3.new(0,0,0)
+ if size then
+ dragBar.Size = UDim2.new(size.X.Scale,size.X.Offset,0,20) + UDim2.new(0,20,0,0)
+ else
+ dragBar.Size = UDim2.new(0,183,0,20)
+ end
+ if position then
+ dragBar.Position = position
+ end
+ dragBar.Active = true
+ dragBar.Draggable = true
+ --dragBar.Visible = false
+ dragBar.MouseEnter:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(49/255,49/255,49/255)
+ end)
+ dragBar.MouseLeave:connect(function ( )
+ dragBar.BackgroundColor3 = Color3.new(39/255,39/255,39/255)
+ end)
+
+ -- plugin name label
+ local pluginNameLabel = Instance.new("TextLabel",dragBar)
+ pluginNameLabel.Name = "BarNameLabel"
+ pluginNameLabel.Text = " " .. tostring(name)
+ pluginNameLabel.TextColor3 = Color3.new(1,1,1)
+ pluginNameLabel.TextStrokeTransparency = 0
+ pluginNameLabel.Size = UDim2.new(1,0,1,0)
+ pluginNameLabel.Font = Enum.Font.ArialBold
+ pluginNameLabel.FontSize = Enum.FontSize.Size18
+ pluginNameLabel.TextXAlignment = Enum.TextXAlignment.Left
+ pluginNameLabel.BackgroundTransparency = 1
+
+ -- close button
+ local closeButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-16,0.5,-8),"X",Enum.FontSize.Size14,"CloseButton",dragBar)
+ local closeEvent = Instance.new("BindableEvent")
+ closeEvent.Name = "CloseEvent"
+ closeEvent.Parent = closeButton
+ closeButton.MouseButton1Click:connect(function ()
+ closeEvent:Fire()
+ closeButton.BackgroundTransparency = 1
+ end)
+
+ -- help button
+ local helpButton = createMenuButton(UDim2.new(0,15,0,17),UDim2.new(1,-51,0.5,-8),"?",Enum.FontSize.Size14,"HelpButton",dragBar)
+ local helpFrame = Instance.new("Frame",dragBar)
+ helpFrame.Name = "HelpFrame"
+ helpFrame.BackgroundColor3 = Color3.new(0,0,0)
+ helpFrame.Size = UDim2.new(0,300,0,552)
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ helpFrame.Active = true
+ helpFrame.BorderSizePixel = 0
+ helpFrame.Visible = false
+
+ helpButton.MouseButton1Click:connect(function( )
+ helpFrame.Visible = not helpFrame.Visible
+ if helpFrame.Visible then
+ helpButton.Selected = true
+ helpButton.BackgroundTransparency = 0
+ local screenGui = getScreenGuiAncestor(helpFrame)
+ if screenGui then
+ if helpFrame.AbsolutePosition.X + helpFrame.AbsoluteSize.X > screenGui.AbsoluteSize.X then --position on left hand side
+ helpFrame.Position = UDim2.new(0,-5 - helpFrame.AbsoluteSize.X,0,0)
+ else -- position on right hand side
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpFrame.Position = UDim2.new(1,5,0,0)
+ end
+ else
+ helpButton.Selected = false
+ helpButton.BackgroundTransparency = 1
+ end
+ end)
+
+ local minimizeButton = createMenuButton(UDim2.new(0,16,0,17),UDim2.new(1,-34,0.5,-8),"-",Enum.FontSize.Size14,"MinimizeButton",dragBar)
+ minimizeButton.TextYAlignment = Enum.TextYAlignment.Top
+
+ local minimizeFrame = Instance.new("Frame",dragBar)
+ minimizeFrame.Name = "MinimizeFrame"
+ minimizeFrame.BackgroundColor3 = Color3.new(73/255,73/255,73/255)
+ minimizeFrame.BorderColor3 = Color3.new(0,0,0)
+ minimizeFrame.Position = UDim2.new(0,0,1,0)
+ if size then
+ minimizeFrame.Size = UDim2.new(size.X.Scale,size.X.Offset,0,50) + UDim2.new(0,20,0,0)
+ else
+ minimizeFrame.Size = UDim2.new(0,183,0,50)
+ end
+ minimizeFrame.Visible = false
+
+ local minimizeBigButton = Instance.new("TextButton",minimizeFrame)
+ minimizeBigButton.Position = UDim2.new(0.5,-50,0.5,-20)
+ minimizeBigButton.Name = "MinimizeButton"
+ minimizeBigButton.Size = UDim2.new(0,100,0,40)
+ minimizeBigButton.Style = Enum.ButtonStyle.RobloxButton
+ minimizeBigButton.Font = Enum.Font.ArialBold
+ minimizeBigButton.FontSize = Enum.FontSize.Size18
+ minimizeBigButton.TextColor3 = Color3.new(1,1,1)
+ minimizeBigButton.Text = "Show"
+
+ local separatingLine = Instance.new("Frame",dragBar)
+ separatingLine.Name = "SeparatingLine"
+ separatingLine.BackgroundColor3 = Color3.new(115/255,115/255,115/255)
+ separatingLine.BorderSizePixel = 0
+ separatingLine.Position = UDim2.new(1,-18,0.5,-7)
+ separatingLine.Size = UDim2.new(0,1,0,14)
+
+ local otherSeparatingLine = separatingLine:clone()
+ otherSeparatingLine.Position = UDim2.new(1,-35,0.5,-7)
+ otherSeparatingLine.Parent = dragBar
+
+ local widgetContainer = Instance.new("Frame",dragBar)
+ widgetContainer.Name = "WidgetContainer"
+ widgetContainer.BackgroundTransparency = 1
+ widgetContainer.Position = UDim2.new(0,0,1,0)
+ widgetContainer.BorderColor3 = Color3.new(0,0,0)
+ if not scrollable then
+ widgetContainer.BackgroundTransparency = 0
+ widgetContainer.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ end
+
+ if size then
+ if scrollable then
+ widgetContainer.Size = size
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,size.Y.Scale,size.Y.Offset)
+ end
+ else
+ if scrollable then
+ widgetContainer.Size = UDim2.new(0,163,0,400)
+ else
+ widgetContainer.Size = UDim2.new(0,dragBar.AbsoluteSize.X,0,400)
+ end
+ end
+ if position then
+ widgetContainer.Position = position + UDim2.new(0,0,0,20)
+ end
+
+ local frame,control,verticalDragger = nil
+ if scrollable then
+ --frame for widgets
+ frame,control = t.CreateTrueScrollingFrame()
+ frame.Size = UDim2.new(1, 0, 1, 0)
+ frame.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ frame.BorderColor3 = Color3.new(0,0,0)
+ frame.Active = true
+ frame.Parent = widgetContainer
+ control.Parent = dragBar
+ control.BackgroundColor3 = Color3.new(72/255,72/255,72/255)
+ control.BorderSizePixel = 0
+ control.BackgroundTransparency = 0
+ control.Position = UDim2.new(1,-21,1,1)
+ if size then
+ control.Size = UDim2.new(0,21,size.Y.Scale,size.Y.Offset)
+ else
+ control.Size = UDim2.new(0,21,0,400)
+ end
+ control:FindFirstChild("ScrollDownButton").Position = UDim2.new(0,0,1,-20)
+
+ local fakeLine = Instance.new("Frame",control)
+ fakeLine.Name = "FakeLine"
+ fakeLine.BorderSizePixel = 0
+ fakeLine.BackgroundColor3 = Color3.new(0,0,0)
+ fakeLine.Size = UDim2.new(0,1,1,1)
+ fakeLine.Position = UDim2.new(1,0,0,0)
+
+ verticalDragger = Instance.new("TextButton",widgetContainer)
+ verticalDragger.ZIndex = 2
+ verticalDragger.AutoButtonColor = false
+ verticalDragger.Name = "VerticalDragger"
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ verticalDragger.BorderColor3 = Color3.new(0,0,0)
+ verticalDragger.Size = UDim2.new(1,20,0,20)
+ verticalDragger.Position = UDim2.new(0,0,1,0)
+ verticalDragger.Active = true
+ verticalDragger.Text = ""
+
+ local scrubFrame = Instance.new("Frame",verticalDragger)
+ scrubFrame.Name = "ScrubFrame"
+ scrubFrame.BackgroundColor3 = Color3.new(1,1,1)
+ scrubFrame.BorderSizePixel = 0
+ scrubFrame.Position = UDim2.new(0.5,-5,0.5,0)
+ scrubFrame.Size = UDim2.new(0,10,0,1)
+ scrubFrame.ZIndex = 5
+ local scrubTwo = scrubFrame:clone()
+ scrubTwo.Position = UDim2.new(0.5,-5,0.5,-2)
+ scrubTwo.Parent = verticalDragger
+ local scrubThree = scrubFrame:clone()
+ scrubThree.Position = UDim2.new(0.5,-5,0.5,2)
+ scrubThree.Parent = verticalDragger
+
+ local areaSoak = Instance.new("TextButton",getScreenGuiAncestor(parent))
+ areaSoak.Name = "AreaSoak"
+ areaSoak.Size = UDim2.new(1,0,1,0)
+ areaSoak.BackgroundTransparency = 1
+ areaSoak.BorderSizePixel = 0
+ areaSoak.Text = ""
+ areaSoak.ZIndex = 10
+ areaSoak.Visible = false
+ areaSoak.Active = true
+
+ local draggingVertical = false
+ local startYPos = nil
+ verticalDragger.MouseEnter:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(60/255,60/255,60/255)
+ end)
+ verticalDragger.MouseLeave:connect(function ()
+ verticalDragger.BackgroundColor3 = Color3.new(50/255,50/255,50/255)
+ end)
+ verticalDragger.MouseButton1Down:connect(function(x,y)
+ draggingVertical = true
+ areaSoak.Visible = true
+ startYPos = y
+ end)
+ areaSoak.MouseButton1Up:connect(function ( )
+ draggingVertical = false
+ areaSoak.Visible = false
+ end)
+ areaSoak.MouseMoved:connect(function(x,y)
+ if not draggingVertical then return end
+
+ local yDelta = y - startYPos
+ if not control.ScrollDownButton.Visible and yDelta > 0 then
+ return
+ end
+
+ if (widgetContainer.Size.Y.Offset + yDelta) < 150 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,150)
+ control.Size = UDim2.new (0,21,0,150)
+ return
+ end
+
+ startYPos = y
+
+ if widgetContainer.Size.Y.Offset + yDelta >= 0 then
+ widgetContainer.Size = UDim2.new(widgetContainer.Size.X.Scale, widgetContainer.Size.X.Offset,widgetContainer.Size.Y.Scale,widgetContainer.Size.Y.Offset + yDelta)
+ control.Size = UDim2.new(0,21,0,control.Size.Y.Offset + yDelta )
+ end
+ end)
+ end
+
+ local function switchMinimize()
+ minimizeFrame.Visible = not minimizeFrame.Visible
+ if scrollable then
+ frame.Visible = not frame.Visible
+ verticalDragger.Visible = not verticalDragger.Visible
+ control.Visible = not control.Visible
+ else
+ widgetContainer.Visible = not widgetContainer.Visible
+ end
+
+ if minimizeFrame.Visible then
+ minimizeButton.Text = "+"
+ else
+ minimizeButton.Text = "-"
+ end
+ end
+
+ minimizeBigButton.MouseButton1Click:connect(function ( )
+ switchMinimize()
+ end)
+
+ minimizeButton.MouseButton1Click:connect(function( )
+ switchMinimize()
+ end)
+
+ if scrollable then
+ return dragBar, frame, helpFrame, closeEvent
+ else
+ return dragBar, widgetContainer, helpFrame, closeEvent
+ end
+end
+
+t.Help =
+ function(funcNameOrFunc)
+ --input argument can be a string or a function. Should return a description (of arguments and expected side effects)
+ if funcNameOrFunc == "CreatePropertyDropDownMenu" or funcNameOrFunc == t.CreatePropertyDropDownMenu then
+ return "Function CreatePropertyDropDownMenu. " ..
+ "Arguments: (instance, propertyName, enumType). " ..
+ "Side effect: returns a container with a drop-down-box that is linked to the 'property' field of 'instance' which is of type 'enumType'"
+ end
+ if funcNameOrFunc == "CreateDropDownMenu" or funcNameOrFunc == t.CreateDropDownMenu then
+ return "Function CreateDropDownMenu. " ..
+ "Arguments: (items, onItemSelected). " ..
+ "Side effect: Returns 2 results, a container to the gui object and a 'updateSelection' function for external updating. The container is a drop-down-box created around a list of items"
+ end
+ if funcNameOrFunc == "CreateMessageDialog" or funcNameOrFunc == t.CreateMessageDialog then
+ return "Function CreateMessageDialog. " ..
+ "Arguments: (title, message, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button"
+ end
+ if funcNameOrFunc == "CreateStyledMessageDialog" or funcNameOrFunc == t.CreateStyledMessageDialog then
+ return "Function CreateStyledMessageDialog. " ..
+ "Arguments: (title, message, style, buttons). " ..
+ "Side effect: Returns a gui object of a message box with 'title' and 'message' as passed in. 'buttons' input is an array of Tables contains a 'Text' and 'Function' field for the text/callback of each button, 'style' is a string, either Error, Notify or Confirm"
+ end
+ if funcNameOrFunc == "GetFontHeight" or funcNameOrFunc == t.GetFontHeight then
+ return "Function GetFontHeight. " ..
+ "Arguments: (font, fontSize). " ..
+ "Side effect: returns the size in pixels of the given font + fontSize"
+ end
+ if funcNameOrFunc == "LayoutGuiObjects" or funcNameOrFunc == t.LayoutGuiObjects then
+
+ end
+ if funcNameOrFunc == "CreateScrollingFrame" or funcNameOrFunc == t.CreateScrollingFrame then
+ return "Function CreateScrollingFrame. " ..
+ "Arguments: (orderList, style) " ..
+ "Side effect: returns 4 objects, (scrollFrame, scrollUpButton, scrollDownButton, recalculateFunction). 'scrollFrame' can be filled with GuiObjects. It will lay them out and allow scrollUpButton/scrollDownButton to interact with them. Orderlist is optional (and specifies the order to layout the children. Without orderlist, it uses the children order. style is also optional, and allows for a 'grid' styling if style is passed 'grid' as a string. recalculateFunction can be called when a relayout is needed (when orderList changes)"
+ end
+ if funcNameOrFunc == "CreateTrueScrollingFrame" or funcNameOrFunc == t.CreateTrueScrollingFrame then
+ return "Function CreateTrueScrollingFrame. " ..
+ "Arguments: (nil) " ..
+ "Side effect: returns 2 objects, (scrollFrame, controlFrame). 'scrollFrame' can be filled with GuiObjects, and they will be clipped if not inside the frame's bounds. controlFrame has children scrollup and scrolldown, as well as a slider. controlFrame can be parented to any guiobject and it will readjust itself to fit."
+ end
+ if funcNameOrFunc == "AutoTruncateTextObject" or funcNameOrFunc == t.AutoTruncateTextObject then
+ return "Function AutoTruncateTextObject. " ..
+ "Arguments: (textLabel) " ..
+ "Side effect: returns 2 objects, (textLabel, changeText). The 'textLabel' input is modified to automatically truncate text (with ellipsis), if it gets too small to fit. 'changeText' is a function that can be used to change the text, it takes 1 string as an argument"
+ end
+ if funcNameOrFunc == "CreateSlider" or funcNameOrFunc == t.CreateSlider then
+ return "Function CreateSlider. " ..
+ "Arguments: (steps, width, position) " ..
+ "Side effect: returns 2 objects, (sliderGui, sliderPosition). The 'steps' argument specifies how many different positions the slider can hold along the bar. 'width' specifies in pixels how wide the bar should be (modifiable afterwards if desired). 'position' argument should be a UDim2 for slider positioning. 'sliderPosition' is an IntValue whose current .Value specifies the specific step the slider is currently on."
+ end
+ if funcNameOrFunc == "CreateLoadingFrame" or funcNameOrFunc == t.CreateLoadingFrame then
+ return "Function CreateLoadingFrame. " ..
+ "Arguments: (name, size, position) " ..
+ "Side effect: Creates a gui that can be manipulated to show progress for a particular action. Name appears above the loading bar, and size and position are udim2 values (both size and position are optional arguments). Returns 3 arguments, the first being the gui created. The second being updateLoadingGuiPercent, which is a bindable function. This function takes one argument (two optionally), which should be a number between 0 and 1, representing the percentage the loading gui should be at. The second argument to this function is a boolean value that if set to true will tween the current percentage value to the new percentage value, therefore our third argument is how long this tween should take. Our third returned argument is a BindableEvent, that when fired means that someone clicked the cancel button on the dialog."
+ end
+ if funcNameOrFunc == "CreateTerrainMaterialSelector" or funcNameOrFunc == t.CreateTerrainMaterialSelector then
+ return "Function CreateTerrainMaterialSelector. " ..
+ "Arguments: (size, position) " ..
+ "Side effect: Size and position are UDim2 values that specifies the selector's size and position. Both size and position are optional arguments. This method returns 3 objects (terrainSelectorGui, terrainSelected, forceTerrainSelection). terrainSelectorGui is just the gui object that we generate with this function, parent it as you like. TerrainSelected is a BindableEvent that is fired whenever a new terrain type is selected in the gui. ForceTerrainSelection is a function that takes an argument of Enum.CellMaterial and will force the gui to show that material as currently selected."
+ end
+ end
+
+--RBXGUI END
+
+
+--rbxsig%mno74b/wRJKHL8Xt9/BxwXVZl+tc9a/CmKlTTsWwuH0ibb5lbU57AjhmG/j/sFf+k7yKL9GKKWCUdPSSH3I6N4Vg02Ru5DtokfUAKrgAAdixtQU0mSgGT3ZI/vNZjH7Dw39RzLgT4rVVyCh38B/pVg0BKcE3SdIXVdeIRPX0cb8=%
+--rbxassetid%53878053%
+
+-- A couple of necessary functions
+local function waitForChild(instance, name)
+ while not instance:FindFirstChild(name) do
+ instance.ChildAdded:wait()
+ end
+end
+local function waitForProperty(instance, property)
+ while not instance[property] do
+ instance.Changed:wait()
+ end
+end
+
+waitForChild(game,"Players")
+waitForProperty(game.Players,"LocalPlayer")
+local player = game.Players.LocalPlayer
+
+local RbxGui,msg = t
+if not RbxGui then print("could not find RbxGui!") return end
+
+--- Begin Locals
+waitForChild(game,"Players")
+
+-- don't do anything if we are in an empty game
+if #game.Players:GetChildren() < 1 then
+ game.Players.ChildAdded:wait()
+end
+
+local tilde = "~"
+local backquote = "`"
+game:GetService("GuiService"):AddKey(tilde) -- register our keys
+game:GetService("GuiService"):AddKey(backquote)
+
+local player = game.Players.LocalPlayer
+
+local backpack = script.Parent
+local screen = script.Parent.Parent
+
+local openCloseDebounce = false
+
+local backpackItems = {}
+
+local buttons = {}
+
+local debounce = false
+
+local guiTweenSpeed = 1
+
+local backpackOldStateVisible = false
+local browsingMenu = false
+
+local mouseEnterCons = {}
+local mouseClickCons = {}
+
+local characterChildAddedCon = nil
+local characterChildRemovedCon = nil
+local backpackAddCon = nil
+local humanoidDiedCon = nil
+local backpackButtonClickCon = nil
+local guiServiceKeyPressCon = nil
+
+local currentLoadout = backpack.Parent.CurrentLoadout
+local swapSlot = script.Parent.SwapSlot
+local grid = script.Parent.Gear.GearGrid
+local scroller = backpack.Gear.GearGridScrollingArea
+local gearPreview = backpack.Gear.GearPreview
+local playerBackpack = player.Backpack
+local currentLoadout = backpack.Parent.CurrentLoadout
+local backpackButton = backpack.Parent.ControlFrame.BackpackButton
+local gearButton = backpack.Gear.GearGrid.GearButton
+local searchBox = backpack.SearchFrame.SearchBoxFrame.SearchBox
+local searchButton = backpack.SearchFrame.SearchButton
+local gearPreview = backpack.Gear.GearPreview
+local resetButton = backpack.SearchFrame.ResetButton
+
+
+
+-- creating scroll bar early as to make sure items get placed correctly
+local scrollFrame, scrollUp, scrollDown, recalculateScroll = RbxGui.CreateScrollingFrame(nil,"grid")
+
+scrollFrame.Position = UDim2.new(0,0,0,30)
+scrollFrame.Size = UDim2.new(1,0,1,-30)
+scrollFrame.Parent = grid
+
+local scrollBar = Instance.new("Frame")
+scrollBar.Name = "ScrollBar"
+scrollBar.BackgroundTransparency = 0.9
+scrollBar.BackgroundColor3 = Color3.new(1,1,1)
+scrollBar.BorderSizePixel = 0
+scrollBar.Size = UDim2.new(0, 17, 1, -36)
+scrollBar.Position = UDim2.new(0,0,0,18)
+scrollBar.Parent = scroller
+
+scrollDown.Position = UDim2.new(0,0,1,-17)
+
+scrollUp.Parent = scroller
+scrollDown.Parent = scroller
+
+local scrollFrameLoadout, scrollUpLoadout, scrollDownLoadout, recalculateScrollLoadout = RbxGui.CreateScrollingFrame()
+
+scrollFrameLoadout.Position = UDim2.new(0,0,0,0)
+scrollFrameLoadout.Size = UDim2.new(1,0,1,0)
+scrollFrameLoadout.Parent = backpack.Gear.GearLoadouts.LoadoutsList
+
+local LoadoutButton = Instance.new("TextButton")
+LoadoutButton.Name = "LoadoutButton"
+LoadoutButton.Font = Enum.Font.ArialBold
+LoadoutButton.FontSize = Enum.FontSize.Size14
+LoadoutButton.Position = UDim2.new(0,0,0,0)
+LoadoutButton.Size = UDim2.new(1,0,0,32)
+LoadoutButton.Style = Enum.ButtonStyle.RobloxButton
+LoadoutButton.Text = "Loadout #1"
+LoadoutButton.TextColor3 = Color3.new(1,1,1)
+LoadoutButton.Parent = scrollFrameLoadout
+
+local LoadoutButtonTwo = LoadoutButton:clone()
+LoadoutButtonTwo.Text = "Loadout #2"
+LoadoutButtonTwo.Parent = scrollFrameLoadout
+
+local LoadoutButtonThree = LoadoutButton:clone()
+LoadoutButtonThree.Text = "Loadout #3"
+LoadoutButtonThree.Parent = scrollFrameLoadout
+
+local LoadoutButtonFour = LoadoutButton:clone()
+LoadoutButtonFour.Text = "Loadout #4"
+LoadoutButtonFour.Parent = scrollFrameLoadout
+
+local scrollBarLoadout = Instance.new("Frame")
+scrollBarLoadout.Name = "ScrollBarLoadout"
+scrollBarLoadout.BackgroundTransparency = 0.9
+scrollBarLoadout.BackgroundColor3 = Color3.new(1,1,1)
+scrollBarLoadout.BorderSizePixel = 0
+scrollBarLoadout.Size = UDim2.new(0, 17, 1, -36)
+scrollBarLoadout.Position = UDim2.new(0,0,0,18)
+scrollBarLoadout.Parent = backpack.Gear.GearLoadouts.GearLoadoutsScrollingArea
+
+scrollDownLoadout.Position = UDim2.new(0,0,1,-17)
+
+scrollUpLoadout.Parent = script.Parent.Gear.GearLoadouts.GearLoadoutsScrollingArea
+scrollDownLoadout.Parent = script.Parent.Gear.GearLoadouts.GearLoadoutsScrollingArea
+
+
+-- Begin Functions
+function removeFromMap(map,object)
+ for i = 1, #map do
+ if map[i] == object then
+ table.remove(map,i)
+ break
+ end
+ end
+end
+
+function robloxLock(instance)
+end
+
+function resize()
+ local size = 0
+ if gearPreview.AbsoluteSize.Y > gearPreview.AbsoluteSize.X then
+ size = gearPreview.AbsoluteSize.X * 0.75
+ else
+ size = gearPreview.AbsoluteSize.Y * 0.75
+ end
+
+ gearPreview.GearImage.Size = UDim2.new(0,size,0,size)
+ gearPreview.GearImage.Position = UDim2.new(0,gearPreview.AbsoluteSize.X/2 - size/2,0.75,-size)
+
+ resizeGrid()
+end
+
+function addToGrid(child)
+ if not child:IsA("Tool") then
+ if not child:IsA("HopperBin") then
+ return
+ end
+ end
+ if child:FindFirstChild("RobloxBuildTool") then return end
+
+ for i,v in pairs(backpackItems) do -- check to see if we already have this gear registered
+ if v == child then return end
+ end
+
+ table.insert(backpackItems,child)
+
+ local changeCon = child.Changed:connect(function(prop)
+ if prop == "Name" then
+ if buttons[child] then
+ if buttons[child].Image == "" then
+ buttons[child].GearText.Text = child.Name
+ end
+ end
+ end
+ end)
+ local ancestryCon = nil
+ ancestryCon = child.AncestryChanged:connect(function(theChild,theParent)
+ local thisObject = nil
+ for k,v in pairs(backpackItems) do
+ if v == child then
+ thisObject = v
+ break
+ end
+ end
+
+ waitForProperty(player,"Character")
+ waitForChild(player,"Backpack")
+ if (child.Parent ~= player.Backpack and child.Parent ~= player.Character) then
+ if ancestryCon then ancestryCon:disconnect() end
+ if changeCon then changeCon:disconnect() end
+
+ for k,v in pairs(backpackItems) do
+ if v == thisObject then
+ if mouseEnterCons[buttons[v]] then mouseEnterCons[buttons[v]]:disconnect() end
+ if mouseClickCons[buttons[v]] then mouseClickCons[buttons[v]]:disconnect() end
+ buttons[v].Parent = nil
+ buttons[v] = nil
+ break
+ end
+ end
+
+ removeFromMap(backpackItems,thisObject)
+
+ resizeGrid()
+ else
+ resizeGrid()
+ end
+ updateGridActive()
+ end)
+ resizeGrid()
+end
+
+function buttonClick(button)
+ if button:FindFirstChild("UnequipContextMenu") and not button.Active then
+ button.UnequipContextMenu.Visible = true
+ browsingMenu = true
+ end
+end
+
+function previewGear(button)
+ if not browsingMenu then
+ gearPreview.GearImage.Image = button.Image
+ gearPreview.GearStats.GearName.Text = button.GearReference.Value.Name
+ end
+end
+
+function checkForSwap(button,x,y)
+ local loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
+ if x >= loadoutChildren[i].AbsolutePosition.x and x <= (loadoutChildren[i].AbsolutePosition.x + loadoutChildren[i].AbsoluteSize.x) then
+ if y >= loadoutChildren[i].AbsolutePosition.y and y <= (loadoutChildren[i].AbsolutePosition.y + loadoutChildren[i].AbsoluteSize.y) then
+ local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
+ swapGearSlot(slot,button)
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+function resizeGrid()
+ for k,v in pairs(backpackItems) do
+ if not v:FindFirstChild("RobloxBuildTool") then
+ if not buttons[v] then
+ local buttonClone = gearButton:clone()
+ buttonClone.Parent = grid.ScrollingFrame
+ buttonClone.Visible = true
+ buttonClone.Image = v.TextureId
+ if buttonClone.Image == "" then
+ buttonClone.GearText.Text = v.Name
+ end
+ buttonClone.GearReference.Value = v
+ buttonClone.Draggable = true
+ buttons[v] = buttonClone
+
+ local unequipMenu = getGearContextMenu()
+
+ unequipMenu.Visible = false
+ unequipMenu.Parent = buttonClone
+
+ local beginPos = nil
+ buttonClone.DragBegin:connect(function(value)
+ buttonClone.ZIndex = 9
+ beginPos = value
+ end)
+ buttonClone.DragStopped:connect(function(x,y)
+ if beginPos ~= buttonClone.Position then
+ buttonClone.ZIndex = 1
+ if not checkForSwap(buttonClone,x,y) then
+ buttonClone:TweenPosition(beginPos,Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.5, true)
+ else
+ buttonClone.Position = beginPos
+ end
+ end
+ end)
+
+ mouseEnterCons[buttonClone] = buttonClone.MouseEnter:connect(function() previewGear(buttonClone) end)
+ mouseClickCons[buttonClone] = buttonClone.MouseButton1Click:connect(function() buttonClick(buttonClone) end)
+ end
+ end
+ end
+ recalculateScroll()
+end
+
+function showPartialGrid(subset)
+
+
+ for k,v in pairs(buttons) do
+ v.Parent = nil
+ end
+ for k,v in pairs(subset) do
+ v.Parent = grid.ScrollingFrame
+ end
+ recalculateScroll()
+end
+
+function showEntireGrid()
+
+ for k,v in pairs(buttons) do
+ v.Parent = grid.ScrollingFrame
+ end
+ recalculateScroll()
+end
+
+function inLoadout(gear)
+ local children = currentLoadout:GetChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ local button = children[i]:GetChildren()
+ if #button > 0 then
+ if button[1].GearReference.Value and button[1].GearReference.Value == gear then
+ return true
+ end
+ end
+ end
+ end
+ return false
+end
+
+function updateGridActive()
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ local gear = nil
+ local gearRef = buttons[v]:FindFirstChild("GearReference")
+
+ if gearRef then gear = gearRef.Value end
+
+ if not gear then
+ buttons[v].Active = false
+ elseif inLoadout(gear) then
+ buttons[v].Active = false
+ else
+ buttons[v].Active = true
+ end
+ end
+ end
+end
+
+function centerGear(loadoutChildren)
+ local gearButtons = {}
+ local lastSlotAdd = nil
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and #loadoutChildren[i]:GetChildren() > 0 then
+ if loadoutChildren[i].Name == "Slot0" then
+ lastSlotAdd = loadoutChildren[i]
+ else
+ table.insert(gearButtons, loadoutChildren[i])
+ end
+ end
+ end
+ if lastSlotAdd then table.insert(gearButtons,lastSlotAdd) end
+
+ local startPos = ( 1 - (#gearButtons * 0.1) ) / 2
+ for i = 1, #gearButtons do
+ gearButtons[i]:TweenPosition(UDim2.new(startPos + ((i - 1) * 0.1),0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
+ end
+end
+
+function spreadOutGear(loadoutChildren)
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ local slot = tonumber(string.sub(loadoutChildren[i].Name,5))
+ if slot == 0 then slot = 10 end
+ loadoutChildren[i]:TweenPosition(UDim2.new((slot - 1)/10,0,0,0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.25, true)
+ end
+ end
+end
+
+function openCloseBackpack()
+ if backpack.Visible == true then
+ updateGridActive()
+
+ loadoutChildren = currentLoadout:GetChildren()
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ loadoutChildren[i].BackgroundTransparency = 0.5
+ end
+ end
+ spreadOutGear(loadoutChildren)
+
+ --[[backpackButton.Selected = true
+ backpack:TweenSizeAndPosition(UDim2.new(0.55, 0, 0.6, 0),UDim2.new(0.225, 0, 0.2, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed/2, true)
+ delay(guiTweenSpeed/2 + 0.01,
+ function()--]]
+ local children = backpack:getChildren()
+ for i = 1, #children do
+ if children[i]:IsA("Frame") then
+ children[i].Visible = true
+ end
+ end
+ resizeGrid()
+ resize()
+ openCloseDebounce = false
+
+
+ end
+end
+
+function loadoutCheck(child, selectState)
+ if not child:IsA("ImageButton") then return end
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ if child:FindFirstChild("GearReference") then
+ if buttons[v].GearReference.Value == child.GearReference.Value then
+ buttons[v].Active = selectState
+ break
+ end
+ end
+ end
+ end
+end
+
+function clearPreview()
+ gearPreview.GearImage.Image = ""
+ gearPreview.GearStats.GearName.Text = ""
+end
+
+function removeAllEquippedGear(physGear)
+ local stuff = player.Character:GetChildren()
+ for i = 1, #stuff do
+ if ( stuff[i]:IsA("Tool") or stuff[i]:IsA("HopperBin") ) and stuff[i] ~= physGear then
+ stuff[i].Parent = playerBackpack
+ end
+ end
+end
+
+function equipGear(physGear)
+ removeAllEquippedGear(physGear)
+ physGear.Parent = player.Character
+ updateGridActive()
+end
+
+function unequipGear(physGear)
+ physGear.Parent = playerBackpack
+ updateGridActive()
+end
+
+function highlight(button)
+ button.TextColor3 = Color3.new(0,0,0)
+ button.BackgroundColor3 = Color3.new(0.8,0.8,0.8)
+end
+function clearHighlight(button)
+ button.TextColor3 = Color3.new(1,1,1)
+ button.BackgroundColor3 = Color3.new(0,0,0)
+end
+
+function swapGearSlot(slot,gearButton)
+ if not swapSlot.Value then -- signal loadout to swap a gear out
+ swapSlot.Slot.Value = slot
+ swapSlot.GearButton.Value = gearButton
+ swapSlot.Value = true
+ updateGridActive()
+ end
+end
+
+
+local UnequipGearMenuClick = function(element, menu)
+ if type(element.Action) ~= "number" then return end
+ local num = element.Action
+ if num == 1 then -- remove from loadout
+ unequipGear(menu.Parent.GearReference.Value)
+ local inventoryButton = menu.Parent
+ local gearToUnequip = inventoryButton.GearReference.Value
+ local loadoutChildren = currentLoadout:GetChildren()
+ local slot = -1
+ for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") then
+ local button = loadoutChildren[i]:GetChildren()
+ if button[1] and button[1].GearReference.Value == gearToUnequip then
+ slot = button[1].SlotNumber.Text
+ break
+ end
+ end
+ end
+ swapGearSlot(slot,nil)
+ end
+end
+
+-- these next two functions are used to stop any use of backpack while the player is dead (can cause issues)
+function activateBackpack()
+ backpack.Visible = backpackOldStateVisible
+
+ backpackButtonClickCon = backpackButton.MouseButton1Click:connect(function() openCloseBackpack() end)
+ guiServiceKeyPressCon = game:GetService("GuiService").KeyPressed:connect(function(key)
+ if key == tilde or key == backquote then
+ openCloseBackpack()
+ end
+ end)
+end
+function deactivateBackpack()
+ if backpackButtonClickCon then backpackButtonClickCon:disconnect() end
+ if guiServiceKeyPressCon then guiServiceKeyPressCon:disconnect() end
+
+ backpackOldStateVisible = backpack.Visible
+ backpack.Visible = false
+end
+
+function setupCharacterConnections()
+
+ if backpackAddCon then backpackAddCon:disconnect() end
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+
+ -- make sure we get all the children
+ local backpackChildren = game.Players.LocalPlayer.Backpack:GetChildren()
+ for i = 1, #backpackChildren do
+ addToGrid(backpackChildren[i])
+ end
+
+ if characterChildAddedCon then characterChildAddedCon:disconnect() end
+ characterChildAddedCon =
+ game.Players.LocalPlayer.Character.ChildAdded:connect(function(child)
+ addToGrid(child)
+ updateGridActive()
+ end)
+
+ if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
+ characterChildRemovedCon =
+ game.Players.LocalPlayer.Character.ChildRemoved:connect(function(child)
+ updateGridActive()
+ end)
+
+
+ if humanoidDiedCon then humanoidDiedCon:disconnect() end
+ local localPlayer = game.Players.LocalPlayer
+ waitForProperty(localPlayer,"Character")
+ waitForChild(localPlayer.Character,"Humanoid")
+ humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(function() deactivateBackpack() end)
+
+ activateBackpack()
+end
+
+function removeCharacterConnections()
+ if characterChildAddedCon then characterChildAddedCon:disconnect() end
+ if characterChildRemovedCon then characterChildRemovedCon:disconnect() end
+ if backpackAddCon then backpackAddCon:disconnect() end
+end
+
+function trim(s)
+ return (s:gsub("^%s*(.-)%s*$", "%1"))
+end
+
+function splitByWhiteSpace(text)
+ if type(text) ~= "string" then return nil end
+
+ local terms = {}
+ for token in string.gmatch(text, "[^%s]+") do
+ if string.len(token) > 2 then
+ table.insert(terms,token)
+ end
+ end
+ return terms
+end
+
+function filterGear(searchTerm)
+ string.lower(searchTerm)
+ searchTerm = trim(searchTerm)
+ if string.len(searchTerm) < 2 then return nil end
+ local terms = splitByWhiteSpace(searchTerm)
+
+ local filteredGear = {}
+ for k,v in pairs(backpackItems) do
+ if buttons[v] then
+ local gearString = string.lower(buttons[v].GearReference.Value.Name)
+ gearString = trim(gearString)
+ for i = 1, #terms do
+ if string.match(gearString,terms[i]) then
+ table.insert(filteredGear,buttons[v])
+ break
+ end
+ end
+ end
+ end
+
+ return filteredGear
+end
+
+
+function showSearchGear()
+ local searchBox = backpack.SearchFrame.SearchBoxFrame.SearchBox
+ local searchText = searchBox.Text
+ searchBox.Text = "Search..."
+ local filteredButtons = filterGear(searchText)
+ if filteredButtons and #filteredButtons > 0 then
+ showPartialGrid(filteredButtons)
+ else
+ showEntireGrid()
+ end
+end
+
+function nukeBackpack()
+ while #buttons > 0 do
+ table.remove(buttons)
+ end
+ buttons = {}
+ while #backpackItems > 0 do
+ table.remove(backpackItems)
+ end
+ backpackItems = {}
+ local scrollingFrameChildren = grid.ScrollingFrame:GetChildren()
+ for i = 1, #scrollingFrameChildren do
+ scrollingFrameChildren[i]:remove()
+ end
+end
+
+function getGearContextMenu()
+ local gearContextMenu = Instance.new("Frame")
+ gearContextMenu.Active = true
+ gearContextMenu.Name = "UnequipContextMenu"
+ gearContextMenu.Size = UDim2.new(0,115,0,70)
+ gearContextMenu.Position = UDim2.new(0,-16,0,-16)
+ gearContextMenu.BackgroundTransparency = 1
+ gearContextMenu.Visible = false
+
+ local gearContextMenuButton = Instance.new("TextButton")
+ gearContextMenuButton.Name = "UnequipContextMenuButton"
+ gearContextMenuButton.Text = ""
+ gearContextMenuButton.Style = Enum.ButtonStyle.RobloxButtonDefault
+ gearContextMenuButton.ZIndex = 4
+ gearContextMenuButton.Size = UDim2.new(1, 0, 1, -20)
+ gearContextMenuButton.Visible = true
+ gearContextMenuButton.Parent = gearContextMenu
+
+ local elementHeight = 12
+
+ local contextMenuElements = {}
+ local contextMenuElementsName = {"Remove Hotkey"}
+
+ for i = 1, #contextMenuElementsName do
+ local element = {}
+ element.Type = "Button"
+ element.Text = contextMenuElementsName[i]
+ element.Action = i
+ element.DoIt = UnequipGearMenuClick
+ table.insert(contextMenuElements,element)
+ end
+
+ for i, contextElement in ipairs(contextMenuElements) do
+ local element = contextElement
+ if element.Type == "Button" then
+ local button = Instance.new("TextButton")
+ button.Name = "UnequipContextButton" .. i
+ button.BackgroundColor3 = Color3.new(0,0,0)
+ button.BorderSizePixel = 0
+ button.TextXAlignment = Enum.TextXAlignment.Left
+ button.Text = " " .. contextElement.Text
+ button.Font = Enum.Font.Arial
+ button.FontSize = Enum.FontSize.Size14
+ button.Size = UDim2.new(1, 8, 0, elementHeight)
+ button.Position = UDim2.new(0,0,0,elementHeight * i)
+ button.TextColor3 = Color3.new(1,1,1)
+ button.ZIndex = 4
+ button.Parent = gearContextMenuButton
+
+ button.MouseButton1Click:connect(function()
+ if button.Active and not gearContextMenu.Parent.Active then
+ local success, result = pcall(function() element.DoIt(element, gearContextMenu) end)
+ browsingMenu = false
+ gearContextMenu.Visible = false
+ clearHighlight(button)
+ clearPreview()
+ end
+ end)
+
+ button.MouseEnter:connect(function()
+ if button.Active and gearContextMenu.Parent.Active then
+ highlight(button)
+ end
+ end)
+ button.MouseLeave:connect(function()
+ if button.Active and gearContextMenu.Parent.Active then
+ clearHighlight(button)
+ end
+ end)
+
+ contextElement.Button = button
+ contextElement.Element = button
+ elseif element.Type == "Label" then
+ local frame = Instance.new("Frame")
+ frame.Name = "ContextLabel" .. i
+ frame.BackgroundTransparency = 1
+ frame.Size = UDim2.new(1, 8, 0, elementHeight)
+
+ local label = Instance.new("TextLabel")
+ label.Name = "Text1"
+ label.BackgroundTransparency = 1
+ label.BackgroundColor3 = Color3.new(1,1,1)
+ label.BorderSizePixel = 0
+ label.TextXAlignment = Enum.TextXAlignment.Left
+ label.Font = Enum.Font.ArialBold
+ label.FontSize = Enum.FontSize.Size14
+ label.Position = UDim2.new(0.0, 0, 0, 0)
+ label.Size = UDim2.new(0.5, 0, 1, 0)
+ label.TextColor3 = Color3.new(1,1,1)
+ label.ZIndex = 4
+ label.Parent = frame
+ element.Label1 = label
+
+ if element.GetText2 then
+ label = Instance.new("TextLabel")
+ label.Name = "Text2"
+ label.BackgroundTransparency = 1
+ label.BackgroundColor3 = Color3.new(1,1,1)
+ label.BorderSizePixel = 0
+ label.TextXAlignment = Enum.TextXAlignment.Right
+ label.Font = Enum.Font.Arial
+ label.FontSize = Enum.FontSize.Size14
+ label.Position = UDim2.new(0.5, 0, 0, 0)
+ label.Size = UDim2.new(0.5, 0, 1, 0)
+ label.TextColor3 = Color3.new(1,1,1)
+ label.ZIndex = 4
+ label.Parent = frame
+ element.Label2 = label
+ end
+ frame.Parent = gearContextMenuButton
+ element.Label = frame
+ element.Element = frame
+ end
+ end
+
+ gearContextMenu.ZIndex = 4
+ gearContextMenu.MouseLeave:connect(function()
+ browsingMenu = false
+ gearContextMenu.Visible = false
+ clearPreview()
+ end)
+ robloxLock(gearContextMenu)
+
+ return gearContextMenu
+end
+
+local backpackChildren = player.Backpack:GetChildren()
+for i = 1, #backpackChildren do
+ addToGrid(backpackChildren[i])
+end
+
+------------------------- Start Lifelong Connections -----------------------
+screen.Changed:connect(function(prop)
+ if prop == "AbsoluteSize" then
+ if debounce then return end
+ debounce = true
+ wait()
+ resize()
+ resizeGrid()
+ debounce = false
+ end
+end)
+
+currentLoadout.ChildAdded:connect(function(child) loadoutCheck(child, false) end)
+currentLoadout.ChildRemoved:connect(function(child) loadoutCheck(child, true) end)
+
+grid.MouseEnter:connect(function() clearPreview() end)
+grid.MouseLeave:connect(function() clearPreview() end)
+
+player.CharacterRemoving:connect(function()
+ removeCharacterConnections()
+ nukeBackpack()
+end)
+player.CharacterAdded:connect(function() setupCharacterConnections() end)
+
+player.ChildAdded:connect(function(child)
+ if child:IsA("Backpack") then
+ playerBackpack = child
+ if backpackAddCon then backpackAddCon:disconnect() end
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+ end
+end)
+
+swapSlot.Changed:connect(function()
+ if not swapSlot.Value then
+ updateGridActive()
+ end
+end)
+
+searchBox.FocusLost:connect(function(enterPressed)
+ if enterPressed then
+ showSearchGear()
+ end
+end)
+
+local loadoutChildren = currentLoadout:GetChildren()
+for i = 1, #loadoutChildren do
+ if loadoutChildren[i]:IsA("Frame") and string.find(loadoutChildren[i].Name,"Slot") then
+ loadoutChildren[i].ChildRemoved:connect(function()
+ updateGridActive()
+ end)
+ loadoutChildren[i].ChildAdded:connect(function()
+ updateGridActive()
+ end)
+ end
+end
+
+searchButton.MouseButton1Click:connect(function() showSearchGear() end)
+------------------------- End Lifelong Connections -----------------------
+
+resize()
+resizeGrid()
+
+-- make sure any items in the loadout are accounted for in inventory
+local loadoutChildren = currentLoadout:GetChildren()
+for i = 1, #loadoutChildren do
+ loadoutCheck(loadoutChildren[i], false)
+end
+
+-- make sure that inventory is listening to gear reparenting
+if characterChildAddedCon == nil and game.Players.LocalPlayer["Character"] then
+ setupCharacterConnections()
+end
+if not backpackAddCon then
+ backpackAddCon = game.Players.LocalPlayer.Backpack.ChildAdded:connect(function(child) addToGrid(child) end)
+end
+
+
+ backpackButton.Visible = true
+
+
+recalculateScrollLoadout()
+
+
+ -
+
+ false
+
+ Workaround
+ wait(0.1)
+game.Players.LocalPlayer.PlayerGui.Backpack.BackpackResizer.Disabled = true
+game.Players.LocalPlayer.PlayerGui.Backpack.BackpackResizer.Disabled = false
+game.Players.LocalPlayer.PlayerGui.Backpack.CurrentLoadout.Visible = true
diff --git a/scripts/launcher/info.ini b/scripts/launcher/info.ini
index bce70f0..bac0fd2 100644
--- a/scripts/launcher/info.ini
+++ b/scripts/launcher/info.ini
@@ -8,6 +8,6 @@ ExtendedVersionNumber=True
ExtendedVersionEditChangelog=True
//ExtendedVersionTemplate=%version% v8.2022.%extended-revision%%lite%
ExtendedVersionTemplate=%version% Snapshot v22.%build%.%revision%.%extended-revision%
-ExtendedVersionRevision=2
+ExtendedVersionRevision=1
IsLite=False
InitialBootup=False
diff --git a/scripts/launcher/splashes.txt b/scripts/launcher/splashes.txt
index d0b1d26..fe89198 100644
--- a/scripts/launcher/splashes.txt
+++ b/scripts/launcher/splashes.txt
@@ -228,4 +228,5 @@ uuhhh.wav
ouch.ogg
Macaroni, Macaroni, Macaroni, Macaroni!|Put the cheese in the middle, and what do you get?
I dunno, they look like pancakes!|I don't think their pan-THEY'RE PANCAKES!
-I built a giant klayman.
\ No newline at end of file
+I built a giant klayman.
+#!|a shebang!
\ No newline at end of file