User:HotThoth/NudgeScript

From Legacy Roblox Wiki
Jump to navigationJump to search
local nudgeValue = game.Lighting:FindFirstChild("Nudge")
if nudgeValue == nil then
	nudgeValue = Instance.new("Vector3Value")
	nudgeValue.Parent = game.Lighting
	nudgeValue.Name = "Nudge"
	nudgeValue.Value = Vector3.new(0,0,0)
end

local tiltAxis = game.Lighting:FindFirstChild("TiltAxis")
if tiltAxis == nil then
	tiltAxis = Instance.new("Vector3Value")
	tiltAxis.Parent = game.Lighting
	tiltAxis.Name = "TiltAxis"
	tiltAxis.Value = Vector3.new(0,1,0)
end

local tiltAngle = game.Lighting:FindFirstChild("TiltAngle")
if tiltAngle == nil then
	tiltAngle = Instance.new("NumberValue")
	tiltAngle.Parent = game.Lighting
	tiltAngle.Name = "TiltAngle"
	tiltAngle.Value = 0
end

local resetToggle = game.Lighting:FindFirstChild("ResetOrientation")
if resetToggle == nil then
	resetToggle = Instance.new("BoolValue")
	resetToggle.Parent = game.Lighting
	resetToggle.Name = "ResetOrientation"
	resetToggle.Value = false
end

local clearScriptToggle = game.Lighting:FindFirstChild("RemoveNudgeScript")
if clearScriptToggle == nil then
	clearScriptToggle = Instance.new("BoolValue")
	clearScriptToggle.Parent = game.Lighting
	clearScriptToggle.Name = "RemoveNudgeScript"
	clearScriptToggle.Value = false
end


local centroid = Vector3.new(0,0,0)
local numParts = 0
local z = Vector3.new(1,0,0) -- axis vector for rotation
local cosTheta = 1 -- cos of angle of rotation
local sinTheta = 0 -- sin of angle of rotation

--function rotateVect(v, z, cosTheta, sinTheta)
function rotateVect(v)
	return (v*cosTheta + z:Cross(v)*sinTheta + z*(z:Dot(v))*(1 - cosTheta))
end


function rotatePart(currChild, personPosition, shiftVector)
		relPosition = currChild.CFrame:vectorToObjectSpace(personPosition-currChild.Position)
		--currChild.CFrame = currChild.CFrame*CFrame.Angles(0, 0, math.pi/2)
		--currChild.CFrame = currChild.CFrame*CFrame.Angles(angleVect.X, angleVect.Y, angleVect.Z)
		axisA = currChild.CFrame:vectorToWorldSpace(Vector3.new(1,0,0))
		axisB = currChild.CFrame:vectorToWorldSpace(Vector3.new(0,1,0))
		axisC = currChild.CFrame:vectorToWorldSpace(Vector3.new(0,0,1))
		axisA = rotateVect(axisA)
		axisB = rotateVect(axisB)
		axisC = rotateVect(axisC)
		currChild.CFrame = CFrame.new(currChild.Position.X, currChild.Position.Y, currChild.Position.Z, axisA.X, axisB.X, axisC.X, axisA.Y, axisB.Y, axisC.Y, axisA.Z, axisB.Z, axisC.Z)
		relPosition = personPosition-currChild.CFrame:vectorToWorldSpace(relPosition)
		currChild.CFrame = CFrame.new(relPosition.X+shiftVector.X, relPosition.Y+shiftVector.Y, relPosition.Z+shiftVector.Z, axisA.X, axisB.X, axisC.X, axisA.Y, axisB.Y, axisC.Y, axisA.Z, axisB.Z, axisC.Z)
end



function collectPartPositions(object)
	if object == nil then return end
	if object.className == "Part" or object.className == "WedgePart" or object.className == "TrussPart" then
		numParts = numParts + 1
		centroid = centroid + object.Position
	end
	--if object.GetChildren then -- if can get children
	if object.className == "Model" or object.className == "Tool" then
		children = object:GetChildren()
		print(#children)
		for i = 1, #children do
			collectPartPositions(children[i])
		end
	end
	return
end


function resetOrientation(object, primaryPartInverseMatrix)
	if object == nil then return end
	if object.className == "Part" or object.className == "WedgePart" or object.className == "TrussPart" then
		object.CFrame = primaryPartInverseMatrix*object.CFrame
	end
	--if object.GetChildren then -- if can get children
	if object.className == "Model" or object.className == "Tool" then
		children = object:GetChildren()
		print(#children)
		for i = 1, #children do
			resetOrientation(children[i], primaryPartInverseMatrix)
		end
	end
	return
end


function tinyTilt(object)
	if object == nil then return end
if object.className == "Part" or object.className == "WedgePart" or object.className == "TrussPart" then
		--object.CFrame = object.CFrame * CFrame.Angles(vect.X, vect.Y, vect.Z)
		rotatePart(object, centroid, Vector3.new(0,0,0))
	end
	--if object.GetChildren then -- if can get children
	if object.className == "Model" or object.className == "Tool" then
		children = object:GetChildren()
		print(#children)
		for i = 1, #children do
			tinyTilt(children[i])
		end
	end
	return
end


function nudge(object, vect)
	if object == nil then return end
if object.className == "Part" or object.className == "WedgePart" or object.className == "TrussPart" then
		object.CFrame = object.CFrame + vect
	end
	--if object.GetChildren then -- if can get children
	if object.className == "Model" or object.className == "Tool" then
		children = object:GetChildren()
		print(#children)
		for i = 1, #children do
			nudge(children[i], vect)
		end
	end
	return
end


function nudgeToggleChange(property)
    if nudgeValue.Value:Dot(nudgeValue.Value) == 0 then return end

	nudgeVector = nudgeValue.Value
	nudgeValue.Value = Vector3.new(0,0,0)
	thingsToMove = game.Selection:Get()
	for i = 1, #thingsToMove do
		nudge(thingsToMove[i], nudgeVector)
	end
end

function tiltToggleChange(property)
	if tiltAngle.Value == 0 then return end
	if tiltAxis.Value:Dot(tiltAxis.Value) == 0 then return end
	
	tiltAxis.Value = tiltAxis.Value.unit

	z = tiltAxis.Value
	tAngle = tiltAngle.Value
	tiltAngle.Value = 0
	sinTheta = math.sin(math.rad(tAngle))
	cosTheta = math.cos(math.rad(tAngle))
	
	thingsToMove = game.Selection:Get()
	for i = 1, #thingsToMove do
		numParts = 0
		centroid = Vector3.new(0,0,0)
		collectPartPositions(thingsToMove[i])
		
		if numParts > 0 then
			centroid = centroid * (1/numParts)
			print(centroid)
	
			tinyTilt(thingsToMove[i])
		end
	end
	
end

function resetToggleChange(property)
	if resetToggle.Value == false then return
	else resetToggle.Value = false end

	local oldPosition = nil	
	local differenceVector = nil

	thingsToMove = game.Selection:Get()
	for i = 1, #thingsToMove do
		if thingsToMove[i].className == "Part" then
			oldPosition = thingsToMove[i].Position
			resetOrientation(thingsToMove[i], thingsToMove[i].CFrame:inverse())
			differenceVector = oldPosition - thingsToMove[i].Position
		elseif thingsToMove[i].className == "Model" or thingsToMove[i].className == "Tool" then
			local primPart = nil
			modelkids = thingsToMove[i]:GetChildren()
			for j = 1, #modelkids do
				if modelkids[j].className == "Part" then
					primPart = modelkids[j]
				end
			end
			if primPart ~= nil then 
				oldPosition = primPart.Position
				resetOrientation(thingsToMove[i], primPart.CFrame:inverse())
				differenceVector = oldPosition - primPart.Position
			end
		end
		if differenceVector ~= nil then
			nudge(thingsToMove[i], differenceVector)
			differenceVector = nil
		end
	end
end

local csConnect = nil
function clearScript(property)
	if clearScriptToggle.Value == false or csConnect == nil then return
	else clearScriptToggle.Value = false csConnect:disconnect() end

	-- remove values and toggles (connections will be killed automatically in the process)
	if nudgeValue ~= nil and nudgeValue.Parent ~= nil then nudgeValue:remove() end
	if tiltAngle ~= nil and tiltAngle.Parent ~= nil then tiltAngle:remove() end
	if tiltAxis ~= nil and tiltAxis.Parent ~= nil then tiltAxis:remove() end
	if resetToggle ~= nil and resetToggle.Parent ~= nil then resetToggle:remove() end
	if clearScriptToggle ~= nil and clearScriptToggle.Parent ~= nil then clearScriptToggle:remove() end	
end


nudgeValue.Changed:connect(nudgeToggleChange)
tiltAngle.Changed:connect(tiltToggleChange)
resetToggle.Changed:connect(resetToggleChange)
csConnect = clearScriptToggle.Changed:connect(clearScript)