forked from aya/aya
766 lines
23 KiB
Lua
766 lines
23 KiB
Lua
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
|