Initial commit

This commit is contained in:
2025-12-17 16:47:48 +00:00
commit 13813f3363
4964 changed files with 1079753 additions and 0 deletions

View File

@@ -0,0 +1,765 @@
while game == nil do
wait(1/30)
end
---------------
--PLUGIN SETUP-
---------------
local loaded = false
local on = false
self = PluginManager():CreatePlugin()
local mouse = self:GetMouse()
mouse.Button1Down:connect(function() mouseDown(mouse) end)
mouse.Button1Up:connect(function() mouseUp(mouse) end)
toolbar = self:CreateToolbar("Terrain")
toolbarbutton = toolbar:CreateButton("Flood Fill", "Flood Fill", "floodFill.png")
toolbarbutton.Click:connect(function()
if on then
Off()
elseif loaded then
On()
end
end)
game:WaitForChild("Workspace")
game.Workspace:WaitForChild("Terrain")
-----------------------------
--LOCAL FUNCTION DEFINITIONS-
-----------------------------
local c = game.Workspace.Terrain
local WorldToCellPreferSolid = c.WorldToCellPreferSolid
local WorldToCellPreferEmpty = c.WorldToCellPreferEmpty
local CellCenterToWorld = c.CellCenterToWorld
local GetCell = c.GetCell
local SetCell = c.SetCell
local maxYExtents = c.MaxExtents.Max.Y
local emptyMaterial = Enum.CellMaterial.Empty
local waterMaterial = Enum.CellMaterial.Water
local floodFill = nil
-----------------
--DEFAULT VALUES-
-----------------
local startCell = nil
local processing = false
-- gui values
local screenGui = nil
local dragBar, closeEvent, helpFrame, lastCell = nil
local progressBar, setProgressFunc, cancelEvent = nil
local ConfirmationPopupObject = nil
--- exposed values to user via gui
local currentMaterial = 1
-- load our libraries
local RbxGui = LoadLibrary("RbxGui")
local RbxUtil = LoadLibrary("RbxUtility")
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset/?id=82741829")
------------------------- OBJECT DEFINITIONS ---------------------
-- helper function for objects
function getClosestColorToTerrainMaterial(terrainValue)
if terrainValue == 1 then return BrickColor.new("Bright green")
elseif terrainValue == 2 then return BrickColor.new("Bright yellow")
elseif terrainValue == 3 then return BrickColor.new("Bright red")
elseif terrainValue == 4 then return BrickColor.new("Sand red")
elseif terrainValue == 5 then return BrickColor.new("Black")
elseif terrainValue == 6 then return BrickColor.new("Dark stone grey")
elseif terrainValue == 7 then return BrickColor.new("Sand blue")
elseif terrainValue == 8 then return BrickColor.new("Deep orange")
elseif terrainValue == 9 then return BrickColor.new("Dark orange")
elseif terrainValue == 10 then return BrickColor.new("Reddish brown")
elseif terrainValue == 11 then return BrickColor.new("Light orange")
elseif terrainValue == 12 then return BrickColor.new("Light stone grey")
elseif terrainValue == 13 then return BrickColor.new("Sand green")
elseif terrainValue == 14 then return BrickColor.new("Medium stone grey")
elseif terrainValue == 15 then return BrickColor.new("Really red")
elseif terrainValue == 16 then return BrickColor.new("Really blue")
elseif terrainValue == 17 then return BrickColor.new("Bright blue")
else return BrickColor.new("Bright green")
end
end
-- Used to create a highlighter that follows the mouse.
-- It is a class mouse highlighter. To use, call MouseHighlighter.Create(mouse) where mouse is the mouse to track.
MouseHighlighter = {}
MouseHighlighter.__index = MouseHighlighter
-- Create a mouse movement highlighter.
-- plugin - Plugin to get the mouse from.
function MouseHighlighter.Create(mouseUse)
local highlighter = {}
local mouse = mouseUse
highlighter.OnClicked = nil
highlighter.mouseDown = false
-- Store the last point used to draw.
highlighter.lastUsedPoint = nil
-- Will hold a part the highlighter will be attached to. This will be moved where the mouse is.
highlighter.selectionPart = nil
-- Hook the mouse up to check for movement.
mouse.Move:connect(function() MouseMoved() end)
mouse.Button1Down:connect(function() highlighter.mouseDown = true end)
mouse.Button1Up:connect(function() highlighter.mouseDown = false
end)
-- Create the part that the highlighter will be attached to.
highlighter.selectionPart = Instance.new("Part")
highlighter.selectionPart.Name = "SelectionPart"
highlighter.selectionPart.Archivable = false
highlighter.selectionPart.Transparency = 0.5
highlighter.selectionPart.Anchored = true
highlighter.selectionPart.Locked = true
highlighter.selectionPart.CanCollide = false
highlighter.selectionPart.FormFactor = Enum.FormFactor.Custom
highlighter.selectionPart.Size = Vector3.new(4,4,4)
highlighter.selectionPart.BottomSurface = 0
highlighter.selectionPart.TopSurface = 0
highlighter.selectionPart.BrickColor = getClosestColorToTerrainMaterial(currentMaterial)
highlighter.selectionPart.Parent = game.Workspace
local billboardGui = Instance.new("BillboardGui",highlighter.selectionPart)
billboardGui.Size = UDim2.new(5,0,5,0)
billboardGui.StudsOffset = Vector3.new(0,2.5,0)
local imageLabel = Instance.new("ImageLabel",billboardGui)
imageLabel.BackgroundTransparency = 1
imageLabel.Size = UDim2.new(1,0,1,0)
imageLabel.Position = UDim2.new(-0.35,0,-0.5,0)
imageLabel.Image = "http://www.roblox.com/asset/?id=82741829"
local lastTweenChange = nil
function startTween()
while tweenUp or tweenDown do
wait(0.2)
end
lastTweenChange = tick()
delay(0,function ( )
local thisTweenStamp = lastTweenChange
local tweenDown, tweenUp = nil
tweenDown = function()
if imageLabel and imageLabel:IsDescendantOf(game.Workspace) and thisTweenStamp == lastTweenChange then
imageLabel:TweenPosition(UDim2.new(-0.35,0,-0.5,0), Enum.EasingDirection.In, Enum.EasingStyle.Quad,0.4,true,tweenUp)
end
end
tweenUp = function()
if imageLabel and imageLabel:IsDescendantOf(game.Workspace) and thisTweenStamp == lastTweenChange then
imageLabel:TweenPosition(UDim2.new(-0.35,0,-0.7,0), Enum.EasingDirection.Out, Enum.EasingStyle.Sine,0.4,true,tweenDown)
end
end
tweenUp()
end)
end
function stopTween()
lastTweenChange = tick()
end
mouse.TargetFilter = highlighter.selectionPart
setmetatable(highlighter, MouseHighlighter)
-- Function to call when the mouse has moved. Updates where to display the highlighter.
function MouseMoved()
if on and not processing then
UpdatePosition(mouse.Hit)
end
end
-- Update where the highlighter is displayed.
-- position - Where to display the highlighter, in world space.
function UpdatePosition(position)
if not position then
return
end
if not mouse.Target then
stopTween()
highlighter.selectionPart.Parent = nil
return
end
if highlighter.selectionPart.Parent ~= game.Workspace then
highlighter.selectionPart.Parent = game.Workspace
startTween()
end
local vectorPos = Vector3.new(position.x,position.y,position.z)
local cellPos = WorldToCellPreferEmpty(c, vectorPos)
local regionToSelect = nil
local cellMaterial = GetCell(c, cellPos.x,cellPos.y,cellPos.z)
local y = cellPos.y
-- only select empty cells
while cellMaterial ~= emptyMaterial do
y = y + 1
cellMaterial = GetCell(c, cellPos.x,y,cellPos.z)
end
cellPos = Vector3.new(cellPos.x,y,cellPos.z)
local lowVec = CellCenterToWorld(c, cellPos.x , cellPos.y - 1, cellPos.z)
local highVec = CellCenterToWorld(c, cellPos.x, cellPos.y + 1, cellPos.z)
regionToSelect = Region3.new(lowVec, highVec)
highlighter.selectionPart.CFrame = regionToSelect.CFrame
if nil ~= highlighter.OnClicked and highlighter.mouseDown then
if nil == highlighter.lastUsedPoint then
highlighter.lastUsedPoint = WorldToCellPreferEmpty(c, Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
else
cellPos = WorldToCellPreferEmpty(c, Vector3.new(mouse.Hit.x, mouse.Hit.y, mouse.Hit.z))
holdChange = cellPos - highlighter.lastUsedPoint
-- Require terrain.
if 0 == GetCell(c, cellPos.X, cellPos.Y, cellPos.Z).Value then
return
else
highlighter.lastUsedPoint = cellPos
end
end
end
end
return highlighter
end
function MouseHighlighter:SetMaterial(newMaterial)
self.selectionPart.BrickColor = getClosestColorToTerrainMaterial(newMaterial)
end
function MouseHighlighter:GetPosition()
local position = self.selectionPart.CFrame.p
return WorldToCellPreferEmpty(c,position)
end
-- Hide the highlighter.
function MouseHighlighter:DisablePreview()
stopTween()
self.selectionPart.Parent = nil
end
-- Show the highlighter.
function MouseHighlighter:EnablePreview()
self.selectionPart.Parent = game.Workspace
startTween()
end
-- Create the mouse movement highlighter.
local mouseHighlighter = MouseHighlighter.Create(mouse)
mouseHighlighter:DisablePreview()
-- Used to create a highlighter.
-- A highlighter is a open, rectuangular area displayed in 3D.
ConfirmationPopup = {}
ConfirmationPopup.__index = ConfirmationPopup
-- Create a standard text label. Use this for all lables in the popup so it is easy to standardize.
-- labelName - What to set the text label name as.
-- pos - Where to position the label. Should be of type UDim2.
-- size - How large to make the label. Should be of type UDim2.
-- text - Text to display.
-- parent - What to set the text parent as.
-- Return:
-- Value is the created label.
function CreateStandardLabel(labelName,
pos,
size,
text,
parent)
local label = Instance.new("TextLabel", parent)
label.Name = labelName
label.Position = pos
label.Size = size
label.Text = text
label.TextColor3 = Color3.new(0.95, 0.95, 0.95)
label.Font = Enum.Font.ArialBold
label.FontSize = Enum.FontSize.Size14
label.TextXAlignment = Enum.TextXAlignment.Left
label.BackgroundTransparency = 1
label.Parent = parent
return label
end
-- Keep common button properties here to make it easer to change them all at once.
-- These are the default properties to use for a button.
buttonTextColor = Color3.new(1, 1, 1);
buttonFont = Enum.Font.ArialBold;
buttonFontSize = Enum.FontSize.Size18;
-- Create a standard dropdown. Use this for all dropdowns in the popup so it is easy to standardize.
-- name - What to use.
-- pos - Where to position the button. Should be of type UDim2.
-- text - Text to show in the button.
-- funcOnPress - Function to run when the button is pressed.
-- parent - What to set the parent as.
-- Return:
-- button - The button gui.
function CreateStandardButton(name,
pos,
text,
funcOnPress,
parent,
size)
button = Instance.new("TextButton", parent)
button.Name = name
button.Position = pos
button.Size = UDim2.new(0,120,0,40)
button.Text = text
if size then
button.Size = size
end
button.Style = Enum.ButtonStyle.RobloxButton
button.TextColor3 = buttonTextColor
button.Font = buttonFont
button.FontSize = buttonFontSize
button.MouseButton1Click:connect(funcOnPress)
return button
end
-- Create a confirmation popup.
--
-- confirmText - What to display in the popup.
-- textOffset - Offset to position text at.
-- confirmFunction - Function to run on confirmation.
-- declineFunction - Function to run when declining.
--
-- Return:
-- Value a table with confirmation gui and options.
function ConfirmationPopup.Create(confirmText,
confirmSmallText,
confirmButtonText,
declineButtonText,
confirmFunction,
declineFunction)
local popup = {}
popup.confirmButton = nil -- Hold the button to confirm a choice.
popup.declineButton = nil -- Hold the button to decline a choice.
popup.confirmationFrame = nil -- Hold the conformation frame.
popup.confirmationText = nil -- Hold the text label to display the conformation message.
popup.confirmationHelpText = nil -- Hold the text label to display the conformation message help.
popup.confirmationFrame = Instance.new("Frame",screenGui)
popup.confirmationFrame.Name = "ConfirmationFrame"
popup.confirmationFrame.Size = UDim2.new(0, 280, 0, 160)
popup.confirmationFrame.Position = UDim2.new(.5, -popup.confirmationFrame.Size.X.Offset/2, 0.5, -popup.confirmationFrame.Size.Y.Offset/2)
popup.confirmationFrame.Style = Enum.FrameStyle.RobloxRound
popup.confirmLabel = CreateStandardLabel("ConfirmLabel", UDim2.new(0,0,0,15), UDim2.new(1, 0, 0, 24), confirmText, popup.confirmationFrame)
popup.confirmLabel.FontSize = Enum.FontSize.Size18
popup.confirmLabel.TextXAlignment = Enum.TextXAlignment.Center
popup.confirmationHelpText = CreateStandardLabel("ConfirmSmallLabel", UDim2.new(0,0,0,40), UDim2.new(1, 0, 0, 28), confirmSmallText, popup.confirmationFrame)
popup.confirmationHelpText.FontSize = Enum.FontSize.Size14
popup.confirmationHelpText.TextWrap = true
popup.confirmationHelpText.Font = Enum.Font.Arial
popup.confirmationHelpText.TextXAlignment = Enum.TextXAlignment.Center
-- Confirm
popup.confirmButton = CreateStandardButton("ConfirmButton",
UDim2.new(0.5, -120, 1, -50),
confirmButtonText,
confirmFunction,
popup.confirmationFrame)
-- Decline
popup.declineButton = CreateStandardButton("DeclineButton",
UDim2.new(0.5, 0, 1, -50),
declineButtonText,
declineFunction,
popup.confirmationFrame)
setmetatable(popup, ConfirmationPopup)
return popup
end
-- Clear the popup, free up assets.
function ConfirmationPopup:Clear()
if nil ~= self.confirmButton then
self.confirmButton.Parent = nil
end
if nil ~= self.declineButton then
self.declineButton.Parent = nil
end
if nil ~= self.confirmationFrame then
self.confirmationFrame.Parent = nil
end
if nil ~= self.confirmLabel then
self.confirmLabel.Parent = nil
end
self.confirmButton = nil
self.declineButton = nil
self.conformationFrame = nil
self.conformText = nil
end
-----------------------
--FUNCTION DEFINITIONS-
-----------------------
local floodFill = function ( x,y,z )
LoadProgressBar("Processing")
breadthFill(x,y,z)
UnloadProgressBar()
game:GetService("ChangeHistoryService"): SetWaypoint("FloodFill")
end
-- Function used when we try and flood fill. Prompts the user first.
-- Will not show if disabled or terrain is being processed.
function ConfirmFloodFill(x,y,z)
-- Only do if something isn't already being processed.
if not processing then
processing = true
if nil == ConfirmationPopupObject then
ConfirmationPopupObject = ConfirmationPopup.Create("Flood Fill At Selected Location?",
"This operation may take some time.",
"Fill",
"Cancel",
function()
ConfirmationPopupObject:Clear()
ConfirmationPopupObject = nil
floodFill(x,y,z)
ConfirmationPopupObject = nil
end,
function()
ConfirmationPopupObject:Clear()
ConfirmationPopupObject = nil
processing = false
end)
end
end
end
function mouseDown(mouse)
if on and mouse.Target == game.Workspace.Terrain then
startCell = mouseHighlighter:GetPosition()
end
end
function mouseUp(mouse)
if processing then return end
local upCell = mouseHighlighter:GetPosition()
if startCell == upCell then
ConfirmFloodFill(upCell.x,upCell.y,upCell.z)
end
end
function getMaterial( x,y,z )
local material = GetCell(c,x,y,z)
return material
end
function startLoadingFrame( )
end
-- Load the progress bar to display when drawing a river.
-- text - Text to display.
function LoadProgressBar(text)
processing = true
-- Start the progress bar.
progressBar, setProgressFunc, cancelEvent = RbxGui.CreateLoadingFrame(text)
progressBar.Position = UDim2.new(.5, -progressBar.Size.X.Offset/2, 0, 15)
progressBar.Parent = screenGui
local loadingPercent = progressBar:FindFirstChild("LoadingPercent",true)
if loadingPercent then
loadingPercent.Parent = nil
end
local loadingBar = progressBar:FindFirstChild("LoadingBar",true)
if loadingBar then
loadingBar.Parent = nil
end
local cancelButton = progressBar:FindFirstChild("CancelButton",true)
if cancelButton then
cancelButton.Text = "Stop"
end
cancelEvent.Event:connect(function(arguments)
processing = false
spin = false
end)
local spinnerFrame = Instance.new("Frame",progressBar)
spinnerFrame.Name = "Spinner"
spinnerFrame.Size = UDim2.new(0, 80, 0, 80)
spinnerFrame.Position = UDim2.new(0.5, -40, 0.5, -55)
spinnerFrame.BackgroundTransparency = 1
local spinnerIcons = {}
local spinnerNum = 1
while spinnerNum <= 8 do
local spinnerImage = Instance.new("ImageLabel")
spinnerImage.Name = "Spinner"..spinnerNum
spinnerImage.Size = UDim2.new(0, 16, 0, 16)
spinnerImage.Position = UDim2.new(.5+.3*math.cos(math.rad(45*spinnerNum)), -8, .5+.3*math.sin(math.rad(45*spinnerNum)), -8)
spinnerImage.BackgroundTransparency = 1
spinnerImage.Image = "http://www.roblox.com/Asset/?id=45880710"
spinnerImage.Parent = spinnerFrame
spinnerIcons[spinnerNum] = spinnerImage
spinnerNum = spinnerNum + 1
end
--Make it spin
delay(0, function()
local spinPos = 0
while processing do
local pos = 0
while pos < 8 do
if pos == spinPos or pos == ((spinPos+1)%8) then
spinnerIcons[pos+1].Image = "http://www.roblox.com/Asset/?id=45880668"
else
spinnerIcons[pos+1].Image = "http://www.roblox.com/Asset/?id=45880710"
end
pos = pos + 1
end
spinPos = (spinPos + 1) % 8
wait(0.2)
end
end)
end
-- Unload the progress bar.
function UnloadProgressBar()
processing = false
if progressBar then
progressBar.Parent = nil
progressBar = nil
end
if setProgressFunc then
setProgressFunc = nil
end
if cancelEvent then
cancelEvent = nil
end
end
function breadthFill( x,y,z )
local yDepthChecks = doBreadthFill(x,y,z)
while yDepthChecks and #yDepthChecks > 0 do
local newYChecks = {}
for i = 1, #yDepthChecks do
local currYDepthChecks = doBreadthFill(yDepthChecks[i].xPos,yDepthChecks[i].yPos,yDepthChecks[i].zPos)
if not processing then
return
end
if currYDepthChecks and #currYDepthChecks > 0 then
for i = 1, #currYDepthChecks do
table.insert(newYChecks,{xPos = currYDepthChecks[i].xPos, yPos = currYDepthChecks[i].yPos, zPos = currYDepthChecks[i].zPos})
end
end
end
yDepthChecks = newYChecks
end
end
function doBreadthFill(x,y,z)
if getMaterial(x,y,z) ~= emptyMaterial then
return
end
local yDepthChecks = {}
local cellsToCheck = breadthFillHelper(x,y,z,yDepthChecks)
local count = 0
while cellsToCheck and #cellsToCheck > 0 do
local cellCheckQueue = {}
for i = 1, #cellsToCheck do
if not processing then
return
end
count = count + 1
local newCellsToCheck = breadthFillHelper(cellsToCheck[i].xPos,cellsToCheck[i].yPos,cellsToCheck[i].zPos,yDepthChecks)
if newCellsToCheck and #newCellsToCheck > 0 then
for i = 1, #newCellsToCheck do
table.insert(cellCheckQueue,{xPos = newCellsToCheck[i].xPos, yPos = newCellsToCheck[i].yPos, zPos = newCellsToCheck[i].zPos})
end
end
if count >= 3000 then
wait()
count = 0
end
end
cellsToCheck = cellCheckQueue
end
return yDepthChecks
end
function cellInTerrain( x,y,z )
if x < c.MaxExtents.Min.X or x >= c.MaxExtents.Max.X then
return false
end
if y < c.MaxExtents.Min.Y or y >= c.MaxExtents.Max.Y then
return false
end
if z < c.MaxExtents.Min.Z or z >= c.MaxExtents.Max.Z then
return false
end
return true
end
function breadthFillHelper(x,y,z,yDepthChecks)
-- first, lets try and fill this cell
if cellInTerrain( x,y,z ) and getMaterial( x, y, z) == emptyMaterial then
SetCell(c,x,y,z,currentMaterial,0,0)
end
local cellsToFill = {}
if cellInTerrain( x + 1,y,z ) and getMaterial( x + 1, y, z) == emptyMaterial then
table.insert(cellsToFill,{xPos = x + 1, yPos = y, zPos = z})
end
if cellInTerrain( x - 1,y,z ) and getMaterial( x - 1, y, z) == emptyMaterial then
table.insert(cellsToFill,{xPos = x - 1, yPos = y, zPos = z})
end
if cellInTerrain( x,y,z + 1) and getMaterial( x, y, z + 1) == emptyMaterial then
table.insert(cellsToFill,{xPos = x, yPos = y, zPos = z + 1})
end
if cellInTerrain( x,y,z - 1) and getMaterial( x, y, z - 1) == emptyMaterial then
table.insert(cellsToFill,{xPos = x, yPos = y, zPos = z - 1})
end
if cellInTerrain( x,y-1,z) and getMaterial( x, y-1, z) == emptyMaterial then
table.insert(yDepthChecks,{xPos = x, yPos = y - 1, zPos = z})
end
for i = 1, #cellsToFill do
SetCell(c,cellsToFill[i].xPos,cellsToFill[i].yPos,cellsToFill[i].zPos,currentMaterial,0,0)
end
if #cellsToFill <= 0 then
return nil
end
return cellsToFill
end
function On()
if not c then
return
end
if self then
self:Activate(true)
end
if toolbarbutton then
toolbarbutton:SetActive(true)
end
if dragBar then
dragBar.Visible = true
end
on = true
end
function Off()
if toolbarbutton then
toolbarbutton:SetActive(false)
end
if mouseHighlighter then
mouseHighlighter:DisablePreview()
end
if dragBar then
dragBar.Visible = false
end
on = false
end
mouseHighlighter.OnClicked = mouseUp
------
--GUI-
------
screenGui = Instance.new("ScreenGui", game:GetService("CoreGui"))
screenGui.Name = "FloodFillGui"
dragBar, containerFrame, helpFrame, closeEvent = RbxGui.CreatePluginFrame("Flood Fill",UDim2.new(0,163,0,195),UDim2.new(0,0,0,0),false,screenGui)
dragBar.Visible = false
helpFrame.Size = UDim2.new(0,200,0,190)
local textHelp = Instance.new("TextLabel",helpFrame)
textHelp.Name = "TextHelp"
textHelp.Font = Enum.Font.ArialBold
textHelp.FontSize = Enum.FontSize.Size12
textHelp.TextColor3 = Color3.new(1,1,1)
textHelp.Size = UDim2.new(1,-6,1,-6)
textHelp.Position = UDim2.new(0,3,0,3)
textHelp.TextXAlignment = Enum.TextXAlignment.Left
textHelp.TextYAlignment = Enum.TextYAlignment.Top
textHelp.BackgroundTransparency = 1
textHelp.TextWrap = true
textHelp.Text =
[[
Quickly replace empty terrain cells with a selected material. Clicking the mouse will cause any empty terrain cells around the point clicked to be filled with the current material, and will also spread to surrounding empty cells (including any empty cells below, but not above).
Simply click on a different material to fill with that material. The floating paint bucket and cube indicate where filling will start.
]]
closeEvent.Event:connect(function() Off() end)
local terrainSelectorGui, terrainSelected, forceTerrainMaterialSelection = RbxGui.CreateTerrainMaterialSelector(UDim2.new(1, -10, 0, 184),UDim2.new(0, 5, 0, 5))
terrainSelectorGui.Parent = containerFrame
terrainSelectorGui.BackgroundTransparency = 1
terrainSelectorGui.BorderSizePixel = 0
terrainSelected.Event:connect(function ( newMaterial )
currentMaterial = newMaterial
if mouseHighlighter then
mouseHighlighter:SetMaterial(currentMaterial)
end
end)
forceTerrainMaterialSelection(Enum.CellMaterial.Water)
self.Deactivation:connect(function()
Off()
end)
--------------------------
--SUCCESSFUL LOAD MESSAGE-
--------------------------
loaded = true