null
nil
-
true
true
0
0
0
1
0
0
0
1
0
0
0
1
ClassicTool
http://www.roblox.com/asset/?id=59105322
Classic Tool
-
false
ClassicToolController
local Tool = script.Parent
local keyUpCon = nil
local gui = nil
local connections = {}
local buttons = {}
local colorButton,SurfaceButton,MaterialButton,ResizeButton,draggerButton = nil
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset?id=59103051")
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset?id=59103080")
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset?id=59103092")
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset?id=59103119")
game:GetService("ContentProvider"):Preload("http://www.roblox.com/asset?id=59103152")
function makeImageButton(buttonName, image, position, parent, hotKeyString)
local button = Instance.new("ImageButton")
button.Name = buttonName
button.Style = Enum.ButtonStyle.RobloxButton
button.Size = UDim2.new(0,45,0,45)
if position then button.Position = position end
button.Parent = parent
local buttonImage = Instance.new("ImageLabel")
buttonImage.Name = "ButtonImage"
buttonImage.BackgroundTransparency = 1
buttonImage.Size = UDim2.new(1,12,1,12)
buttonImage.Position = UDim2.new(0,-6,0,-6)
buttonImage.Image = image
buttonImage.Parent = button
if hotKeyString then
local textShortcut = Instance.new("TextLabel")
textShortcut.Text = hotKeyString
textShortcut.Name = "TextShortcut"
textShortcut.Font = Enum.Font.ArialBold
textShortcut.BackgroundTransparency = 1
textShortcut.FontSize = Enum.FontSize.Size14
textShortcut.TextColor3 = Color3.new(1,1,1)
textShortcut.Size = UDim2.new(0,textShortcut.TextBounds.X,0,textShortcut.TextBounds.X)
textShortcut.Parent = button
end
return button
end
function deactivateTool(script)
local enable = script:FindFirstChild("Active")
if enable and enable:IsA("BoolValue") then
enable.Value = false
end
end
function deactivateAllTools()
local toolChildren = Tool:GetChildren()
for i = 1, #toolChildren do
if toolChildren[i]:IsA("BaseScript") and toolChildren[i] ~= script then
deactivateTool(toolChildren[i])
end
end
for i = 1, #buttons do
buttons[i].Selected = false
end
end
function goToTool(toolName, button)
deactivateAllTools()
button.Selected = true
wait() -- give scripts a heartbeat to get set straight
local toolScript = Tool:FindFirstChild(toolName)
if toolScript and toolScript:IsA("BaseScript") then
local enable = toolScript:FindFirstChild("Active")
if enable and enable:IsA("BoolValue") then
enable.Value = true
end
end
end
function makeClassicControlGui()
clearAllConnections()
local classicGui = Instance.new("ScreenGui")
classicGui.Name = "ClassicGui"
local classicFrame = Instance.new("Frame")
classicFrame.Name = "ClassicFrame"
classicFrame.BackgroundTransparency = 1
classicFrame.Size = UDim2.new(0,246,0,45)
classicFrame.Position = UDim2.new(0.5, -113, 1, -130)
classicFrame.Parent = classicGui
colorButton = makeImageButton("ColorButton","http://www.roblox.com/asset?id=59103051",UDim2.new(0,0,0.5,-23), classicFrame, "F")
local colorCon = colorButton.MouseButton1Click:connect(function() goToTool("Color", colorButton) end)
table.insert(connections,colorCon)
table.insert(buttons,colorButton)
SurfaceButton = makeImageButton("SurfaceButton","http://www.roblox.com/asset?id=59103080",UDim2.new(0,90,0.5,-23), classicFrame, "H")
local surfaceCon = SurfaceButton.MouseButton1Click:connect(function() goToTool("Surface", SurfaceButton) end)
table.insert(connections,surfaceCon)
table.insert(buttons,SurfaceButton)
MaterialButton = makeImageButton("MaterialButton","http://www.roblox.com/asset?id=59103092",UDim2.new(0,45,0.5,-23), classicFrame, "G")
local materialCon = MaterialButton.MouseButton1Click:connect(function() goToTool("Material", MaterialButton) end)
table.insert(connections,materialCon)
table.insert(buttons,MaterialButton)
ResizeButton = makeImageButton("ResizeButton","http://www.roblox.com/asset?id=59103119",UDim2.new(0,180,0.5,-23), classicFrame, "K")
local resizeCon = ResizeButton.MouseButton1Click:connect(function() goToTool("Resize", ResizeButton) end)
table.insert(connections,resizeCon)
table.insert(buttons,ResizeButton)
draggerButton = makeImageButton("ResizeButton","http://www.roblox.com/asset?id=59103152",UDim2.new(0,135,0.5,-23), classicFrame, "J")
local draggerCon = draggerButton.MouseButton1Click:connect(function() goToTool("Dragger", draggerButton) end)
table.insert(connections,draggerCon)
table.insert(buttons,draggerButton)
return classicGui
end
function clearAllConnections()
for i = 1, #connections do
connections[i]:disconnect()
end
connections = {}
end
function hotKey(key)
key = key:lower()
if key == "f" then
goToTool("Color", colorButton)
elseif key == "g" then
goToTool("Material", MaterialButton)
elseif key == "h" then
goToTool("Surface", SurfaceButton)
elseif key == "j" then
goToTool("Dragger", draggerButton)
elseif key == "k" then
goToTool("Resize", ResizeButton)
end
end
function onEquippedLocal(mouse)
Tool.Mouse.Value = mouse
if not gui then
gui = makeClassicControlGui()
end
gui.Parent = game.Players.LocalPlayer.PlayerGui
keyUpCon = mouse.KeyUp:connect(function(key) hotKey(key) end)
end
function onUnequippedLocal()
if keyUpCon then keyUpCon:disconnect() end
deactivateAllTools()
gui.Parent = nil
end
Tool.Equipped:connect(onEquippedLocal)
Tool.Unequipped:connect(onUnequippedLocal)
-
false
-0.5
0.5
0
0
-0.5
0.5
0
0
199
-0.000566363335
0.480126768
0.498794556
-1.50203878e-005
1.50579854e-006
-1.00000012
9.8371238e-006
1
1.50565256e-006
1.00000012
-9.83710197e-006
-1.50204023e-005
true
0.5
0.300000012
-0.5
0.5
0
0
-0.5
0.5
0
0
true
256
Handle
0
-0.5
0.5
0
0
0
0
0
-0.5
0.5
0
0
0
0
0
0
2
1
1
0.800000012
2
-
2
2
http://www.roblox.com/asset/?id=15952510
5
Mesh
0
0
0
0.400000006
0.400000006
0.400000006
http://www.roblox.com/asset/?id=15952494
1
1
1
-
false
Sound
1
false
rbxasset://sounds/swordslash.wav
1
-
false
Sound
1
false
rbxasset://sounds/unsheath.wav
1
-
false
Sound
1
false
rbxasset://sounds/swordslash.wav
1
-
false
Sound
1
false
rbxasset://sounds/unsheath.wav
1
-
false
Color
-- basic functions
function waitForChild(instance, name)
while not instance:findFirstChild(name) do
instance.ChildAdded:wait()
end
end
local Tool = script.Parent
enabled = true
local menu
local origTexture = Tool.TextureId
local localAssetBase = "rbxasset://textures/ui/"
local currentColorButton = nil
game:GetService("ContentProvider"):Preload("rbxasset://icons/color_sel.png")
local buttonDownCon, mouseMoveCon
local clickCons = {}
function onButton1Down(mouse)
if not enabled then
return
end
enabled = false
mouse.Icon = "rbxasset://textures\\GunWaitCursor.png"
wait(.5)
mouse.Icon = "rbxasset://textures\\GunCursor.png"
enabled = true
end
local selectionBox
local selectionLasso
function setSelectionBox(part)
unsetSelectionBox()
selectionBox.Adornee = part
selectionLasso.Part = part
end
function unsetSelectionBox()
selectionBox.Adornee = nil
selectionLasso.Part = nil
end
function canSelectObject(part)
return part and not (part.Locked) and (part.Position - Tool.Parent.Head.Position).Magnitude < 60
end
function on3dButton1Down(mouse)
local part = mouse.Target
if canSelectObject(part) then
if Instance.Lock(part) then
color = Tool.Color.CurrentColor.Value
if color == nil then
Instance.Unlock(part)
return
end
part.BrickColor = color
Instance.Unlock(part)
end
end
end
function on3dMouseMove(mouse)
mouse.Icon ="rbxasset://textures\\FillCursor.png"
local part = mouse.Target
if canSelectObject(part) then
setSelectionBox(part)
else
unsetSelectionBox()
end
end
function makeColorMenu()
local paintGui = Instance.new("ScreenGui")
paintGui.Name = "PaintGui"
local paintMenu = Instance.new("ImageLabel")
paintMenu.Name = "PaintMenu"
paintMenu.Position = UDim2.new(0,0,1,-600)
paintMenu.Size = UDim2.new(0,120,0,500)
paintMenu.BackgroundTransparency = 1
paintMenu.ZIndex = 2
paintMenu.Image = localAssetBase .. "PaintMenu.png"
paintMenu.Parent = paintGui
local paintColorButton = Instance.new("ImageButton")
paintColorButton.BorderSizePixel = 0
paintColorButton.ZIndex = 3
paintColorButton.Modal = true
paintColorButton.Size = UDim2.new(0.200000003, 0,0.0500000007, 0)
local selection = Instance.new("Frame")
selection.Name = "Selection"
selection.BorderSizePixel = 0
selection.BackgroundColor3 = Color3.new(1,1,1)
selection.BackgroundTransparency = 1
selection.ZIndex = 2
selection.Size = UDim2.new(1.1,0,1.1,0)
selection.Position = UDim2.new(-0.05,0,-0.05,0)
selection.Parent = paintColorButton
local header = 0.08
local spacing = 18
local count = 1
local function findNextColor()
colorName = tostring(BrickColor.new(count))
while colorName == "Medium stone grey" do
count = count + 1
colorName = tostring(BrickColor.new(count))
end
return count
end
for i = 0,15 do
for j = 1, 4 do
newButton = paintColorButton:clone()
newButton.BackgroundColor3 = BrickColor.new(findNextColor()).Color
newButton.Name = tostring(BrickColor.new(count))
count = count + 1
if j == 1 then newButton.Position = UDim2.new(0.08,0,i/spacing + header,0)
elseif j == 2 then newButton.Position = UDim2.new(0.29,0,i/spacing + header,0)
elseif j == 3 then newButton.Position = UDim2.new(0.5,0,i/spacing + header,0)
elseif j == 4 then newButton.Position = UDim2.new(0.71,0,i/spacing + header,0) end
newButton.Parent = paintMenu
end
end
local paintButtons = paintMenu:GetChildren()
for i = 1, #paintButtons do
local newCon = paintButtons[i].MouseButton1Click:connect(function()
Tool.Color.CurrentColor.Value = BrickColor.new(paintButtons[i].Name)
if currentColorButton then
if currentColorButton:FindFirstChild("Selection") then
currentColorButton.Selection.BackgroundTransparency = 1
end
end
currentColorButton = paintButtons[i]
paintButtons[i].Selection.BackgroundTransparency = 0
end)
local anotherCon = paintButtons[i].MouseEnter:connect(function()
paintButtons[i].Selection.BackgroundTransparency = 0
end)
local oneMoreCon = paintButtons[i].MouseLeave:connect(function()
if paintButtons[i] ~= currentColorButton then paintButtons[i].Selection.BackgroundTransparency = 1 end
end)
table.insert(clickCons,newCon)
table.insert(clickCons,anotherCon)
table.insert(clickCons,oneMoreCon)
end
return paintGui
end
function onEquippedLocal(mouse)
Tool.TextureId = "rbxasset://icons/color_sel.png"
local character = script.Parent.Parent
local player = game.Players:GetPlayerFromCharacter(character)
buttonDownCon = mouse.Button1Down:connect(function() on3dButton1Down(mouse) end)
mouseMoveCon = mouse.Move:connect(function() on3dMouseMove(mouse) end)
mouse.Icon ="rbxasset://textures\\FillCursor.png"
selectionBox = Instance.new("SelectionBox")
selectionBox.Color = Tool.Color.CurrentColor.Value
selectionBox.Adornee = nil
selectionBox.Parent = player.PlayerGui
selectionLasso = Instance.new("SelectionPartLasso")
selectionLasso.Name = "Model Delete Lasso"
selectionLasso.Humanoid = character.Humanoid
selectionLasso.Part = nil
selectionLasso.Visible = true
selectionLasso.archivable = false
selectionLasso.Color = Tool.Color.CurrentColor.Value
selectionLasso.Parent = game.workspace
menu = makeColorMenu()
menu.Parent = game.Players.LocalPlayer.PlayerGui
end
function onUnequippedLocal()
if menu then menu:remove() end
Tool.TextureId = origTexture
for i = 1, #clickCons do
clickCons[i]:disconnect()
end
clickCons = {}
if selectionBox then selectionBox:Remove() end
if selectionLasso then selectionLasso:Remove() end
if mouseMoveCon then mouseMoveCon:disconnect() end
if buttonDownCon then buttonDownCon:disconnect() end
end
waitForChild(Tool.Color,"CurrentColor")
waitForChild(Tool.Color,"Active")
Tool.Color.CurrentColor.Changed:connect(function()
if selectionBox then selectionBox.Color = Tool.Color.CurrentColor.Value end
if selectionLasso then selectionLasso.Color = Tool.Color.CurrentColor.Value end
end)
script.Active.Changed:connect(function(prop)
if script.Active.Value == true then
onEquippedLocal(Tool.Mouse.Value)
else
onUnequippedLocal()
end
end)
-
Active
false
-
CurrentColor
194
-
false
Material
-- basic functions
function waitForChild(instance, name)
while not instance:findFirstChild(name) do
instance.ChildAdded:wait()
end
end
local Tool = script.Parent
waitForChild(Tool.Material,"Active")
waitForChild(Tool.Material,"CurrentMaterial")
enabled = true
local origTexture = Tool.TextureId
local localAssetBase = "rbxasset://textures/ui/"
game:GetService("ContentProvider"):Preload("rbxasset://icons/material_sel.png")
local menu
local selectionBox
local selectionLasso
local selectedButton
local value = nil
local downCons = {}
local currentMaterialButton = nil
function setSelectionBox(part)
unsetSelectionBox()
selectionBox.Adornee = part
selectionLasso.Part = part
end
function unsetSelectionBox()
selectionBox.Adornee = nil
selectionLasso.Part = nil
end
local MaterialEnum = {}
MaterialEnum["Plastic"] = Enum.Material.Plastic
MaterialEnum["Wood"] = Enum.Material.Wood
MaterialEnum["Slate"] = Enum.Material.Slate
MaterialEnum["CorrodedMetal"] = Enum.Material.CorrodedMetal
MaterialEnum["Ice"] = Enum.Material.Ice
MaterialEnum["Grass"] = Enum.Material.Grass
MaterialEnum["Foil"] = Enum.Material.Foil
MaterialEnum["DiamondPlate"] = Enum.Material.DiamondPlate
MaterialEnum["Concrete"] = Enum.Material.Concrete
function on3dButton1Down(mouse)
local part = mouse.Target
if part and not (part.Locked) then
if Instance.Lock(part) then
part.Material = MaterialEnum[Tool.Material.CurrentMaterial.Value]
Instance.Unlock(part)
end
end
end
function canSelectObject(part)
return part and not (part.Locked) and (part.Position - Tool.Parent.Head.Position).Magnitude < 60
end
function on3dMouseMove(mouse)
mouse.Icon ="rbxasset://textures\\MaterialCursor.png"
local part = mouse.Target
if canSelectObject(part) then
setSelectionBox(part)
else
unsetSelectionBox()
end
end
function createMaterialMenu()
local materialGui = Instance.new("ScreenGui")
materialGui.Name = "MaterialGui"
local materialMenu = Instance.new("ImageLabel")
materialMenu.Name = "MaterialMenu"
materialMenu.Position = UDim2.new(0,0,1,-350)
materialMenu.Size = UDim2.new(0,100,0,250)
materialMenu.BackgroundTransparency = 1
materialMenu.ZIndex = 2
materialMenu.Image = localAssetBase .. "MaterialMenu.png"
materialMenu.Parent = materialGui
local textures = {"Plastic","Wood","Slate","CorrodedMetal","Ice","Grass","Foil","DiamondPlate","Concrete"}
local materialButtons = {}
local materialButton = Instance.new("ImageButton")
materialButton.BackgroundTransparency = 1
materialButton.Size = UDim2.new(0.400000003, 0,0.16, 0)
materialButton.ZIndex = 4
local selection = Instance.new("Frame")
selection.Name = "Selection"
selection.BorderSizePixel = 0
selection.BackgroundColor3 = Color3.new(1,1,1)
selection.BackgroundTransparency = 1
selection.ZIndex = 3
selection.Size = UDim2.new(1.1,0,1.1,0)
selection.Position = UDim2.new(-0.05,0,-0.05,0)
selection.Parent = materialButton
local current = 1
local function getTextureAndName(button)
if current > #textures then
button:remove()
return false
end
button.Image = localAssetBase .. textures[current] .. ".png"
button.Name = textures[current]
current = current + 1
return true
end
local ySpacing = 0.10
local xSpacing = 0.07
for i = 1,5 do
for j = 1,2 do
local button = materialButton:clone()
button.Position = UDim2.new((j -1)/2.2 + xSpacing,0,ySpacing + (i - 1)/5.5,0)
if getTextureAndName(button) then button.Parent = materialMenu else button:remove() end
table.insert(materialButtons,button)
end
end
for i = 1, #materialButtons do
local newCon = materialButtons[i].MouseButton1Click:connect(function()
Tool.Material.CurrentMaterial.Value = materialButtons[i].Name
if currentMaterialButton then
if currentMaterialButton:FindFirstChild("Selection") then
currentMaterialButton.Selection.BackgroundTransparency = 1
end
end
currentMaterialButton = materialButtons[i]
materialButtons[i].Selection.BackgroundTransparency = 0
end)
local enterCon = materialButtons[i].MouseEnter:connect(function()
materialButtons[i].Selection.BackgroundTransparency = 0
end)
local leaveCon = materialButtons[i].MouseLeave:connect(function()
if materialButtons[i] ~= currentMaterialButton then materialButtons[i].Selection.BackgroundTransparency = 1 end
end)
table.insert(downCons, newCon)
table.insert(downCons, enterCon)
table.insert(downCons, leaveCon)
end
return materialGui
end
function onEquippedLocal(mouse)
Tool.TextureId = "rbxasset://icons/material_sel.png"
value = nil
selectedButton = nil
local character = script.Parent.Parent
local player = game.Players:GetPlayerFromCharacter(character)
selectedButton = nil
button1DownCon = mouse.Button1Down:connect(function() on3dButton1Down(mouse) end)
mouseMoveCon = mouse.Move:connect(function() on3dMouseMove(mouse) end)
mouse.Icon ="rbxasset://textures\\MaterialCursor.png"
selectionBox = Instance.new("SelectionBox")
selectionBox.Color = BrickColor.Yellow()
selectionBox.Adornee = nil
selectionBox.Parent = player.PlayerGui
selectionLasso = Instance.new("SelectionPartLasso")
selectionLasso.Name = "Model Material Lasso"
selectionLasso.Humanoid = character.Humanoid
selectionLasso.Parent = game.workspace
selectionLasso.Part = nil
selectionLasso.Visible = true
selectionLasso.archivable = false
selectionLasso.Color = BrickColor.Green()
menu = createMaterialMenu()
menu.Parent = game.Players.LocalPlayer.PlayerGui
end
function onUnequippedLocal()
if button1DownCon then button1DownCon:disconnect() end
if mouseMoveCon then mouseMoveCon:disconnect() end
for i = 1, #downCons do
downCons[i]:disconnect()
end
downCons = {}
menu:remove()
Tool.TextureId = origTexture
if selectionBox then selectionBox:Remove() end
if selectionLasso then selectionLasso:Remove() end
end
script.Active.Changed:connect(function(prop)
if script.Active.Value == true then
onEquippedLocal(Tool.Mouse.Value)
else
onUnequippedLocal()
end
end)
-
Active
false
-
CurrentMaterial
Plastic
-
false
Resize
-- basic functions
function waitForChild(instance, name)
while not instance:findFirstChild(name) do
instance.ChildAdded:wait()
end
end
local Tool = script.Parent
waitForChild(Tool.Resize,"Active")
enabled = true
local origTexture = Tool.TextureId
game:GetService("ContentProvider"):Preload("rbxasset://icons/resize_sel.png")
local selectionBox
local selectionLasso
local handles
local previousDistance
local needsCursor = true
-- Wether a handle is being dragged, true if it is and false if not.
local isDragging = false
-- Hold the anchor state a piece was in when dragging started.
local anchorState = false
local currMouseTarget
local connections = {}
function onHandlesDown(normal)
previousDistance = 0
end
function onHandlesDrag(normal, distance)
if handles.Adornee then
local delta = distance - previousDistance
if math.abs(delta) >= handles.Adornee.ResizeIncrement then
local sizeDelta = math.floor(delta / handles.Adornee.ResizeIncrement + 0.5) * handles.Adornee.ResizeIncrement
-- Keep the piece from falling while resizing.
-- Auto join the piece to other pieces.
if not isDragging then
isDragging = true
anchorState = handles.Adornee.Anchored
handles.Adornee.Anchored = true
end
game.JointsService:SetJoinAfterMoveInstance(handles.Adornee)
if handles.Adornee:Resize(normal, sizeDelta) then
previousDistance = distance
end
game.JointsService:CreateJoinAfterMoveJoints()
game.JointsService:SetJoinAfterMoveInstance(nil)
end
end
end
function onButton1Down(mouse)
local success = pcall(function() theMouse = mouse.Target end)
if success then
if canSelect(mouse.Target) then
selectionBox.Adornee = mouse.Target
selectionLasso.Part = mouse.Target
handles.Adornee = mouse.Target
handles.Faces = mouse.Target.ResizeableFaces
else
selectionBox.Adornee = nil
selectionLasso.Part = nil
handles.Adornee = nil
end
end
end
function mouseTargetChanged(mouse)
if canSelect(mouse.Target) then
if needsCursor then
mouse.Icon ="rbxasset://textures\\DragCursor.png"
needsCursor = false
end
else
needsCursor = true
mouse.Icon = ""
end
end
local function isPartOfModel(object)
if object and object ~= game.Workspace and object:IsA("Model") then
return true
elseif not object or object == game.Workspace then
return false
else
return isPartOfModel(object.Parent)
end
end
function canSelect(object)
local isModel = isPartOfModel(object)
return object and object:IsA("BasePart") and not object.Locked and not isPartOfModel(object)
end
function onEquippedLocal(mouse)
currMouseTarget = nil
table.insert(connections,mouse.Button1Down:connect(function() onButton1Down(mouse) end) )
-- Track mouse up since up won't happen for the handle unless the mouse is over the handle.
table.insert(connections,mouse.Button1Up:connect(function()
if isDragging then
handles.Adornee.Anchored = anchorState
isDragging = false
end
end) )
table.insert(connections, mouse.Move:connect(function()
if currMouseTarget ~= mouse.Target then
mouseTargetChanged(mouse)
currMouseTarget = mouse.Target
end
end)
)
local character = script.Parent.Parent
local player = game.Players:GetPlayerFromCharacter(character)
selectionBox = Instance.new("SelectionBox")
selectionBox.Color = BrickColor.Blue()
selectionBox.Adornee = nil
selectionBox.Parent = player.PlayerGui
selectionLasso = Instance.new("SelectionPartLasso")
selectionLasso.Name = "Model Delete Lasso"
selectionLasso.Humanoid = character.Humanoid
selectionLasso.Parent = game.workspace
selectionLasso.Part = nil
selectionLasso.Visible = true
selectionLasso.archivable = false
selectionLasso.Color = BrickColor.Red()
handles = Instance.new("Handles")
handles.Color = BrickColor.Blue()
handles.Adornee = nil
handles.MouseDrag:connect(onHandlesDrag)
handles.MouseButton1Down:connect(onHandlesDown)
handles.Parent = player.PlayerGui
end
function onUnequippedLocal()
Tool.TextureId = origTexture
selectionBox:Remove()
selectionLasso:Remove()
handles:Remove()
for i = 1, #connections do
if connections[i] then connections[i]:disconnect() end
end
connections = {}
end
script.Active.Changed:connect(function(prop)
if script.Active.Value == true then
onEquippedLocal(Tool.Mouse.Value)
else
onUnequippedLocal()
end
end)
-
Active
false
-
false
Surface
-- basic functions
function waitForChild(instance, name)
while not instance:findFirstChild(name) do
instance.ChildAdded:wait()
end
end
local Tool = script.Parent
local menu
waitForChild(Tool.Surface,"Active")
waitForChild(Tool.Surface,"CurrentSurface")
enabled = true
local origTexture = Tool.TextureId
local localAssetBase = "rbxasset://textures/ui/"
game:GetService("ContentProvider"):Preload("rbxasset://icons/surface_sel.png")
local selectionSurface
local selectionLasso
local currentSurfaceButton = nil
local mouseMoveCon, button1DownCon
local conArray = {}
function setSelectionSurface(part, surface)
unsetSelectionSurface()
selectionSurface.Adornee = part
selectionSurface.TargetSurface = surface
selectionLasso.Part = part
end
function unsetSelectionSurface()
selectionSurface.Adornee = nil
selectionLasso.Part = nil
end
local SurfaceEnum = {}
SurfaceEnum["Smooth"] = Enum.SurfaceType.Smooth
SurfaceEnum["Studs"] = Enum.SurfaceType.Studs
SurfaceEnum["Inlet"] = Enum.SurfaceType.Inlet
SurfaceEnum["Universal"] = Enum.SurfaceType.Universal
SurfaceEnum["Glue"] = Enum.SurfaceType.Glue
SurfaceEnum["Weld"] = Enum.SurfaceType.Weld
SurfaceEnum["Hinge"] = Enum.SurfaceType.Hinge
SurfaceEnum["Motor"] = Enum.SurfaceType.Motor
function canSelectObject(part, surface)
return part and not (part.Locked) and part:IsA("BasePart") and (part.Position - Tool.Parent.Head.Position).Magnitude < 60 and
(not(part:IsA("WedgePart")) or surface ~= Enum.NormalId.Front)
end
function on3dMouseMove(mouse)
local part = mouse.Target
local surface = mouse.TargetSurface
if canSelectObject(part, surface) then
setSelectionSurface(part, surface)
else
unsetSelectionSurface()
end
end
function on3dButton1Down(mouse)
local part = selectionSurface.Adornee
if part then
local normalId = selectionSurface.TargetSurface
local surface = Tool.Surface.CurrentSurface.Value
if surface == nil then return end
--Apply the selected surface to the current parts
if normalId == Enum.NormalId.Top then
part.TopSurface = surface
elseif normalId == Enum.NormalId.Bottom then
elseif normalId == Enum.NormalId.Front then
part.BottomSurface = surface
part.FrontSurface = surface
elseif normalId == Enum.NormalId.Back then
part.BackSurface = surface
elseif normalId == Enum.NormalId.Left then
part.LeftSurface = surface
elseif normalId == Enum.NormalId.Right then
part.RightSurface = surface
end
end
end
function createSurfaceMenu()
local surfaceGui = Instance.new("ScreenGui")
surfaceGui.Name = "SurfaceGui"
local surfaceMenu = Instance.new("ImageLabel")
surfaceMenu.Name = "SurfaceMenu"
surfaceMenu.Position = UDim2.new(0,0,1,-400)
surfaceMenu.Size = UDim2.new(0,150,0,300)
surfaceMenu.BackgroundTransparency = 1
surfaceMenu.ZIndex = 2
surfaceMenu.Image = localAssetBase .. "SurfaceMenu.png"
surfaceMenu.Parent = surfaceGui
textures = {"Smooth", "Studs", "Inlets", "Universal", "Glue", "Weld", "Hinge", "Motor"}
current = 1
local surfaceButtons = {}
local surfaceButton = Instance.new("ImageButton")
surfaceButton.BackgroundTransparency = 1
surfaceButton.Size = UDim2.new(0.400000003, 0,0.19, 0)
surfaceButton.ZIndex = 4
local selection = Instance.new("Frame")
selection.Name = "Selection"
selection.BorderSizePixel = 0
selection.BackgroundColor3 = Color3.new(1,1,1)
selection.BackgroundTransparency = 1
selection.ZIndex = 3
selection.Size = UDim2.new(1.1,0,1.1,0)
selection.Position = UDim2.new(-0.05,0,-0.05,0)
selection.Parent = surfaceButton
local function getTextureAndName(button)
if current > #textures then
button:remove()
return false
end
button.Image = localAssetBase .. textures[current] .. ".png"
if textures[current] == "Inlets" then --nice hack to adjust for inconsistent namings
button.Name = "Inlet"
else
button.Name = textures[current]
end
current = current + 1
return true
end
local ySpacing = 0.14
local xSpacing = 0.07
for i = 1,4 do
for j = 1,2 do
local button = surfaceButton:clone()
button.Position = UDim2.new((j -1)/2.2 + xSpacing,0,ySpacing + (i - 1)/4.6,0)
getTextureAndName(button)
button.Parent = surfaceMenu
table.insert(surfaceButtons,button)
end
end
for i = 1, #surfaceButtons do
local newCon = surfaceButtons[i].MouseButton1Click:connect(function()
Tool.Surface.CurrentSurface.Value = surfaceButtons[i].Name
if currentSurfaceButton then
if currentSurfaceButton:FindFirstChild("Selection") then
currentSurfaceButton.Selection.BackgroundTransparency = 1
end
end
currentSurfaceButton = surfaceButtons[i]
surfaceButtons[i].Selection.BackgroundTransparency = 0
end)
local enterCon = surfaceButtons[i].MouseEnter:connect(function()
surfaceButtons[i].Selection.BackgroundTransparency = 0
end)
local leaveCon = surfaceButtons[i].MouseLeave:connect(function()
if surfaceButtons[i] ~= currentSurfaceButton then surfaceButtons[i].Selection.BackgroundTransparency = 1 end
end)
table.insert(conArray,newCon)
table.insert(conArray,enterCon)
table.insert(conArray,leaveCon)
end
return surfaceGui
end
function onEquippedLocal(mouse)
Tool.TextureId = "rbxasset://icons/surface_sel.png"
local character = script.Parent.Parent
local player = game.Players:GetPlayerFromCharacter(character)
mouseMoveCon = mouse.Move:connect(function() on3dMouseMove(mouse) end)
button1DownCon = mouse.Button1Down:connect(function() on3dButton1Down(mouse) end)
selectionSurface = Instance.new("SurfaceSelection")
selectionSurface.Color = BrickColor.Red()
selectionSurface.Adornee = nil
selectionSurface.Parent = player.PlayerGui
selectionLasso = Instance.new("SelectionPartLasso")
selectionLasso.Name = "Model Surface Lasso"
selectionLasso.Humanoid = character.Humanoid
selectionLasso.Parent = game.workspace
selectionLasso.Part = nil
selectionLasso.Visible = true
selectionLasso.archivable = false
selectionLasso.Color = BrickColor.Yellow()
menu = createSurfaceMenu()
menu.Parent = game.Players.LocalPlayer.PlayerGui
end
function onUnequippedLocal()
if mouseMoveCon then mouseMoveCon:disconnect() end
if button1DownCon then button1DownCon:disconnect() end
for i = 1, #conArray do
if conArray[i] then conArray[i]:disconnect() end
end
conArray = {}
menu:remove()
Tool.TextureId = origTexture
if selectionBox then selectionBox:Remove() end
if selectionLasso then selectionLasso:Remove() end
if selectionSurface then selectionSurface:Remove() end
end
script.Active.Changed:connect(function(prop)
if script.Active.Value == true then
onEquippedLocal(Tool.Mouse.Value)
else
onUnequippedLocal()
end
end)
-
Active
false
-
CurrentSurface
Smooth
-
Mouse
[null]
-
false
Dragger
-- basic functions
function waitForChild(instance, name)
while not instance:findFirstChild(name) do
instance.ChildAdded:wait()
end
end
local Tool = script.Parent
waitForChild(Tool.Dragger, "Active")
local gui = nil
local connections = {}
function deactivateTool(script)
local enable = script:FindFirstChild("Active")
if enable and enable:IsA("BoolValue") then
enable.Value = false
end
end
function deactivateAllTools()
local toolChildren = script:GetChildren()
for i = 1, #toolChildren do
if toolChildren[i]:IsA("BaseScript") and toolChildren[i] ~= script then
deactivateTool(toolChildren[i])
end
end
end
function switchGrid(type)
deactivateAllTools()
wait()
if type == "1" then
script.OldDragger.Active.Value = true
gui.DraggerButton.Selected = true
gui.Dragger4xButton.Selected = false
else
script.NewDragger.Active.Value = true
gui.DraggerButton.Selected = false
gui.Dragger4xButton.Selected = true
end
end
function makeTextButton(buttonName, text, position, parent)
local button = Instance.new("TextButton")
button.Name = buttonName
button.Style = Enum.ButtonStyle.RobloxButton
button.Size = UDim2.new(0,100,0,40)
if position then button.Position = position end
button.Parent = parent
button.Text = text
button.Font = Enum.Font.ArialBold
button.FontSize = Enum.FontSize.Size18
button.TextColor3 = Color3.new(1,1,1)
return button
end
function makeDraggerGui()
local draggerGui = Instance.new("ScreenGui")
draggerGui.Name = "DraggerGui"
local draggerButton = makeTextButton("DraggerButton","1x1 Grid",UDim2.new(0.5,-100,0,0),draggerGui)
local dragger4xButton = makeTextButton("Dragger4xButton","4x4 Grid",UDim2.new(0.5,0,0,0),draggerGui)
local con = draggerButton.MouseButton1Click:connect(function() switchGrid("1") end)
local con2 = dragger4xButton.MouseButton1Click:connect(function() switchGrid("4") end)
table.insert(connections,con)
table.insert(connections,con2)
return draggerGui
end
function onEquippedLocal(mouse)
Tool.Mouse.Value = mouse
if not gui then
gui = makeDraggerGui()
end
gui.Parent = game.Players.LocalPlayer.PlayerGui
script.NewDragger.Active.Value = true
gui.Dragger4xButton.Selected = true
end
function onUnequippedLocal()
for i = 1, #connections do
connections[i]:disconnect()
end
connections = {}
gui:remove()
gui = nil
deactivateAllTools()
end
script.Active.Changed:connect(function(prop)
if script.Active.Value == true then
onEquippedLocal(Tool.Mouse.Value)
else
onUnequippedLocal()
end
end)
-
false
OldDragger
-- basic functions
function waitForChild(instance, name)
while not instance:findFirstChild(name) do
instance.ChildAdded:wait()
end
end
local Tool = script.Parent.Parent
waitForChild(Tool.Dragger.OldDragger, "Active")
enabled = true
local origTexture = Tool.TextureId
game:GetService("ContentProvider"):Preload("rbxasset://icons/freemove_sel.png")
local selectionBox
local currentSelection
local currentSelectionColors = {}
local selectionLasso
local inGui = false
local inPalette = false
local connections = {}
function canSelectObject(part)
return part and not (part.Locked) and (part.Position - Tool.Parent.Head.Position).Magnitude < 60
end
function findModel(part)
while part ~= nil do
if part:IsA("Model") and part ~= game.Workspace then
return part
elseif part == game.Workspace then
return nil
end
part = part.Parent
end
return nil
end
function startDrag(mousePart, hitPoint, collection)
dragger = Instance.new("Dragger")
pcall(function() dragger:MouseDown(mousePart, hitPoint, collection) end)
end
function collectBaseParts(object, collection)
if object == nil then return end
if object:IsA("BasePart") then
collection[#collection+1] = object
end
for index,child in pairs(object:GetChildren()) do
collectBaseParts(child, collection)
end
end
function onMouseDown(mouse)
mouse.Icon ="rbxasset://textures\\GrabRotateCursor.png"
local part = mouse.Target
if canSelectObject(part) then
local hitPoint = mouse.Hit:toObjectSpace(part.CFrame).p
if trySelection(part) then
local instances = {}
collectBaseParts(currentSelection, instances)
startDrag(part, hitPoint, instances)
return
end
end
onMouseUp(mouse)
end
function onMouseUp(mouse)
mouse.Icon ="rbxasset://textures\\GrabCursor.png"
if dragger ~= nil then
pcall(function() dragger:MouseUp() end)
dragger = nil
end
end
function trySelection(part)
if canSelectObject(part) then
selectionLasso.Part = part
local model = findModel(part)
if model then
return setSelection(model)
else
return setSelection(part)
end
else
clearSelection()
return false
end
end
function onKeyDown(key)
if dragger ~= nil then
if key == 'R' or key == 'r' then
dragger:AxisRotate(Enum.Axis.Y)
elseif key == 'T' or key == 't' then
dragger:AxisRotate(Enum.Axis.Z)
end
end
end
local alreadyMoving
function onMouseMove(mouse)
if alreadyMoving then
return
end
alreadyMoving = true
if dragger ~= nil then
pcall(function() dragger:MouseMove(mouse.UnitRay) end)
else
trySelection(mouse.Target)
end
alreadyMoving = false
end
function saveSelectionColor(instance)
if instance:IsA("BasePart") then
currentSelectionColors[instance] = instance.BrickColor
if instance.BrickColor == BrickColor.Blue() then
instance.BrickColor = BrickColor.new("Deep blue")
else
instance.BrickColor = BrickColor.Blue()
end
end
local children = instance:GetChildren()
if children then
for pos, child in pairs(children) do
saveSelectionColor(child)
end
end
end
function setSelection(partOrModel)
if partOrModel ~= currentSelection then
clearSelection()
currentSelection = partOrModel
saveSelectionColor(currentSelection)
selectionBox.Adornee = currentSelection
return true
else
if currentSelection ~= nil then
return true
end
end
return false
end
function clearSelection()
if currentSelection ~= nil then
for part, color in pairs(currentSelectionColors) do
part.BrickColor = color
end
selectionBox.Adornee = nil
end
currentSelectionColors = {}
currentSelection = nil
if(selectionLasso) then
selectionLasso.Part = nil
end
if(selectionBox) then
selectionBox.Adornee = nil
end
end
function onEquippedLocal(mouse)
wait(0.1)
Tool.TextureId = "rbxasset://icons/freemove_sel.png"
local character = script.Parent.Parent
local player = game.Players:GetPlayerFromCharacter(character)
guiMain = Instance.new("ScreenGui")
guiMain.Parent = game.Players.LocalPlayer.PlayerGui
inGui = false
inPalette = false
mouse.Icon ="rbxasset://textures\\GrabCursor.png"
local con = mouse.Button1Down:connect(function() onMouseDown(mouse) end)
table.insert(connections,con)
con = mouse.Button1Up:connect(function() onMouseUp(mouse) end)
con = table.insert(connections,con)
con = mouse.Move:connect(function() onMouseMove(mouse) end)
table.insert(connections,con)
con = mouse.KeyDown:connect(function(string) onKeyDown(string) end)
table.insert(connections,con)
selectionBox = Instance.new("SelectionBox")
selectionBox.Name = "Model Delete Selection"
selectionBox.Color = BrickColor.Blue()
selectionBox.Adornee = nil
selectionBox.Parent = game.Players.LocalPlayer.PlayerGui
selectionLasso = Instance.new("SelectionPartLasso")
selectionLasso.Name = "Model Drag Lasso"
selectionLasso.Humanoid = game.Players.LocalPlayer.Character.Humanoid
selectionLasso.archivable = false
selectionLasso.Visible = true
selectionLasso.Parent = game.workspace
selectionLasso.Color = BrickColor.Blue()
alreadyMoving = false
end
function onUnequippedLocal()
for i = 1, #connections do
connections[i]:disconnect()
end
connections = {}
Tool.TextureId = origTexture
clearSelection()
selectionBox:Remove()
selectionLasso:Remove()
end
script.Active.Changed:connect(function()
if script.Active.Value then
onEquippedLocal(Tool.Mouse.Value)
else
onUnequippedLocal()
end
end)
-
Active
false
-
Active
false
-
false
NewDragger
local Tool = script.Parent.Parent
game:GetService("ContentProvider"):Preload("rbxasset://icons/freemove_sel.png")
local selectionBox
local currentSelection
local currentSelectionColors = {}
local Mouse = nil
local player = nil
local instances = {}
local maxDragDistance = 60
local connections = {}
while not Tool:FindFirstChild("ErrorBox") do Tool.ChildAdded:wait() end
local errorBox = Tool.ErrorBox
local lastTargetCFrame = nil
function canSelectObject(part)
return part and not (part.Locked) and (part.Position - script.Parent.Parent.Parent.Head.Position).Magnitude < maxDragDistance
end
function findModel(part)
while part ~= nil do
if part.className == "Model" then
return part
end
part = part.Parent
end
return nil
end
function isPart(object)
return object and (object:IsA("Part") or object:IsA("TrussPart") or object:IsA("WedgePart") or object:IsA("VehicleSeat"))
end
function positionPartsAtCFrame3(collection, aCFrame)
local insertCFrame
if collection[1]:IsA("Model") then
-- we assume model has at least one part in it; need to find first part
i = 1
while (i < (#collection[1]:GetChildren()) and not isPart(collection[1]:GetChildren()[i])) do
i = i + 1
end
insertCFrame = collection[1]:GetChildren()[i].CFrame
for i, object in pairs(collection[1]:GetChildren()) do
if isPart(object) then
local posPartInWorld = object.Position
local posPart1InWorld = insertCFrame.p
local newPosPartInWorld = posPartInWorld - posPart1InWorld + aCFrame.p
local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = object.CFrame:components()
object.CFrame = CFrame.new(newPosPartInWorld.x, newPosPartInWorld.y, newPosPartInWorld.z, R00, R01, R02, R10, R11, R12, R20, R21, R22)
end
end
else
collection[1].CFrame = aCFrame
end
end
function getBoundingBox2(partOrModel)
-- for models, the bounding box is defined as the minimum and maximum individual part bounding boxes
-- relative to the first part's coordinate frame.
local minVec = Vector3.new(math.huge, math.huge, math.huge)
local maxVec = Vector3.new(-math.huge, -math.huge, -math.huge)
if isPart(partOrModel) then
minVec = -0.5 * partOrModel.Size
maxVec = -minVec
elseif partOrModel:IsA("Terrain") then
minVec = Vector3.new(-2, -2, -2)
maxVec = Vector3.new(2, 2, 2)
else
local part1 = partOrModel:GetChildren()[1]
for i, object in pairs(partOrModel:GetChildren()) do
if isPart(object) then
boxMinInWorld = object.CFrame:pointToWorldSpace(-0.5 * object.Size)
boxMinInPart1 = part1.CFrame:pointToObjectSpace(boxMinInWorld)
boxMaxInWorld = object.CFrame:pointToWorldSpace(0.5 * object.Size)
boxMaxInPart1 = part1.CFrame:pointToObjectSpace(boxMaxInWorld)
local minX = minVec.x
local minY = minVec.y
local minZ = minVec.z
local maxX = maxVec.x
local maxY = maxVec.y
local maxZ = maxVec.z
if boxMinInPart1.x < minVec.x then
minX = boxMinInPart1.x
end
if boxMinInPart1.y < minVec.y then
minY = boxMinInPart1.y
end
if boxMinInPart1.z < minVec.z then
minZ = boxMinInPart1.z
end
if boxMaxInPart1.x < minX then
minX = boxMaxInPart1.x
end
if boxMaxInPart1.y < minY then
minY = boxMaxInPart1.y
end
if boxMaxInPart1.z < minZ then
minZ = boxMaxInPart1.z
end
if boxMinInPart1.x > maxVec.x then
maxX = boxMinInPart1.x
end
if boxMinInPart1.y > maxVec.y then
maxY = boxMinInPart1.y
end
if boxMinInPart1.z > maxVec.z then
maxZ = boxMinInPart1.z
end
if boxMaxInPart1.x > maxX then
maxX = boxMaxInPart1.x
end
if boxMaxInPart1.y > maxY then
maxY = boxMaxInPart1.y
end
if boxMaxInPart1.z > maxZ then
maxZ = boxMaxInPart1.z
end
minVec = Vector3.new(minX, minY, minZ)
maxVec = Vector3.new(maxX, maxY, maxZ)
end
end
end
return minVec, maxVec
end
-- function to do the same as above, but in world coordinates (really only used for region3-based bounds-checking)
function getBoundingBoxInWorldCoordinates(partOrModel)
local minVec = Vector3.new(math.huge, math.huge, math.huge)
local maxVec = Vector3.new(-math.huge, -math.huge, -math.huge)
if partOrModel:IsA("Part") or partOrModel:IsA("WedgePart") or partOrModel:IsA("TrussPart")then
vec1 = partOrModel.CFrame:pointToWorldSpace(-0.5 * partOrModel.Size)
vec2 = partOrModel.CFrame:pointToWorldSpace(0.5 * partOrModel.Size)
minVec = Vector3.new(math.min(vec1.X, vec2.X), math.min(vec1.Y, vec2.Y), math.min(vec1.Z, vec2.Z))
maxVec = Vector3.new(math.max(vec1.X, vec2.X), math.max(vec1.Y, vec2.Y), math.max(vec1.Z, vec2.Z))
elseif partOrModel:IsA("Terrain") then
-- we shouldn't have to deal with this case
--minVec = Vector3.new(-2, -2, -2)
--maxVec = Vector3.new(2, 2, 2)
else
local part1 = partOrModel:GetChildren()[1]
for i, object in pairs(partOrModel:GetChildren()) do
if (object:IsA("Part") or object:IsA("WedgePart") or object:IsA("TrussPart")) then
boxMinInWorld = object.CFrame:pointToWorldSpace(-0.5 * object.Size)
boxMinInPart1 = part1.CFrame:pointToObjectSpace(boxMinInWorld)
boxMaxInWorld = object.CFrame:pointToWorldSpace(0.5 * object.Size)
boxMaxInPart1 = part1.CFrame:pointToObjectSpace(boxMaxInWorld)
local minX = minVec.x
local minY = minVec.y
local minZ = minVec.z
local maxX = maxVec.x
local maxY = maxVec.y
local maxZ = maxVec.z
if boxMinInWorld.x < minVec.x then
minX = boxMinInWorld.x
end
if boxMinInWorld.y < minVec.y then
minY = boxMinInWorld.y
end
if boxMinInWorld.z < minVec.z then
minZ = boxMinInWorld.z
end
if boxMaxInWorld.x < minX then
minX = boxMaxInWorld.x
end
if boxMaxInWorld.y < minY then
minY = boxMaxInWorld.y
end
if boxMaxInWorld.z < minZ then
minZ = boxMaxInWorld.z
end
if boxMinInWorld.x > maxVec.x then
maxX = boxMinInWorld.x
end
if boxMinInWorld.y > maxVec.y then
maxY = boxMinInWorld.y
end
if boxMinInWorld.z > maxVec.z then
maxZ = boxMinInWorld.z
end
if boxMaxInWorld.x > maxX then
maxX = boxMaxInWorld.x
end
if boxMaxInWorld.y > maxY then
maxY = boxMaxInWorld.y
end
if boxMaxInWorld.z > maxZ then
maxZ = boxMaxInWorld.z
end
minVec = Vector3.new(minX, minY, minZ)
maxVec = Vector3.new(maxX, maxY, maxZ)
end
end
end
return minVec, maxVec
end
function getTargetPartBoundingBox(targetPart)
if targetPart.Parent:FindFirstChild("RobloxModel") ~= nil then
return getBoundingBox2(targetPart.Parent)
else
return getBoundingBox2(targetPart)
end
end
function getMouseTargetCFrame(targetPart)
if targetPart.Parent:FindFirstChild("RobloxModel") ~= nil then
return targetPart.Parent:GetChildren()[1].CFrame
else
return targetPart.CFrame
end
end
function getClosestAlignedWorldDirection(aVector3InWorld)
local xDir = Vector3.new(1,0,0)
local yDir = Vector3.new(0,1,0)
local zDir = Vector3.new(0,0,1)
local xDot = aVector3InWorld.x * xDir.x + aVector3InWorld.y * xDir.y + aVector3InWorld.z * xDir.z
local yDot = aVector3InWorld.x * yDir.x + aVector3InWorld.y * yDir.y + aVector3InWorld.z * yDir.z
local zDot = aVector3InWorld.x * zDir.x + aVector3InWorld.y * zDir.y + aVector3InWorld.z * zDir.z
if math.abs(xDot) > math.abs(yDot) and math.abs(xDot) > math.abs(zDot) then
if xDot > 0 then
return 0
else
return 3
end
elseif math.abs(yDot) > math.abs(xDot) and math.abs(yDot) > math.abs(zDot) then
if yDot > 0 then
return 1
else
return 4
end
else
if zDot > 0 then
return 2
else
return 5
end
end
end
function findConfigAtMouseTarget(collection)
-- *Critical Assumption* :
-- This function assumes the target CF axes are orthogonal with the target bounding box faces
-- And, it assumes the insert CF axes are orthongonal with the insert bounding box faces
-- Therefore, insertion will not work with angled faces on wedges or other "non-block" parts, nor
-- will it work for parts in a model that are not orthogonally aligned with the model's CF.
local grid = 4.0
local admissibleConfig = false
local targetConfig = CFrame.new(0,0,0)
local minBB, maxBB = getBoundingBox2(collection[1])
local diagBB = maxBB - minBB
local insertCFrame
if collection[1]:IsA("Model") then
i = 1
while (i < (#collection[1]:GetChildren()) and not isPart(collection[1]:GetChildren()[i])) do
i = i + 1
end
insertCFrame = collection[1]:GetChildren()[i].CFrame
else
insertCFrame = collection[1].CFrame
end
Mouse.TargetFilter = collection[1]
local targetPart = Mouse.Target
if targetPart == nil then
return admissibleConfig, targetConfig
end
-- test mouse hit location
local minBBTarget, maxBBTarget = getTargetPartBoundingBox(targetPart)
local diagBBTarget = maxBBTarget - minBBTarget
local targetCFrame = getMouseTargetCFrame(targetPart)
local hitCFrame = Mouse.Hit
local mouseHitInWorld = hitCFrame.p
--local targetVectorInWorld = targetCFrame:vectorToWorldSpace(Vector3.FromNormalId(Mouse.TargetSurface))
if targetPart:IsA("Terrain") then
if not cluster then cluster = game.Workspace.Terrain end
-- the prefer solid is messing things up very slightly!! (because the TargetSurface stays correct when the cells are shifted very slightly prematurely)
cellID = cluster:WorldToCellPreferSolid(mouseHitInWorld)
targetCFrame = CFrame.new(cluster:CellCenterToWorld(cellID.x, cellID.y, cellID.z))
end
local targetVectorInWorld = targetCFrame:vectorToWorldSpace(Vector3.FromNormalId(Mouse.TargetSurface))
local mouseHitInTarget = targetCFrame:pointToObjectSpace(mouseHitInWorld)
local targetRefPointInTarget
local clampToSurface
if getClosestAlignedWorldDirection(targetVectorInWorld) == 0 then
targetRefPointInTarget = targetCFrame:vectorToObjectSpace(Vector3.new(1, -1, 1))
insertRefPointInInsert = insertCFrame:vectorToObjectSpace(Vector3.new(-1, -1, 1))
clampToSurface = Vector3.new(0,1,1)
elseif getClosestAlignedWorldDirection(targetVectorInWorld) == 3 then
targetRefPointInTarget = targetCFrame:vectorToObjectSpace(Vector3.new(-1, -1, -1))
insertRefPointInInsert = insertCFrame:vectorToObjectSpace(Vector3.new(1, -1, -1))
clampToSurface = Vector3.new(0,1,1)
elseif getClosestAlignedWorldDirection(targetVectorInWorld) == 1 then
targetRefPointInTarget = targetCFrame:vectorToObjectSpace(Vector3.new(-1, 1, 1))
insertRefPointInInsert = insertCFrame:vectorToObjectSpace(Vector3.new(-1, -1, 1))
clampToSurface = Vector3.new(1,0,1)
elseif getClosestAlignedWorldDirection(targetVectorInWorld) == 4 then
targetRefPointInTarget = targetCFrame:vectorToObjectSpace(Vector3.new(-1, -1, 1))
insertRefPointInInsert = insertCFrame:vectorToObjectSpace(Vector3.new(-1, 1, 1))
clampToSurface = Vector3.new(1,0,1)
elseif getClosestAlignedWorldDirection(targetVectorInWorld) == 2 then
targetRefPointInTarget = targetCFrame:vectorToObjectSpace(Vector3.new(-1, -1, 1))
insertRefPointInInsert = insertCFrame:vectorToObjectSpace(Vector3.new(-1, -1, -1))
clampToSurface = Vector3.new(1,1,0)
else
targetRefPointInTarget = targetCFrame:vectorToObjectSpace(Vector3.new(1, -1, -1))
insertRefPointInInsert = insertCFrame:vectorToObjectSpace(Vector3.new(1, -1, 1))
clampToSurface = Vector3.new(1,1,0)
end
targetRefPointInTarget = targetRefPointInTarget * (0.5 * diagBBTarget) + 0.5 * (maxBBTarget + minBBTarget)
insertRefPointInInsert = insertRefPointInInsert * (0.5 * diagBB) + 0.5 * (maxBB + minBB)
-- To Do: For cases that are not aligned to the world grid, account for the minimal rotation
-- needed to bring the Insert part(s) into alignment with the Target Part
-- Apply the rotation here
local delta = mouseHitInTarget - targetRefPointInTarget
local deltaClamped = Vector3.new(grid * math.modf(delta.x/grid), grid * math.modf(delta.y/grid), grid * math.modf(delta.z/grid))
deltaClamped = deltaClamped * clampToSurface
local targetTouchInTarget = deltaClamped + targetRefPointInTarget
local TargetTouchRelToWorld = targetCFrame:pointToWorldSpace(targetTouchInTarget)
local InsertTouchInWorld = insertCFrame:vectorToWorldSpace(insertRefPointInInsert)
local posInsertOriginInWorld = TargetTouchRelToWorld - InsertTouchInWorld
local x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 = insertCFrame:components()
targetConfig = CFrame.new(posInsertOriginInWorld.x, posInsertOriginInWorld.y, posInsertOriginInWorld.z, R00, R01, R02, R10, R11, R12, R20, R21, R22)
admissibleConfig = true
return admissibleConfig, targetConfig
end
function startDrag(mousePart, hitPoint, collection)
lastTargetCFrame = nil
dragger = Instance.new("Dragger")
pcall(function() dragger:MouseDown(mousePart, hitPoint, collection) end)
end
function collectBaseParts(object, collection)
if object == nil then return end
--if object:IsA("BasePart") then
if isPart(object) then
collection[#collection+1] = object
end
for index,child in pairs(object:GetChildren()) do
collectBaseParts(child, collection)
end
end
function onMouseDown(mouse)
mouse.Icon ="rbxasset://textures\\GrabRotateCursor.png"
local part = mouse.Target
if canSelectObject(part) then
local hitPoint = mouse.Hit:toObjectSpace(part.CFrame).p
if trySelection(part) then
instances = {}
game.JointsService:ClearJoinAfterMoveJoints()
game.JointsService:SetJoinAfterMoveInstance(mouse.Target)
collectBaseParts(currentSelection, instances)
startDrag(part, hitPoint, instances)
return
end
end
end
-- stampability-checking functions (copied from StampScript)
function flashRedBox(targetModel)
if not player then return end
errorBox.Parent = player.PlayerGui
errorBox.Adornee = targetModel
delay(0,function()
for i = 1, 3 do
errorBox.Visible = true
wait(0.13)
errorBox.Visible = false
wait(0.13)
end
errorBox.Adornee = nil
errorBox.Parent = Tool
end)
end
-- below function should work as a Region3 query, returning true if a single cluster part is within this region
function clusterPartsInRegion(startVector, endVector)
if not cluster then return false end
local startCell = cluster:WorldToCell(startVector)
local endCell = cluster:WorldToCell(endVector)
local startX = startCell.X
local startY = startCell.Y
local startZ = startCell.Z
local endX = endCell.X
local endY = endCell.Y
local endZ = endCell.Z
if startX < cluster.MaxExtents.Min.X then startX = cluster.MaxExtents.Min.X end
if startY < cluster.MaxExtents.Min.Y then startY = cluster.MaxExtents.Min.Y end
if startZ < cluster.MaxExtents.Min.Z then startZ = cluster.MaxExtents.Min.Z end
if endX > cluster.MaxExtents.Max.X then endX = cluster.MaxExtents.Max.X end
if endY > cluster.MaxExtents.Max.Y then endY = cluster.MaxExtents.Max.Y end
if endZ > cluster.MaxExtents.Max.Z then endZ = cluster.MaxExtents.Max.Z end
--print(startX, endX)
--print(startY, endY)
--print(startZ, endZ)
for x = startX, endX do
for y = startY, endY do
for z = startZ, endZ do
--if game.Workspace.Cluster:GetCell(x, y, z) > 0 then return true end
if (cluster:GetCell(x, y, z).Value) > 0 then return true end
end
end
end
return false
end
-- helper function to determine if a character can be pushed upwards by a certain amount
-- FILL THIS OUT!!! -- character is 5 studs tall, we'll check a 1.5 x 1.5 x 4.5 box around char, with center .5 studs below torsocenter
function spaceAboveCharacter(charTorso, newTorsoY)
local partsAboveChar = game.Workspace:FindPartsInRegion3(Region3.new(Vector3.new(charTorso.Position.X, newTorsoY, charTorso.Position.Z) - Vector3.new(.75, 2.75, .75), Vector3.new(charTorso.Position.X, newTorsoY, charTorso.Position.Z) + Vector3.new(.75, 1.75, .75)), charTorso.Parent, 100)
for j = 1, #partsAboveChar do
if partsAboveChar[j].CanCollide and not partsAboveChar[j]:IsDescendantOf(currentSelection) then return false end
end
if clusterPartsInRegion(Vector3.new(charTorso.Position.X, newTorsoY, charTorso.Position.Z) - Vector3.new(.75, 2.75, .75), Vector3.new(charTorso.Position.X, newTorsoY, charTorso.Position.Z) + Vector3.new(.75, 1.75, .75)) then return false end
return true
end
local insertBoundingBoxOverlapVector = Vector3.new(1, 1, 1)
function onMouseUp(mouse)
mouse.Icon ="rbxasset://textures\\GrabCursor.png"
local thingToPlace = {}
thingToPlace[1] = currentSelection
if dragger ~= nil then
local minBB, maxBB = getBoundingBoxInWorldCoordinates(currentSelection)
local configFound, targetCFrame = findConfigAtMouseTarget(thingToPlace)
if configFound then
-- don't drag into terrain
if clusterPartsInRegion(minBB+insertBoundingBoxOverlapVector, maxBB-insertBoundingBoxOverlapVector) then flashRedBox(currentSelection) return end
local blockingParts = game.Workspace:FindPartsInRegion3(Region3.new(minBB+insertBoundingBoxOverlapVector, maxBB-insertBoundingBoxOverlapVector), currentSelection, 100)
for b = 1, #blockingParts do
-- put code back here if we want to prevent dragger from dragging into other stamped models (once Region3 fix goes out)
end
local alreadyPushedUp = {}
-- if no blocking model below, then see if stamping on top of a character
for b = 1, #blockingParts do
if blockingParts[b].Parent and not alreadyPushedUp[blockingParts[b].Parent] and blockingParts[b].Parent:FindFirstChild("Humanoid") and blockingParts[b].Parent:FindFirstChild("Humanoid"):IsA("Humanoid") then
local blockingPersonTorso = blockingParts[b].Parent:FindFirstChild("Torso")
alreadyPushedUp[blockingParts[b].Parent] = true
if blockingPersonTorso then
-- if so, let's push the person upwards so they pop on top of the stamped model/part (but only if there's space above them)
local newY = maxBB.Y + 3
if spaceAboveCharacter(blockingPersonTorso, newY) then
blockingPersonTorso.CFrame = blockingPersonTorso.CFrame + Vector3.new(0, newY - blockingPersonTorso.CFrame.p.Y, 0)
else
-- if no space, we just error
flashRedBox(currentSelection)
return
end
end
end
end
Mouse.TargetFilter = nil
pcall(function() dragger:MouseUp() end)
game.JointsService:CreateJoinAfterMoveJoints()
dragger = nil
end
end
end
function trySelection(part)
if canSelectObject(part) then
local model = findModel(part)
if model then
return setSelection(model)
else
return setSelection(part)
end
else
clearSelection()
return false
end
end
function onKeyDown(key)
if dragger ~= nil then
if key == 'R' or key == 'r' then
pcall(function() dragger:AxisRotate(Enum.Axis.Y) end)
elseif key == 'T' or key == 't' then
pcall(function() dragger:AxisRotate(Enum.Axis.Z) end)
end
end
end
local alreadyMoving = false
function onMouseMove(mouse)
if alreadyMoving then
return
end
alreadyMoving = true
if dragger ~= nil then
local thingToDrag = {}
thingToDrag[1] = currentSelection
pcall(function() dragger:MouseMove(mouse.UnitRay) end)-- needed to break welds properly
configFound, targetCFrame = findConfigAtMouseTarget(thingToDrag)
if configFound then
local minBB, maxBB = getBoundingBoxInWorldCoordinates(currentSelection)
-- need to offset by distance to be dragged
local currModelCFrame
if currentSelection:IsA("Model") then
-- we assume model has at least one part in it; need to find first part
i = 1
while (i < (#currentSelection:GetChildren()) and not isPart(currentSelection:GetChildren()[i])) do
i = i + 1
end
currModelCFrame = currentSelection:GetChildren()[i].CFrame
else currModelCFrame = currentSelection.CFrame end
minBB = minBB + targetCFrame.p - currModelCFrame.p
maxBB = maxBB + targetCFrame.p - currModelCFrame.p
-- don't drag into terrain
if clusterPartsInRegion(minBB+insertBoundingBoxOverlapVector, maxBB-insertBoundingBoxOverlapVector) then
if lastTargetCFrame then positionPartsAtCFrame3(thingToDrag, lastTargetCFrame) end
alreadyMoving = false
return
end
local blockingParts = game.Workspace:FindPartsInRegion3(Region3.new(minBB+insertBoundingBoxOverlapVector, maxBB-insertBoundingBoxOverlapVector), currentSelection, 100)
for b = 1, #blockingParts do
-- put code back here if we want to prevent dragger from dragging into other stamped models (once Region3 fix goes out)
end
positionPartsAtCFrame3(thingToDrag, targetCFrame)
lastTargetCFrame = targetCFrame
end
else
trySelection(mouse.Target)
end
alreadyMoving = false
end
function saveSelectionColor(instance)
if instance:IsA("BasePart") then
currentSelectionColors[instance] = instance.BrickColor
if instance.BrickColor == BrickColor.Blue() then
instance.BrickColor = BrickColor.new("Deep blue")
else
instance.BrickColor = BrickColor.Blue()
end
end
local children = instance:GetChildren()
if children then
for pos, child in pairs(children) do
saveSelectionColor(child)
end
end
end
function setSelection(partOrModel)
if partOrModel ~= currentSelection then
clearSelection()
currentSelection = partOrModel
saveSelectionColor(currentSelection)
selectionBox.Adornee = currentSelection
return true
elseif partOrModel == nil then
clearSelection()
return false
end
return partOrModel == currentSelection
end
function clearSelection()
if currentSelection ~= nil then
for part, color in pairs(currentSelectionColors) do
part.BrickColor = color
end
selectionBox.Adornee = nil
end
currentSelectionColors = {}
currentSelection = nil
if(selectionBox) then
selectionBox.Adornee = nil
end
end
function onEquippedLocal(mouse)
Mouse = mouse
local character = script.Parent.Parent.Parent
player = game.Players:GetPlayerFromCharacter(character)
mouse.Icon ="rbxasset://textures\\GrabCursor.png"
local con = Mouse.Button1Down:connect(function() onMouseDown(Mouse) end)
table.insert(connections,con)
con = Mouse.Button1Up:connect(function() onMouseUp(Mouse) end)
con = table.insert(connections,con)
con = Mouse.Move:connect(function() onMouseMove(Mouse) end)
table.insert(connections,con)
con = Mouse.KeyDown:connect(function(string) onKeyDown(string) end)
table.insert(connections,con)
selectionBox = Instance.new("SelectionBox")
selectionBox.Name = "Model Delete Selection"
selectionBox.Color = BrickColor.Blue()
selectionBox.Adornee = nil
selectionBox.Parent = player.PlayerGui
alreadyMoving = false
end
function onUnequippedLocal()
for i = 1, #connections do
connections[i]:disconnect()
end
connections = {}
clearSelection()
selectionBox:Remove()
end
script.Active.Changed:connect(function()
if script.Active.Value then
onEquippedLocal(Tool.Mouse.Value)
else
onUnequippedLocal()
end
end)
-
Active
false
-
[null]
21
ErrorBox
0
false